keepalived-0.4.9 v0.4.9
authorAlexandre Cassen <acassen@freebox.fr>
Wed, 19 Dec 2001 18:21:03 +0000 (19:21 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:54 +0000 (10:58 +0200)
* keepalived-0.4.9 released.
* Jan Holmberg, <jan@artech.net> added a memory managment framework.
  In debug mode it is used as a memory leak buster. We can so use it
  to debug quickly memory leaks (buffer overrun, allocation errors, ...).
* Jan Holmberg and I added support to SSL. Checker SSL_GET. Can be used
  with autogenerated cert or with specific cafile, certfile, keyfile.
* Use the OpenSSL, <www.openssl.org> library for MD5 & SSL functions.
* Jan Holmberg and I Rewrote the HTTP_GET code to use full asynchronous
  stream handling. The code use a common part for HTTP/SSL stream handling.
  Review the MD5 digest buffer computation, update MD5 over received buffer.
* Patched some memory leaks in smtp handling.
* Jan Holmbarg added support to LVS FWMARK.
* Added command line option for keepalived. Used the libpopt library.
  -h, -v, -n, -d, -l, -f.
* Jan Holmberg and I added debugging facility on keepalived console.
* Added a BOOTSTRAP_DELAY of 1sec when registering checkers during
  daemon bootstrap.
* VRRP : Jan Holmberg added possibility to run an extra script when
  VRRP Instance become or leave MASTER STATE (=> using a forked process).
* Review/fine the whole code to apply cosmetics patch.
* Rewrote the genhash utility.
* Started checkers API specs.
* doc doc doc...
* keepalived-0.4.8 released.

77 files changed:
CONTRIBUTORS [new file with mode: 0644]
ChangeLog
INSTALL
Makefile
TODO
cfreader.c
cfreader.h
check.h
check_http.c
check_http.h
check_misc.c
check_misc.h
check_ssl.c [new file with mode: 0644]
check_ssl.h [new file with mode: 0644]
check_tcp.c
check_tcp.h
etc/keepalived/keepalived.conf
genhash/AUTHORS [new file with mode: 0644]
genhash/COPYING [new file with mode: 0644]
genhash/ChangeLog [new file with mode: 0644]
genhash/INSTALL [new file with mode: 0644]
genhash/Makefile
genhash/README [new file with mode: 0644]
genhash/TODO [new file with mode: 0644]
genhash/client.c [new file with mode: 0644]
genhash/client.h [new file with mode: 0644]
genhash/common.c [new file with mode: 0644]
genhash/common.h [new file with mode: 0644]
genhash/genhash.c [deleted file]
genhash/genhash.h [deleted file]
genhash/main.c [new file with mode: 0644]
genhash/main.h [new file with mode: 0644]
genhash/md5.c [deleted file]
genhash/md5.h [deleted file]
genhash/ssl.crt [new file with mode: 0644]
genhash/ssl.csr [new file with mode: 0644]
genhash/ssl.key [new file with mode: 0644]
genhash/ssl.pem [new file with mode: 0644]
ipfwwrapper.c
ipfwwrapper.h
ipvswrapper.c
ipvswrapper.h
ipwrapper.c
ipwrapper.h
layer4.c
layer4.h
libipfwc/libipfwc.c
libipfwc/libipfwc.h
main.c
main.h
md5.c [deleted file]
md5.h [deleted file]
memory.c [new file with mode: 0644]
memory.h [new file with mode: 0644]
pidfile.c
pidfile.h
samples/client.pem [new file with mode: 0644]
samples/dh1024.pem [new file with mode: 0644]
samples/keepalived.conf.SSL_GET [new file with mode: 0644]
samples/keepalived.conf.ssl [new file with mode: 0644]
samples/root.pem [new file with mode: 0644]
scheduler.c
scheduler.h
smtp.c
smtp.h
utils.c
utils.h
vrrp.c
vrrp.h
vrrp_ipaddress.c
vrrp_ipaddress.h
vrrp_ipsecah.c
vrrp_ipsecah.h
vrrp_netlink.c
vrrp_netlink.h
vrrp_scheduler.c
vrrp_scheduler.h

diff --git a/CONTRIBUTORS b/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..29a5aba
--- /dev/null
@@ -0,0 +1 @@
+Jan Holmberg <jan@artech.net>
index 433b6cb..32fb1c0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
+2001-12-10  Alexandre Cassen  <acassen@linux-vs.org>
+       * keepalived-0.4.9 released.
+       * Jan Holmberg, <jan@artech.net> added a memory managment framework.
+         In debug mode it is used as a memory leak buster. We can so use it
+         to debug quickly memory leaks (buffer overrun, allocation errors, ...).
+       * Jan Holmberg and I added support to SSL. Checker SSL_GET. Can be used
+         with autogenerated cert or with specific cafile, certfile, keyfile.
+       * Use the OpenSSL, <www.openssl.org> library for MD5 & SSL functions.
+       * Jan Holmberg and I Rewrote the HTTP_GET code to use full asynchronous
+         stream handling. The code use a common part for HTTP/SSL stream handling.
+         Review the MD5 digest buffer computation, update MD5 over received buffer.
+       * Patched some memory leaks in smtp handling.
+       * Jan Holmbarg added support to LVS FWMARK.
+       * Added command line option for keepalived. Used the libpopt library.
+         -h, -v, -n, -d, -l, -f.
+       * Jan Holmberg and I added debugging facility on keepalived console.
+       * Added a BOOTSTRAP_DELAY of 1sec when registering checkers during
+         daemon bootstrap.
+       * VRRP : Jan Holmberg added possibility to run an extra script when
+         VRRP Instance become or leave MASTER STATE (=> using a forked process).
+       * Review/fine the whole code to apply cosmetics patch.
+       * Rewrote the genhash utility.
+       * Started checkers API specs.
+       * doc doc doc...
+
 2001-11-20  Alexandre Cassen  <acassen@linux-vs.org>
-        * keepalived-0.4.8 released.
+       * 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.
diff --git a/INSTALL b/INSTALL
index 69ab723..75f1dd1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -15,9 +15,10 @@ Installation
   2. cd into the directory
   3. 'make' and 'make install'. This will install 
      keepalived into your system (binary and configuration file).
-  4. cd into genhash directory
+  4. cd into genhash directory (read the INSTALL file).
   5. 'make' and 'make install'. This will install
-     the MD5 url digest generator. You need it to configure HTTP GET check.
+     the MD5 url digest generator. You need it to configure HTTP GET check
+     and SSL GET check in order to compute MD5SUM digest etalon.
   6. link keepalived.init into your runlevel directory. On redhat systems :
      ln -s /etc/rc.d/init.d/keepalived.init /etc/rc.d/rc3.d/S99keepalived
 
@@ -33,3 +34,4 @@ Configuration
 
 
 Have fun with it !
+Alexandre
index 503f9ed..5306042 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,28 +1,32 @@
 # Makefile
 # Alexandre Cassen <acassen@linux-vs.org>
 
-EXEC= keepalived
-CC= gcc
+EXEC = keepalived
+CC = gcc
 
-KERNEL := KERNEL_2_$(shell uname -r | cut -d'.' -f2)
+KERNEL := _KRNL_2_$(shell uname -r | cut -d'.' -f2)_
 
 # To compile with debug messages uncomment the following line
-CFLAGS= -g -Wall -Wunused -DDEBUG -D$(KERNEL)
-#CFLAGS= -g -Wall -D$(KERNEL)
+CFLAGS= -g -O6 -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
+# CFLAGS= -g -Wall -O6 -D$(KERNEL) $(SSL)
 DEFS=
 
-ifeq ($(KERNEL),KERNEL_2_2)
+SSL := -lssl -lcrypto
+LIB := $(LIB) $(SSL) -lpopt
+
+ifeq ($(KERNEL),_KRNL_2_2_)
   LIB := $(LIB) libipfwc/libipfwc.a
 endif
 
 DEFS= main.h \
+       memory.h \
         scheduler.h \
         cfreader.h \
         layer4.h \
         check_tcp.h \
         check_http.h \
+        check_ssl.h \
         check_misc.h \
-        md5.h \
        vrrp.h \
        vrrp_scheduler.h \
        vrrp_netlink.h \
@@ -31,17 +35,18 @@ DEFS= main.h \
         smtp.h
 
 OBJECTS := main.o \
+       memory.o \
        utils.o \
        scheduler.o \
        cfreader.o \
        layer4.o \
        check_tcp.o \
        check_http.o \
+        check_ssl.o \
        check_misc.o \
-       md5.o \
        ipwrapper.o \
        ipvswrapper.o
-ifeq ($(KERNEL),KERNEL_2_2)
+ifeq ($(KERNEL),_KRNL_2_2_)
   OBJECTS := $(OBJECTS) ipfwwrapper.o
 endif
 OBJECTS := $(OBJECTS) \
@@ -63,16 +68,20 @@ all:        $(EXEC)
        @echo ""
        @echo "Make complete"
 
+debug: $(EXEC)
+       @echo""
+       @echo "Make complete"
+
 $(EXEC):       $(OBJECTS) $(DEFS) $(LIB)
        $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS) $(LIB)
 
-ifeq ($(KERNEL),KERNEL_2_2)
+ifeq ($(KERNEL),_KRNL_2_2_)
 libipfwc/libipfwc.a:
        cd libipfwc/ && $(MAKE) libipfwc.a
 endif
 
 subclean:
-ifeq ($(KERNEL),KERNEL_2_2)
+ifeq ($(KERNEL),_KRNL_2_2_)
        cd libipfwc/ && $(MAKE) clean
 endif
 
@@ -84,4 +93,6 @@ install:
        install -m 755 etc/rc.d/init.d/keepalived.init /etc/rc.d/init.d/
        mkdir /etc/keepalived
        install -m 644 etc/keepalived/keepalived.conf /etc/keepalived/
+       mkdir /etc/keepalived/samples
+       install -m 644 samples/* /etc/keepalived/samples/
 
diff --git a/TODO b/TODO
index 3a6ff31..2e4c982 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 * Documentation.
 * Synchronize IPVS topology with VRRP synchronization events.
 * Insert LDAP, SSL, FTP, SSH, IMAP, POP, RADIUS checkers.
-* Security auditing.
+* Replave some unfixed len strcat & sprintf
 * Add minimum configuration verification (realserver must have
   a checker defined, ...)
 * Add system verification (must have LVS support in kernel, 
index c48b002..54359c8 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: cfreader.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: cfreader.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -23,6 +23,7 @@
  */
 
 #include "cfreader.h"
+#include "memory.h"
 
 /* Global keyword structure defs */
 char *string; /* Temp read buffer */
@@ -46,6 +47,7 @@ struct keyword keywords[] = {
   {KW_PTIMEOUT,     "persistence_timeout"},
   {KW_PROTOCOL,     "protocol"},
   {KW_SSVR,         "sorry_server"},
+  {KW_FWMARK,       "fwmark"},
 
   {KW_SVR,          "real_server"},
   {KW_WEIGHT,       "weight"},
@@ -79,6 +81,14 @@ struct keyword keywords[] = {
   {KW_VRRPIPADD,    "virtual_ipaddress"},
   {KW_VRRPSYNC,     "sync_instance"},
   {KW_VRRPPREEMPT,  "preempt"},
+  {KW_VRRPDEBUG,    "debug"},
+  {KW_VRRPNOTIFY,   "notify"},
+
+  {KW_SSLPASSWORD,  "password"},
+  {KW_SSLCAFILE,    "ca"},
+  {KW_SSLCERTFILE,  "certificate"},
+  {KW_SSLKEYFILE,   "key"},
+  {KW_SSL,          "SSL"},
 
   {KW_UNKNOWN,     NULL}
 };
@@ -205,7 +215,7 @@ urls * remove_url(urls * lstptr)
   urls *t;
 
   t = (urls *)lstptr->next;
-  free(lstptr);
+  FREE(lstptr);
   return t;
 }
 
@@ -215,14 +225,14 @@ realserver * remove_svr(realserver * lstptr)
 
   t = (realserver *)lstptr->next;
 
-  if(lstptr->method->http_get != NULL) {
-    while(lstptr->method->http_get->check_urls != NULL)
-      lstptr->method->http_get->check_urls = remove_url(lstptr->method->http_get->check_urls);
-    free(lstptr->method->http_get);
+  if(lstptr->method->u.http_get != NULL) {
+    while(lstptr->method->u.http_get->check_urls != NULL)
+      lstptr->method->u.http_get->check_urls = remove_url(lstptr->method->u.http_get->check_urls);
+    FREE(lstptr->method->u.http_get);
   }
 
-  free(lstptr->method);
-  free(lstptr);
+  FREE(lstptr->method);
+  FREE(lstptr);
   return t;
 }
 
@@ -232,21 +242,23 @@ virtualserver * remove_vs(virtualserver * lstptr)
 
   t = (virtualserver *)lstptr->next;
   while(lstptr->svr != NULL) lstptr->svr = remove_svr(lstptr->svr);
-  free(lstptr->s_svr);
-  free(lstptr);
+
+  if (lstptr->s_svr)
+    FREE(lstptr->s_svr);
+  FREE(lstptr);
   return t;
 }
 
-vrrp_instance * remove_vrrp(vrrp_instance *lstptr)
+vrrp_instance *remove_vrrp(vrrp_instance *lstptr)
 {
   vrrp_instance *t;
 
   t = (vrrp_instance *)lstptr->next;
-  free(lstptr->vsrv->vaddr);
-  free(lstptr->vsrv->ipsecah_counter);
-  free(lstptr->vsrv->vif);
-  free(lstptr->vsrv);
-  free(lstptr);
+  FREE(lstptr->vsrv->vaddr);
+  FREE(lstptr->vsrv->ipsecah_counter);
+  FREE(lstptr->vsrv->vif);
+  FREE(lstptr->vsrv);
+  FREE(lstptr);
   return t;
 }
 
@@ -255,7 +267,7 @@ notification_email * remove_email(notification_email *lstptr)
   notification_email *t;
 
   t = (notification_email *)lstptr->next;
-  free(lstptr);
+  FREE(lstptr);
   return t;
 }
 
@@ -269,6 +281,12 @@ void clear_conf(configuration_data * lstptr)
 
   while(lstptr->lvstopology != NULL)
     lstptr->lvstopology = remove_vs(lstptr->lvstopology);
+
+  /* All SSL GET use the same shared SSL context */
+  if (lstptr->ssldata)
+    FREE(lstptr->ssldata);
+
+  FREE(lstptr);
 }
 
 void clear_vrrp_instance(vrrp_instance *lstptr)
@@ -284,14 +302,14 @@ void dump_httpget(http_get_check *pointerhttpget)
 {
   urls *pointerurls;
 
-  syslog(LOG_DEBUG,"       -> Nb get retry = %d",
+  syslog(LOG_INFO,"       -> Nb get retry = %d",
                    pointerhttpget->nb_get_retry);
-  syslog(LOG_DEBUG,"       -> Delay before retry = %d",
+  syslog(LOG_INFO,"       -> Delay before retry = %d",
                    pointerhttpget->delay_before_retry);
 
   pointerurls = pointerhttpget->check_urls;
   while(pointerhttpget->check_urls) {
-    syslog(LOG_DEBUG,"       -> Url = %s, Digest = %s",
+    syslog(LOG_INFO,"       -> Url = %s, Digest = %s",
                      pointerhttpget->check_urls->url,
                      pointerhttpget->check_urls->digest);
 
@@ -303,34 +321,38 @@ void dump_httpget(http_get_check *pointerhttpget)
 void dump_svr(realserver *pointersvr)
 {
   while(pointersvr != NULL) {
-    syslog(LOG_DEBUG,"    -> SVR IP = %s, PORT = %d, WEIGHT = %d",
+    syslog(LOG_INFO,"    -> SVR IP = %s, PORT = %d, WEIGHT = %d",
                      inet_ntoa(pointersvr->addr_ip),
                      ntohs(pointersvr->addr_port),
                      pointersvr->weight);
 
     switch (pointersvr->method->type) {
-      case ICMP_CHECK_ID:
-        syslog(LOG_DEBUG,"       -> Keepalive method = ICMP_CHECK");
+      case ICMP_CHECK_ID: /* no more implemented... */
+        syslog(LOG_INFO,"       -> Keepalive method = ICMP_CHECK");
         break;
       case TCP_CHECK_ID:
-        syslog(LOG_DEBUG,"       -> Keepalive method = TCP_CHECK");
-        syslog(LOG_DEBUG,"       -> Connection timeout = %d",
+        syslog(LOG_INFO,"       -> Keepalive method = TCP_CHECK");
+        syslog(LOG_INFO,"       -> Connection timeout = %d",
                          pointersvr->method->connection_to);
         break;
       case HTTP_GET_ID:
-        syslog(LOG_DEBUG,"       -> Keepalive method = HTTP_GET");
-        syslog(LOG_DEBUG,"       -> Connection timeout = %d",
+        syslog(LOG_INFO,"       -> Keepalive method = HTTP_GET");
+        syslog(LOG_INFO,"       -> Connection timeout = %d",
                          pointersvr->method->connection_to);
-        dump_httpget(pointersvr->method->http_get);
+        dump_httpget(pointersvr->method->u.http_get);
         break;
       case SSL_GET_ID:
+        syslog(LOG_INFO,"       -> Keepalive method = SSL_GET");
+        syslog(LOG_INFO,"       -> Connection timeout = %d",
+                         pointersvr->method->connection_to);
+        dump_httpget(pointersvr->method->u.http_get);
         break;
       case LDAP_GET_ID:
         break;
       case MISC_CHECK_ID:
-       syslog(LOG_DEBUG,"       -> Keepalive method = MISC_CHECK");
-       syslog(LOG_DEBUG,"       -> Check path = %s",
-                        pointersvr->method->misc_check_path);
+       syslog(LOG_INFO,"       -> Keepalive method = MISC_CHECK");
+       syslog(LOG_INFO,"       -> Check path = %s",
+                        pointersvr->method->u.misc_check_path);
        break;
     }
 
@@ -341,45 +363,49 @@ void dump_svr(realserver *pointersvr)
 void dump_vs(virtualserver *pointervs)
 {
   while(pointervs != NULL) {
-    syslog(LOG_DEBUG, " VS IP = %s, PORT = %d",
-                      inet_ntoa(pointervs->addr_ip),
-                      ntohs(pointervs->addr_port));
-
-    syslog(LOG_DEBUG, " -> delay_loop = %d, lb_algo = %s, "
+    if (pointervs->vfwmark) {
+      syslog(LOG_INFO, " VS FWMARK = %d"
+                      , pointervs->vfwmark);
+    } else {
+      syslog(LOG_INFO, " VS IP = %s, PORT = %d"
+                      , inet_ntoa(pointervs->addr_ip)
+                      , ntohs(pointervs->addr_port));
+    }
+    syslog(LOG_INFO, " -> delay_loop = %d, lb_algo = %s, "
                       "persistence = %s, protocol = %s",
                       pointervs->delay_loop, pointervs->sched,
                       pointervs->timeout_persistence,
                       (pointervs->service_type == IPPROTO_TCP)?"TCP":"UDP");
 
     switch (pointervs->loadbalancing_kind) {
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
       case 0:
-        syslog(LOG_DEBUG, " -> lb_kind = NAT");
-        syslog(LOG_DEBUG, " -> nat mask = %s", inet_ntoa(pointervs->nat_mask));
+        syslog(LOG_INFO, " -> lb_kind = NAT");
+        syslog(LOG_INFO, " -> nat mask = %s", inet_ntoa(pointervs->nat_mask));
         break;
       case IP_MASQ_F_VS_DROUTE:
-        syslog(LOG_DEBUG, " -> lb_kind = DR");
+        syslog(LOG_INFO, " -> lb_kind = DR");
         break;
       case IP_MASQ_F_VS_TUNNEL:
-        syslog(LOG_DEBUG, " -> lb_kind = TUN");
+        syslog(LOG_INFO, " -> lb_kind = TUN");
         break;
 #else
       case IP_VS_CONN_F_MASQ:
-        syslog(LOG_DEBUG, " -> lb_kind = NAT");
+        syslog(LOG_INFO, " -> lb_kind = NAT");
         break;
       case IP_VS_CONN_F_DROUTE:
-        syslog(LOG_DEBUG, " -> lb_kind = DR");
+        syslog(LOG_INFO, " -> lb_kind = DR");
         break;
       case IP_VS_CONN_F_TUNNEL:
-        syslog(LOG_DEBUG, " -> lb_kind = TUN");
+        syslog(LOG_INFO, " -> lb_kind = TUN");
         break;
 #endif
     }
 
     if (pointervs->s_svr != NULL) {
-      syslog(LOG_DEBUG, " -> sorry server = [%s:%d]",
-                        inet_ntoa(pointervs->s_svr->addr_ip),
-                        ntohs(pointervs->s_svr->addr_port));
+      syslog(LOG_INFO, " -> sorry server = [%s:%d]"
+                      , inet_ntoa(pointervs->s_svr->addr_ip)
+                      , ntohs(pointervs->s_svr->addr_port));
     }
 
     dump_svr(pointervs->svr);
@@ -391,7 +417,7 @@ void dump_vs(virtualserver *pointervs)
 void dump_email(notification_email *pointeremail)
 {
   while(pointeremail != NULL) {
-    syslog(LOG_DEBUG," Email notification = %s", pointeremail->addr);
+    syslog(LOG_INFO," Email notification = %s", pointeremail->addr);
 
     pointeremail = (notification_email *)pointeremail->next;
   }
@@ -402,28 +428,28 @@ void dump_vrrp(vrrp_instance *pointervrrp)
   int i;
 
   while (pointervrrp != NULL) {
-    syslog(LOG_DEBUG, " VRRP Instance = %s", pointervrrp->iname);
+    syslog(LOG_INFO, " VRRP Instance = %s", pointervrrp->iname);
     if (pointervrrp->vsrv->init_state == VRRP_STATE_BACK)
-      syslog(LOG_DEBUG, "   Want State = BACKUP");
+      syslog(LOG_INFO, "   Want State = BACKUP");
     else
-      syslog(LOG_DEBUG, "   Want State = MASTER");
-    syslog(LOG_DEBUG, "   Device = %s", pointervrrp->vsrv->vif->ifname);
+      syslog(LOG_INFO, "   Want State = MASTER");
+    syslog(LOG_INFO, "   Device = %s", pointervrrp->vsrv->vif->ifname);
     if (strlen(pointervrrp->isync) > 0)
-      syslog(LOG_DEBUG, "   Sync with instance = %s", pointervrrp->isync);
-    syslog(LOG_DEBUG, "   Virtual Router ID = %d", pointervrrp->vsrv->vrid);
-    syslog(LOG_DEBUG, "   Priority = %d", pointervrrp->vsrv->priority);
-    syslog(LOG_DEBUG, "   Advert interval = %dsec",
+      syslog(LOG_INFO, "   Sync with instance = %s", pointervrrp->isync);
+    syslog(LOG_INFO, "   Virtual Router ID = %d", pointervrrp->vsrv->vrid);
+    syslog(LOG_INFO, "   Priority = %d", pointervrrp->vsrv->priority);
+    syslog(LOG_INFO, "   Advert interval = %dsec",
                       pointervrrp->vsrv->adver_int/VRRP_TIMER_HZ);
     if (pointervrrp->vsrv->preempt)
-      syslog(LOG_DEBUG, "   Preempt active");
+      syslog(LOG_INFO, "   Preempt active");
     if (pointervrrp->vsrv->vif->auth_type) {
-      syslog(LOG_DEBUG, "   Authentication type = %s", 
+      syslog(LOG_INFO, "   Authentication type = %s", 
             (pointervrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
-      syslog(LOG_DEBUG, "   Password = %s", pointervrrp->vsrv->vif->auth_data);
+      syslog(LOG_INFO, "   Password = %s", pointervrrp->vsrv->vif->auth_data);
     }
-    syslog(LOG_DEBUG, "   VIP count = %d", pointervrrp->vsrv->naddr);
+    syslog(LOG_INFO, "   VIP count = %d", pointervrrp->vsrv->naddr);
     for (i = 0; i<pointervrrp->vsrv->naddr; i++)
-      syslog(LOG_DEBUG, "     VIP%d = %s", i+1, ip_ntoa(ntohl(pointervrrp->vsrv->vaddr[i].addr)));
+      syslog(LOG_INFO, "     VIP%d = %s", i+1, ip_ntoa(ntohl(pointervrrp->vsrv->vaddr[i].addr)));
 
     pointervrrp = (vrrp_instance *)pointervrrp->next;
   }
@@ -431,23 +457,40 @@ void dump_vrrp(vrrp_instance *pointervrrp)
 
 void dump_conf(configuration_data *lstconf)
 {
-  if(lstconf == NULL) {
-    syslog(LOG_DEBUG, "Empty data configuration !!!");
+  if (lstconf == NULL) {
+    syslog(LOG_INFO, "Empty data configuration !!!");
   } else {
-    syslog(LOG_DEBUG,"------< Global definitions >------");
-    syslog(LOG_DEBUG," LVS ID = %s",lstconf->lvs_id);
-    syslog(LOG_DEBUG," Smtp server = %s", inet_ntoa(lstconf->smtp_server));
-    syslog(LOG_DEBUG," Smtp server connection timeout = %d", lstconf->smtp_connection_to);
-    syslog(LOG_DEBUG," Email notification from = %s",lstconf->email_from);
+    syslog(LOG_INFO, "------< Global definitions >------");
+    syslog(LOG_INFO, " LVS ID = %s",lstconf->lvs_id);
+    syslog(LOG_INFO, " Smtp server = %s", inet_ntoa(lstconf->smtp_server));
+    syslog(LOG_INFO, " Smtp server connection timeout = %d", lstconf->smtp_connection_to);
+    syslog(LOG_INFO, " Email notification from = %s", lstconf->email_from);
     dump_email(lstconf->email);
 
+    if (lstconf->ssldata) {
+      syslog(LOG_INFO, "------< SSL definitions >------");
+      if (strlen(lstconf->ssldata->password) > 0)
+        syslog(LOG_INFO, " Password: %s", lstconf->ssldata->password);
+      if (strlen(lstconf->ssldata->cafile) > 0)
+        syslog(LOG_INFO, " CA-file: %s", lstconf->ssldata->cafile);
+      if (strlen(lstconf->ssldata->certfile) > 0)
+        syslog(LOG_INFO, " Certificate file: %s", lstconf->ssldata->certfile);
+      if (strlen(lstconf->ssldata->keyfile) > 0)
+        syslog(LOG_INFO, " Key file: %s", lstconf->ssldata->keyfile);
+      if (!strlen(lstconf->ssldata->keyfile)  &&
+          !strlen(lstconf->ssldata->certfile) &&
+          !strlen(lstconf->ssldata->cafile)   &&
+          !strlen(lstconf->ssldata->password)) 
+        syslog(LOG_INFO, " Using autogen SSL context");
+    }
+
     if (lstconf->vrrp) {
-      syslog(LOG_DEBUG,"------< VRRP Topology >------");
+      syslog(LOG_INFO, "------< VRRP Topology >------");
       dump_vrrp(lstconf->vrrp);
     }
 
     if (lstconf->lvstopology) {
-      syslog(LOG_DEBUG,"------< LVS Topology >------");
+      syslog(LOG_INFO, "------< LVS Topology >------");
       dump_vs(lstconf->lvstopology);
     }
   }
@@ -459,11 +502,10 @@ void process_stream_icmpcheck(FILE *stream, realserver *svrfill)
   keepalive_check *methodfill;
 
   /* Allocate new method structure */
-  methodfill = (keepalive_check *)malloc(sizeof(keepalive_check));
-  memset(methodfill, 0, sizeof(keepalive_check));
+  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
 
   methodfill->type = ICMP_CHECK_ID;
-  methodfill->http_get = NULL;
+  methodfill->u.http_get = NULL;
 
   svrfill->method = methodfill;
 }
@@ -473,11 +515,10 @@ void process_stream_tcpcheck(FILE *stream, realserver *svrfill)
   keepalive_check *methodfill;
 
   /* Allocate new method structure */
-  methodfill = (keepalive_check *)malloc(sizeof(keepalive_check));
-  memset(methodfill, 0, sizeof(keepalive_check));
+  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
 
   methodfill->type = TCP_CHECK_ID;
-  methodfill->http_get = NULL;
+  methodfill->u.http_get = NULL;
 
   do {
     switch (key(string)) {
@@ -496,15 +537,13 @@ void process_stream_tcpcheck(FILE *stream, realserver *svrfill)
 void process_stream_misccheck(FILE *stream, realserver *svrfill)
 {
   keepalive_check *methodfill;
-  char* pathstring = (char*)malloc(512);
+  char* pathstring = (char*)MALLOC(512);
 
   /* Allocate new method structure */
-  methodfill = (keepalive_check *)malloc(sizeof(keepalive_check));
-  memset(methodfill, 0, sizeof(keepalive_check));
+  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
 
   methodfill->type = MISC_CHECK_ID;
-  methodfill->http_get = NULL;
-  methodfill->misc_check_path = NULL;
+  methodfill->u.misc_check_path = NULL;
 
   do {
     switch (key(string)) {
@@ -513,7 +552,7 @@ void process_stream_misccheck(FILE *stream, realserver *svrfill)
         break;
       case KW_MISCPATH:
        fgets(pathstring,512,stream);
-       methodfill->misc_check_path=pathstring;
+       methodfill->u.misc_check_path=pathstring;
        break;
       case KW_UNKNOWN:
         break;
@@ -529,8 +568,7 @@ void process_stream_url(FILE *stream, http_get_check *httpgetfill)
   urls *urlfill;
 
   /* Allocate new url structure */
-  urlfill = (urls *)malloc(sizeof(urls));
-  memset(urlfill, 0, sizeof(urls));
+  urlfill = (urls *)MALLOC(sizeof(urls));
 
   urlfill->next = NULL;
 
@@ -551,21 +589,20 @@ void process_stream_url(FILE *stream, http_get_check *httpgetfill)
   httpgetfill->check_urls = add_item_url(httpgetfill->check_urls, urlfill);
 }
 
-void process_stream_httpget(FILE *stream, realserver *svrfill)
+void process_stream_httpget(FILE *stream, realserver *svrfill, int type)
 {
   keepalive_check *methodfill;
   http_get_check *httpgetfill;
 
   /* Allocate new method structure */
-  methodfill = (keepalive_check *)malloc(sizeof(keepalive_check));
-  memset(methodfill, 0, sizeof(keepalive_check));
+  methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
 
   /* Allocate new http get structure */
-  httpgetfill = (http_get_check *)malloc(sizeof(http_get_check));
-  memset(httpgetfill, 0, sizeof(http_get_check));
+  httpgetfill = (http_get_check *)MALLOC(sizeof(http_get_check));
+
+  methodfill->type = type;
+  methodfill->u.http_get = httpgetfill;
 
-  methodfill->type = HTTP_GET_ID;
-  methodfill->http_get = httpgetfill;
   httpgetfill->check_urls = NULL;
 
   do {
@@ -596,8 +633,7 @@ void process_stream_svr(FILE *stream, virtualserver *vsfill)
   realserver *svrfill;
 
   /* Allocate new real server structure */
-  svrfill = (realserver *)malloc(sizeof(realserver));
-  memset(svrfill, 0, sizeof(realserver));
+  svrfill = (realserver *)MALLOC(sizeof(realserver));
 
   /* Add the real server allocated to the virtual server
    * data structure.
@@ -623,9 +659,10 @@ void process_stream_svr(FILE *stream, virtualserver *vsfill)
         process_stream_tcpcheck(stream, svrfill);
         break;
       case KW_HTTPGET:
-        process_stream_httpget(stream, svrfill);
+        process_stream_httpget(stream, svrfill, HTTP_GET_ID);
         break;
-      case KW_SSLGET: /* not yet implemented */
+      case KW_SSLGET: 
+        process_stream_httpget(stream, svrfill, SSL_GET_ID);
         break;
       case KW_LDAPGET: /* not yet implemented */
         break;
@@ -644,8 +681,7 @@ void process_stream_ssvr(FILE *stream, virtualserver *vsfill)
   realserver *ssvrfill;
 
   /* Allocate new sorry server structure */
-  ssvrfill = (realserver *)malloc(sizeof(realserver));
-  memset(ssvrfill, 0, sizeof(realserver));
+  ssvrfill = (realserver *)MALLOC(sizeof(realserver));
 
   /* direct affectation, we can use add_item_svr, so
    * can specify more than 1 sorry_server...
@@ -669,8 +705,7 @@ void process_stream_vs(FILE *stream, configuration_data *conf_data)
   virtualserver *vsfill;
 
   /* Allocate new virtual server structure */
-  vsfill = (virtualserver *)malloc(sizeof(virtualserver));
-  memset(vsfill, 0, sizeof(virtualserver));
+  vsfill = (virtualserver *)MALLOC(sizeof(virtualserver));
 
   /* Add the virtual server allocated to the configuration
    * data structure.
@@ -680,9 +715,15 @@ void process_stream_vs(FILE *stream, configuration_data *conf_data)
   conf_data->lvstopology = add_item_vs(conf_data->lvstopology, vsfill);
 
   fscanf(stream, "%s", string);
-  vsfill->addr_ip.s_addr = inet_addr(string);
-  fscanf(stream, "%s", string);
-  vsfill->addr_port = htons(atoi(string));
+  if (!strcmp(string, "fwmark")) {
+    fscanf(stream, "%s", string);
+    vsfill->vfwmark = atoi(string);
+  } else {
+    vsfill->vfwmark = 0;
+    vsfill->addr_ip.s_addr = inet_addr(string);
+    fscanf(stream, "%s", string);
+    vsfill->addr_port = htons(atoi(string));
+  }
 
   /* Setting default value */
   vsfill->delay_loop = KEEPALIVED_DEFAULT_DELAY;
@@ -698,7 +739,7 @@ void process_stream_vs(FILE *stream, configuration_data *conf_data)
       case KW_LBKIND:
         fscanf(stream, "%s", string);
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
         if (strcmp(string, "NAT") == 0)
           vsfill->loadbalancing_kind = 0;
         else
@@ -757,8 +798,7 @@ void process_stream_email(FILE *stream, configuration_data *conf_data)
   do {
     fscanf(stream, "%s", string);
     if(key(string) != KW_BEGINFLAG && key(string) != KW_ENDFLAG) {
-      emailfill = (notification_email *)malloc(sizeof(notification_email));
-      memset(emailfill, 0, sizeof(notification_email));
+      emailfill = (notification_email *)MALLOC(sizeof(notification_email));
       strncat(emailfill->addr, string, sizeof(emailfill->addr));
       emailfill->next = NULL;
       conf_data->email = add_item_email(conf_data->email, emailfill);
@@ -794,14 +834,44 @@ void process_stream_globaldefs(FILE *stream, configuration_data *conf_data)
   } while(key(string) != KW_ENDFLAG);
 }
 
+int process_stream_ssl(FILE *stream, configuration_data *conf_data)
+{
+  /* Fill in the global defs structure */
+  do {
+    switch (key(string)) {
+      case KW_SSLPASSWORD:
+        fscanf(stream, "%s", conf_data->ssldata->password);
+        conf_data->ssldata->enable |= 1;
+        break;
+      case KW_SSLCAFILE:
+        fscanf(stream, "%s", conf_data->ssldata->cafile);
+        conf_data->ssldata->enable |= 2;
+        break;
+      case KW_SSLKEYFILE:
+        fscanf(stream, "%s", conf_data->ssldata->keyfile);
+        conf_data->ssldata->enable |= 4;
+        break;
+      case KW_SSLCERTFILE:
+        fscanf(stream, "%s", conf_data->ssldata->certfile);
+        conf_data->ssldata->enable |= 8;
+        break;
+      case KW_UNKNOWN:
+        break;
+    }
+    fscanf(stream, "%s", string);
+  } while(key(string) != KW_ENDFLAG);
+
+  return conf_data->ssldata->enable;
+}
+
 static void add_item_vrrp_vip(vrrp_rt *vsrv, uint32_t ipaddr)
 {
   vsrv->naddr++;
   /* alloc the room */
   if( vsrv->vaddr ){
-    vsrv->vaddr = realloc(vsrv->vaddr, vsrv->naddr*sizeof(*vsrv->vaddr));
+    vsrv->vaddr = REALLOC(vsrv->vaddr, vsrv->naddr*sizeof(*vsrv->vaddr));
   } else {
-    vsrv->vaddr = malloc(sizeof(*vsrv->vaddr));
+    vsrv->vaddr = (vip_addr *)MALLOC(sizeof(*vsrv->vaddr));
   }
   /* store the data */
   vsrv->vaddr[vsrv->naddr-1].addr = ipaddr;
@@ -847,29 +917,24 @@ int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
   seq_counter *counterfill;
 
   /* Allocate new VRRP structure */
-  vrrpfill = (vrrp_instance *)malloc(sizeof(vrrp_instance));
-  rtfill = (vrrp_rt *)malloc(sizeof(vrrp_rt));
-  viffill = (vrrp_if *)malloc(sizeof(vrrp_if));
-  counterfill = (seq_counter *)malloc(sizeof(seq_counter));
-
-  memset(vrrpfill, 0, sizeof(vrrp_instance));
-  memset(rtfill, 0, sizeof(vrrp_rt));
-  memset(viffill, 0, sizeof(vrrp_if));
-  memset(counterfill, 0, sizeof(seq_counter));
+  vrrpfill     = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
+  rtfill       = (vrrp_rt *)      MALLOC(sizeof(vrrp_rt));
+  viffill      = (vrrp_if *)      MALLOC(sizeof(vrrp_if));
+  counterfill  = (seq_counter *)  MALLOC(sizeof(seq_counter));
 
   /* Add the vrrp instance allocated to the configuration
    * data structure.
    */
-  vrrpfill->vsrv = rtfill;
-  vrrpfill->vsrv->vif = viffill;
+  vrrpfill->vsrv          = rtfill;
+  vrrpfill->vsrv->vif     = viffill;
   vrrpfill->vsrv->ipsecah_counter = counterfill;
-  vrrpfill->vsrv->vaddr = NULL;
-  vrrpfill->vsrv->vaddr = NULL;
-  vrrpfill->next = NULL;
+  vrrpfill->vsrv->vaddr   = NULL;
+  vrrpfill->vsrv->vaddr   = NULL;
+  vrrpfill->next          = NULL;
 
   /* default value */
-  rtfill->wantstate = VRRP_STATE_BACK;
-  rtfill->init_state = VRRP_STATE_BACK;
+  rtfill->wantstate       = VRRP_STATE_BACK;
+  rtfill->init_state      = VRRP_STATE_BACK;
 
   conf_data->vrrp = add_item_vrrp(conf_data->vrrp, vrrpfill);
 
@@ -928,6 +993,18 @@ int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
       case KW_VRRPPREEMPT:
         rtfill->preempt = !rtfill->preempt;
         break;
+      case KW_VRRPDEBUG:
+        fscanf(stream, "%d", &rtfill->debug);
+        if (VRRP_IS_BAD_DEBUG_INT(rtfill->debug)) {
+          syslog(LOG_DEBUG, "VRRP Error : Debug intervall not valid !");
+          syslog(LOG_DEBUG, "VRRP Error : must be between 0-4");
+          return 0;
+        }
+        break;
+      case KW_VRRPNOTIFY:
+        fscanf(stream, "%s", rtfill->notify_file);
+        rtfill->notify_exec = 1;
+        break;
       case KW_UNKNOWN:
         break;
     }
@@ -941,29 +1018,28 @@ int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
   return 1;
 }
 
-configuration_data * conf_reader()
+configuration_data *conf_reader(char *conf_file)
 {
   configuration_data *conf_data;
   FILE *stream;
 
-  /* Allocate configuration data memory */
-  conf_data = (configuration_data *)malloc(sizeof(configuration_data));
-  memset(conf_data, 0, sizeof(configuration_data));
-
   /* Parse the confuguration file */
-  stream = fopen(CONFFILE, "r");
+  stream = fopen((conf_file)?conf_file:CONFFILE, "r");
   if(!stream) {
     syslog(LOG_INFO, "ConfReader : Can not read the configuration file...");
     return(NULL);
   }
 
+  /* Allocate configuration data memory */
+  conf_data = (configuration_data *)MALLOC(sizeof(configuration_data));
+
   /* Allocate temp buffer string */
-  string = (char *)malloc(TEMP_BUFFER_LENGTH);
-  memset(string, 0, TEMP_BUFFER_LENGTH);
+  string = (char *)MALLOC(TEMP_BUFFER_LENGTH);
 
   /* Initialise the dynamic data structure */
   conf_data->email = NULL;
   conf_data->lvstopology = NULL;
+  conf_data->ssldata = NULL;
 
   while (!feof(stream)) {
     switch (key(string)) {
@@ -977,13 +1053,19 @@ configuration_data * conf_reader()
         if (!process_stream_vrrp(stream, conf_data))
           return NULL;
         break;
+      case KW_SSL:
+        conf_data->ssldata = (ssl_data *)MALLOC(sizeof(ssl_data));
+        conf_data->ssldata->enable = 0;
+        if ((process_stream_ssl(stream, conf_data) & 7) != 7)
+          return NULL;
+        break;
       case KW_UNKNOWN:
         break;
     }
     fscanf(stream, "%s", string);
   }
 
-  free(string);
+  FREE(string);
   fclose(stream);
   return(conf_data);
 }
index f4b7e38..bcf5094 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        cfreader.c include file.
  *  
- * Version:     $Id: cfreader.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: cfreader.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -30,8 +30,8 @@
 #include <stdint.h>
 #include <syslog.h>
 #include <arpa/inet.h>
-
-#ifdef KERNEL_2_2
+#include <openssl/ssl.h>
+#ifdef _KRNL_2_2_
   #include <linux/ip_masq.h>
   #include <net/ip_masq.h>
 #else
 #define MAX_TIMEOUT_LENGTH 5
 #define MAX_INT_LENGTH     10
 
-#ifdef KERNEL_2_2
+#define MAX_SSL_PASSWORD    48
+#define MAX_SSL_PATH        240
+
+#ifdef _KRNL_2_2_
   #define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
 #else
   #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
@@ -113,11 +116,35 @@ struct keyword {
 #define KW_VRRPSYNC    43
 #define KW_VRRPPREEMPT 44
 
-#define KW_UNKNOWN     45
+#define KW_VRRPDEBUG    45
+#define KW_VRRPNOTIFY   46
+#define KW_FWMARK       47
+
+#define KW_SSLPASSWORD  48
+#define KW_SSLCAFILE    49
+#define KW_SSLKEYFILE   50
+#define KW_SSLCERTFILE  51
+#define KW_SSL          52
+
+#define KW_UNKNOWN     53
 
 #define KEEPALIVED_DEFAULT_DELAY 60
 
 /* Structure definition  */
+
+/* SSL common data */
+typedef struct _ssl_data SSL_DATA;
+typedef struct _ssl_data {
+  int        enable;
+  int        strong_check;
+  SSL_CTX    *ctx;
+  SSL_METHOD *meth;
+  char       password[MAX_SSL_PASSWORD];
+  char       cafile[MAX_SSL_PATH];
+  char       certfile[MAX_SSL_PATH];
+  char       keyfile[MAX_SSL_PATH];
+} ssl_data;
+
 typedef struct _urls {
   char url[MAX_URL_LENGTH];
   char digest[DIGEST_LENGTH];
@@ -140,8 +167,10 @@ typedef struct _keepalive_check {
 #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;
+  union {
+    http_get_check *http_get;
+    char *misc_check_path;
+  } u;
 } keepalive_check;
 
 typedef struct _real_server {
@@ -156,6 +185,7 @@ typedef struct _real_server {
 
 typedef struct _virtual_server {
   struct in_addr addr_ip;
+  uint32_t vfwmark;
   uint16_t addr_port;
   uint16_t service_type;
   int delay_loop;
@@ -190,12 +220,12 @@ typedef struct _configuration_data {
   int smtp_connection_to;
   notification_email *email;
   vrrp_instance *vrrp;
-
   virtualserver *lvstopology;
+  ssl_data      *ssldata;
 } configuration_data;
 
 /* prototypes */
-extern configuration_data * conf_reader();
+extern configuration_data *conf_reader(char *conf_file);
 extern void clear_conf(configuration_data * lstptr);
 extern void clear_vrrp_instance(vrrp_instance *lstptr);
 extern void dump_conf(configuration_data * lstptr);
diff --git a/check.h b/check.h
index d067869..d299ba2 100644 (file)
--- a/check.h
+++ b/check.h
@@ -5,7 +5,7 @@
  *
  * Part:        Checkers arguments structures definitions.
  *
- * Version:     $Id: check.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #ifndef _CHECK_H
 #define _CHECK_H
 
+/* system includes */
+#include <openssl/md5.h>
+#include <openssl/ssl.h>
+
+/* ssl specific thread arguments defs */
+typedef struct {
+  char *buffer;
+  char *extracted;
+  int   error;
+  int   len;
+  SSL   *ssl;
+  BIO   *bio;
+  MD5_CTX context;
+} REQ;
+
 /* http specific thread arguments defs */
-struct http_thread_arg {
+typedef struct _http_thread_arg {
   int retry_it;                /* current number of get retry */
   int url_it;                  /* current url checked index */
-};
+  REQ *req;                    /* GET buffer and SSL args */
+} http_thread_arg;
 
 /* global thread arguments defs */
-struct thread_arg {
+typedef struct _thread_arg {
   configuration_data *root;    /* pointer to the configuration root data */
   virtualserver *vs;           /* pointer to the checker thread virtualserver */
   realserver *svr;             /* pointer to the checker thread realserver */
   void *checker_arg;           /* pointer to the specific checker arg */
-};
+} thread_arg;
 
 #endif
index f0e3fb6..7bbee09 100644 (file)
@@ -3,13 +3,12 @@
  *              <www.linuxvirtualserver.org>. It monitor & manipulate
  *              a loadbalanced server pool using multi-layer checks.
  *
- * Part:        HTTP GET CHECK. Perform an http get query to a specified
- *              url, compute a MD5 over this result and match it to the
- *              expected value.
+ * Part:        WEB CHECK. Common HTTP/SSL checker primitives.
  *
- * Version:     $Id: check_http.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check_http.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
- * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
  *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
  *              2 of the License, or (at your option) any later version.
  */
 
+#include <openssl/err.h>
 #include "check_http.h"
+#include "check_ssl.h"
+#include "memory.h"
+
+/* 
+ * The global design of this checker is the following :
+ * 
+ * - All the actions are done asynchronously.
+ * - All the actions handle timeout connection.
+ * - All the actions handle error from low layer to upper
+ *   layers.
+ * 
+ * The global synopsis of the inter-thread-call is :
+ *     
+ *     http_connect_thread (handle layer4 connect)
+ *            v
+ *     http_check_thread (handle SSL connect)
+ *            v
+ *     http_request_thread (send SSL GET request)
+ *            v
+ *     http_response_thread (initialize read stream step)
+ *         /             \
+ *        /               \
+ *       v                 v
+ *  http_read_thread   ssl_read_thread (perform HTTP|SSL stream)
+ *       v              v
+ *     http_handle_response (next checker thread registration)
+ */
 
-/* simple function returning a pointer to the html buffer begin */
-char *extract_html(char *buffer, int size_buffer)
-{
-  char *end=buffer+size_buffer;
-
-  while ( buffer < end &&
-          !(*buffer++ == '\n' &&
-            (*buffer == '\n' || (*buffer ++ == '\r' && *buffer =='\n'))));
-
-  if (*buffer == '\n') return buffer+1;
-  return NULL;
-}
-
-/* return the url pointer of the current url iterator  */
-urls *fetch_next_url(struct thread_arg *thread_arg)
+/*
+ * Simple epilog functions. Handling event timeout.
+ * Finish the checker with memory managment or url rety check.
+ *
+ * c == 0 => reset to 0 retry_it counter
+ * t == 0 => reset to 0 url_it counter
+ * method == 1 => register a new checker thread
+ * method == 2 => register a retry on url checker thread
+ */
+int epilog(thread *thread, int metod, int t, int c)
 {
-  struct http_thread_arg *checker_arg;
-  int i = 0;
-
+  thread_arg *thread_arg = THREAD_ARG(thread);
+  http_thread_arg *checker_arg;
+  int delay = 0;
+  REQ *req;
   checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req = checker_arg->req;
+  if (metod) {
+    checker_arg->url_it   += t ? t : -checker_arg->url_it;
+    checker_arg->retry_it += c ? c : -checker_arg->retry_it;
+  }
 
-  /* fetch the next url */
-  for (i=0; i<checker_arg->url_it; i++)
-    thread_arg->svr->method->http_get->check_urls=(urls *) thread_arg->svr->method->http_get->check_urls->next;
+  /* register next timer thread */
+  switch (metod) {
+    case 1:
+      if (req)
+        delay = thread_arg->vs->delay_loop;
+      else
+        delay = thread_arg->vs->delay_loop -
+                thread_arg->svr->method->u.http_get->delay_before_retry;
+      thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+      break; 
+    case 2:
+      delay = thread_arg->svr->method->u.http_get->delay_before_retry;
+      thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+      break;
+  }
 
-  if (thread_arg->svr->method->http_get->check_urls != NULL)
-    return thread_arg->svr->method->http_get->check_urls;
+  /* If req == NULL, fd is not created */
+  if (req != NULL) {
+    if (req->ssl)
+      SSL_free(req->ssl);
+    if (req->buffer)
+      FREE(req->buffer);
+    FREE(req);
+    close(thread->u.fd);
+  }
 
-  return NULL;
+  return 0;
 }
 
-/* read http get result from the remote http server. Apply trigger check to this result */
-int http_response_thread(struct thread *thread)
+int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
 {
-  struct thread_arg *thread_arg;
-  struct http_thread_arg *checker_arg;
-  long total_length = 0;
-  int rcv_buffer_size = 0;
-  int di = 0;
-  MD5_CTX context;
-  unsigned char digest[16];
-  char *buffer;
-  char *digest_tmp;
-  char *buffer_html;
-  char *buffer_tmp;
-  urls *fetched_url;
-  urls *pointerurls;
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
 
-  thread_arg = THREAD_ARG(thread);
+  thread_arg  = THREAD_ARG(thread);
   checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
 
-  /* Handle read timeout */
-  if(thread->type == THREAD_READ_TIMEOUT) {
-#ifdef DEBUG
+  /*
+   * The get retry implementation mean that we retry performing
+   * a GET on the same url until the remote web server return 
+   * html buffer. This is sometime needed with some applications
+   * servers.
+   */
+  if (++checker_arg->retry_it <=
+      thread_arg->svr->method->u.http_get->nb_get_retry) {
+
+#ifdef _DEBUG_
+    syslog(LOG_DEBUG, "Retry %s server [%s:%d] after %d retry.", debug_msg,
+                      inet_ntoa(thread_arg->svr->addr_ip),
+                      ntohs(thread_arg->svr->addr_port),
+                      checker_arg->retry_it - 1);
+#endif
+    return epilog(thread,2,0,1);
+  } else {
+#ifdef _DEBUG_
     if (thread_arg->svr)
-      syslog(LOG_DEBUG, "HTTP read timeout to [%s:%d].",
+      syslog(LOG_DEBUG, "Timeout %s server [%s:%d].", debug_msg,
                           inet_ntoa(thread_arg->svr->addr_ip),
                           ntohs(thread_arg->svr->addr_port));
 #endif
     /* check if server is currently alive */
     if (thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
+      smtp_alert(thread->master, thread_arg->root, thread_arg->svr, "DOWN", smtp_msg);
       perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
     }
 
-    /* reset iterator counters */
-    memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-    /* register next timer thread */
-    thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                     thread_arg->vs->delay_loop);
-
-    close(thread->u.fd);
-    return 0;
+    return epilog(thread,1,0,0);
   }
 
-  /* Allocate the get buffers */
-  buffer = (char *)malloc(MAX_BUFFER_LENGTH);
-  buffer_tmp = (char *)malloc(GET_BUFFER_LENGTH);
-
-  /* Cleanup the room */
-  memset(buffer, 0, MAX_BUFFER_LENGTH);
-  memset(buffer_tmp, 0, GET_BUFFER_LENGTH);
-
-  /* Read the fd until remote sever stop sending data.
-     -> FIXME : need to register a new read thread while receiving data */
-  while ((rcv_buffer_size = read(thread->u.fd, buffer_tmp, GET_BUFFER_LENGTH)) != 0) {
-    if (rcv_buffer_size == -1) {
-      if (errno == EAGAIN) goto end;
-      free(buffer);
-      free(buffer_tmp);
-      close(thread->u.fd);
-
-      /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-      }
-
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
-
-      return 0;
-    }
-
-    /* received data overflow buffer size ? */
-    if (total_length >= MAX_BUFFER_LENGTH) {
-      syslog(LOG_INFO, "Received buffer from [%s:%d] overflow our get buffer size.",
-                       inet_ntoa(thread_arg->svr->addr_ip),
-                       ntohs(thread_arg->svr->addr_port));
-      free(buffer);
-      free(buffer_tmp);
-      close(thread->u.fd);
-
-      /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : received data overflow <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-      }
-
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
-
-      return 0;
-    } else {
-      memcpy(buffer+total_length, buffer_tmp, rcv_buffer_size);
-      memset(buffer_tmp, 0, GET_BUFFER_LENGTH);
-      total_length += rcv_buffer_size;
-      if (rcv_buffer_size < GET_BUFFER_LENGTH) goto end;
-    }
-  }
+  return 0;
+}
 
-end:
+/* HTML stream parser primitives */
+/* simple function returning a pointer to the html buffer begin */
+char *extract_html(char *buffer, int size_buffer)
+{
+  char *end = buffer+size_buffer;
 
-  buffer_html = extract_html(buffer, total_length);
+  while ( buffer < end &&
+          !(*buffer++ == '\n' &&
+            (*buffer == '\n' || (*buffer ++ == '\r' && *buffer =='\n'))));
 
-//print_buffer(total_length - (buffer_html - buffer),buffer_html);
+  if (*buffer == '\n') return buffer+1;
+  return NULL;
+}
 
-  if ((total_length == 0) || ((total_length-(buffer_html-buffer)) == 0)) {
-#ifdef DEBUG
-    syslog(LOG_DEBUG, "No html data received from remote server [%s:%d].",
-                      inet_ntoa(thread_arg->svr->addr_ip),
-                      ntohs(thread_arg->svr->addr_port));
-#endif
+/* return the url pointer of the current url iterator  */
+urls *fetch_next_url(thread_arg *thread_arg)
+{
+  http_thread_arg *checker_arg;
+  int i = 0;
 
-    checker_arg->retry_it++;
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
 
-    /* The get retry implementation mean that we retry performing
-     * a GET on the same url until the remote web server return 
-     * html buffer. This is sometime needed with some applications
-     * servers.
-     */
-    if (checker_arg->retry_it > 
-        thread_arg->svr->method->http_get->nb_get_retry) {
+  /* fetch the next url */
+  for (i=0; i<checker_arg->url_it; i++)
+    thread_arg->svr->method->u.http_get->check_urls=(urls *)thread_arg->svr->method->u.http_get->check_urls->next;
 
-#ifdef DEBUG
-      syslog(LOG_DEBUG, "Empty buffer returned from [%s:%d] after %d retry.",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port),
-                        --checker_arg->retry_it);
-#endif
+  if (thread_arg->svr->method->u.http_get->check_urls != NULL)
+    return thread_arg->svr->method->u.http_get->check_urls;
 
-      /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : empty buffer received <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-      }
+  return NULL;
+}
 
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
+/* Handle response */
+int http_handle_response(thread *thread, unsigned char digest[16], int empty_buffer)
+{
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  REQ *req;
+  int r, di = 0;
+  unsigned char *digest_tmp;
+  urls *fetched_url;
+  urls *pointerurls;
 
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
 
-    } else {
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->svr->method->http_get->delay_before_retry);
-    }
+  if (empty_buffer) {
+    return timeout_epilog(thread,
+      "=> CHECK failed on service : empty buffer received <=\n\n",
+      "Read, no data received from ");
   } else {
-
     /* Compute MD5SUM */
-    digest_tmp = (char *)malloc(2*sizeof(digest));
-    memset(digest_tmp, 0, 2*sizeof(digest));
-    memset(digest, 0, sizeof(digest));
-    MD5Init(&context);
-    MD5Update(&context, buffer_html, total_length-(buffer_html-buffer));
-    MD5Final(digest, &context);
-
-    for (di=0; di < 16; ++di)
+    digest_tmp = (char *)MALLOC(MD5_BUFFER_LENGTH+1);
+    for (di=0; di < 16; di++)
       sprintf(digest_tmp+2*di, "%02x", digest[di]);
 
-    pointerurls = thread_arg->svr->method->http_get->check_urls;
+    pointerurls = thread_arg->svr->method->u.http_get->check_urls;
     fetched_url = fetch_next_url(thread_arg);
-    thread_arg->svr->method->http_get->check_urls = pointerurls;
+    thread_arg->svr->method->u.http_get->check_urls = pointerurls;
 
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s].",
                       inet_ntoa(thread_arg->svr->addr_ip),
                       ntohs(thread_arg->svr->addr_port),
                       checker_arg->url_it+1, digest_tmp);
 #endif
 
-    if (strcmp(fetched_url->digest, digest_tmp) !=  0) {
+    r = strcmp(fetched_url->digest, digest_tmp);
+    FREE(digest_tmp);
 
-#ifdef DEBUG
+    if (r) {
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d), expecting MD5SUM [%s].",
                         inet_ntoa(thread_arg->svr->addr_ip),
                         ntohs(thread_arg->svr->addr_port),
                         checker_arg->url_it+1, fetched_url->digest);
 #endif
 
-
       /* check if server is currently alive */
       if (thread_arg->svr->alive) {
         smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : MD5 digest mismatch <=\n\n");
+                   "DOWN", "=> CHECK failed on service : MD5 digest mismatch <=\n\n");
         perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
       }
-
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
-
-      /* free temporary buffer */
-      free(digest_tmp);
-
+      return epilog(thread,1,0,0);
     } else {
-
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "MD5 digest success to [%s:%d] url(%d), expected MD5SUM [%s] match.",
                         inet_ntoa(thread_arg->svr->addr_ip),
                         ntohs(thread_arg->svr->addr_port),
                         checker_arg->url_it+1, fetched_url->digest);
 #endif
-
-      /* reset retry iterator and increment url iterator */
-      checker_arg->retry_it = 0;
-      checker_arg->url_it++;
-      free(digest_tmp);
-
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->svr->method->http_get->delay_before_retry);
+      return epilog(thread,2,1,0)+1;
     }
   }
-
-  free(buffer);
-  free(buffer_tmp);
-  close(thread->u.fd);
-
-  return 1;
+  return epilog(thread,0,0,0)+1;
 }
 
-/* remote http server is connected, send it the get url query.  */
-int http_request_thread(struct thread *thread)
+/* Asynchronous HTTP stream reader */
+int http_read_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  struct http_thread_arg *checker_arg;
-  char *str_request;
-  urls *fetched_url;
-  urls *pointerurls;
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  unsigned char digest[16];
+  REQ *req;
+  int r = 0;
 
-  thread_arg = THREAD_ARG(thread);
+  thread_arg  = THREAD_ARG(thread);
   checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
 
   /* Handle read timeout */
-  if(thread->type == THREAD_WRITE_TIMEOUT) {
-#ifdef DEBUG
-    if (thread_arg->svr)
-      syslog(LOG_DEBUG, "HTTP write timeout to [%s:%d].",
-                          inet_ntoa(thread_arg->svr->addr_ip),
-                          ntohs(thread_arg->svr->addr_port));
-#endif
-    /* check if server is currently alive */
-    if (thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
-      perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-    }
+  if (thread->type == THREAD_READ_TIMEOUT) {
+    return timeout_epilog(thread,
+      "=> HTTP CHECK failed on service : recevice data <=\n\n",
+      "HTTP read");
+  }
 
-    /* reset iterator counters */
-    memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
+  /* read the HTTP stream */
+  r = read(thread->u.fd, req->buffer+req->len, MAX_BUFFER_LENGTH-req->len);
 
-    /* register next timer thread */
-    thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                     thread_arg->vs->delay_loop);
+  if (r == -1 || r == 0) { /* -1:error , 0:EOF */
 
-    close(thread->u.fd);
-    return 0;
-  }
+    /* All the HTTP stream has been parsed */
+    MD5_Final(digest, &req->context);
 
-  str_request = (char *)malloc(GET_REQUEST_BUFFER_LENGTH);
-  memset(str_request, 0, GET_REQUEST_BUFFER_LENGTH);
+    if (r == -1) {
+      /* We have encourred a real read error */
+      if (thread_arg->svr->alive) {
+        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
+                   "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
+        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      }
+      return epilog(thread,1,0,0);
+    }
 
-  pointerurls = thread_arg->svr->method->http_get->check_urls;
-  fetched_url = fetch_next_url(thread_arg);
-  thread_arg->svr->method->http_get->check_urls = pointerurls;
+    /* Handle response stream */
+    http_handle_response(thread, digest, (!req->extracted)?1:0);
 
-  if (fetched_url != NULL) {
-    snprintf(str_request, GET_REQUEST_BUFFER_LENGTH, GETCMD, fetched_url->url);
   } else {
-    /* All the url have been successfully checked.
-     * Check completed.
-     */
-    close(thread->u.fd);
-    free(str_request);
 
-    /* check if server is currently alive */
-    if (!thread_arg->svr->alive) {
-      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "UP", "=> HTTP CHECK succeed on service <=\n\n");
-      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+    req->len += r;
+    if (!req->extracted) {
+      if ((req->extracted = extract_html(req->buffer, req->len))) {
+        r = req->len - (req->extracted-req->buffer);
+        if (r) {
+          memcpy(req->buffer, req->extracted, r);
+          MD5_Update(&req->context, req->buffer, r);
+          r=0;
+        }
+        req->len = r;
+      } else {
+        /* minimize buffer using no 2*CR/LF found yet */
+        if (req->len > 3) {
+          memcpy(req->buffer, req->buffer + req->len - 3, 3);
+          req->len = 3;
+        }
+      }
+    } else {
+      if (req->len) {
+        MD5_Update(&req->context, req->buffer, req->len);
+        req->len = 0;
+      }
     }
 
-    /* reset iterator counters */
-    memset(checker_arg, 0, sizeof(struct http_thread_arg));
+    /*
+     * Register next http stream reader.
+     * Register itself to not perturbe global I/O multiplexer.
+     */
+    thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
+                    thread_arg->svr->method->connection_to);
+  }
+
+  return 0;
+}
+
+/*
+ * Read get result from the remote web server.
+ * Apply trigger check to this result.
+ */
+int http_response_thread(thread *thread)
+{
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  REQ *req;
 
-    /* register next timer thread */
-    thread_add_timer(thread->master, http_connect_thread, thread_arg,
-                     thread_arg->vs->delay_loop);
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
 
-    return 1;
+  /* Handle read timeout */
+  if (thread->type == THREAD_READ_TIMEOUT) {
+    return timeout_epilog(thread,
+      "=> CHECK failed on service : recevice data <=\n\n",
+      "WEB read");
   }
 
-#ifdef DEBUG
-  syslog(LOG_DEBUG,"Processing url(%d) of [%s:%d].",
-                   checker_arg->url_it+1,
-                   inet_ntoa(thread_arg->svr->addr_ip),
-                   ntohs(thread_arg->svr->addr_port));
+  /* Allocate & clean the get buffer */
+  req->buffer    = (char *)MALLOC(MAX_BUFFER_LENGTH);
+  req->extracted = NULL;
+  req->len       = 0;
+  req->error     = 0;
+  MD5_Init(&req->context);
+
+  /* Register asynchronous http/ssl read thread */
+  if (thread_arg->svr->method->type == SSL_GET_ID)
+    thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
+                    thread_arg->svr->method->connection_to);
+  else
+    thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
+                    thread_arg->svr->method->connection_to);
+  return 0;
+}
+
+/* remote Web server is connected, send it the get url query.  */
+int http_request_thread(thread *thread)
+{
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  char    *str_request;
+  urls    *fetched_url;
+  urls    *pointerurls;
+  REQ     *req;
+  int ret = 0;
+
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
+
+  /* Handle read timeout */
+  if(thread->type == THREAD_WRITE_TIMEOUT) {
+    return timeout_epilog(thread,
+      "=> CHECK failed on service : read timeout <=\n\n",
+      "Web read, timeout");
+  }
+
+  /* Allocate & clean the GET string */
+  str_request = (char *)MALLOC(GET_REQUEST_BUFFER_LENGTH);
+
+  pointerurls = thread_arg->svr->method->u.http_get->check_urls;
+  fetched_url = fetch_next_url(thread_arg);
+  thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+
+  snprintf(str_request, GET_REQUEST_BUFFER_LENGTH
+                      , REQUEST_TEMPLATE, fetched_url->url
+                      , inet_ntoa(thread_arg->svr->addr_ip)
+                      , ntohs(thread_arg->svr->addr_port));
+
+#ifdef _DEBUG_
+  syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d].",
+                    checker_arg->url_it+1,
+                    inet_ntoa(thread_arg->svr->addr_ip),
+                    ntohs(thread_arg->svr->addr_port));
 #endif
 
-  if (send(thread->u.fd, str_request, strlen(str_request), 0) == -1) {
+  /* Send the GET request to remote Web server */
+  if (thread_arg->svr->method->type == SSL_GET_ID)
+    ret = ssl_send_request(req->ssl, str_request, strlen(str_request));
+  else
+    ret = (send(thread->u.fd, str_request, strlen(str_request), 0) != -1)?1:0;
+
+  FREE(str_request);
+
+  if (!ret) {
     syslog(LOG_WARNING, "Cannot send get request to [%s:%d].",
                         inet_ntoa(thread_arg->svr->addr_ip),
                         ntohs(thread_arg->svr->addr_port));
@@ -378,117 +419,124 @@ int http_request_thread(struct thread *thread)
     /* check if server is currently alive */
     if (thread_arg->svr->alive) {
       smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                 "DOWN", "=> HTTP CHECK failed on service : cannot send data <=\n\n");
+                 "DOWN", "=> CHECK failed on service : cannot send data <=\n\n");
       perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
     }
-
-    /* reset iterator counters */
-    memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-    /* register next timer thread */
-    thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                     thread_arg->vs->delay_loop);
-
-    close(thread->u.fd);
-    free(str_request);
-    return 0;
+    return epilog(thread,1,0,0);
   }
 
   /* Register read timeouted thread */
   thread_add_read(thread->master, http_response_thread, thread_arg, thread->u.fd,
                   thread_arg->svr->method->connection_to);
-
-  free(str_request);
   return 1;
 }
 
-/* HTTP checkers threads */
-int
-http_check_thread(struct thread *thread)
+/* WEB checkers threads */
+int http_check_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  REQ *req;
+  int ret = 1;
+
   int status;
 
-  thread_arg = THREAD_ARG(thread);
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
 
   status = tcp_socket_state(thread->u.fd, thread, http_check_thread);
 
   switch (status) {
     case connect_error:
-#ifdef DEBUG
-      syslog(LOG_DEBUG,"Error connecting HTTP server [%s:%d].",
+#ifdef _DEBUG_
+      syslog(LOG_DEBUG,"Error connecting server [%s:%d].",
                        inet_ntoa(thread_arg->svr->addr_ip),
                        ntohs(thread_arg->svr->addr_port));
 #endif
-
       /* check if server is currently alive */
       if (thread_arg->svr->alive) {
         smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : connection error <=\n\n");
+                   "DOWN", "=> CHECK failed on service : connection error <=\n\n");
         perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
       }
-
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
-
+      return epilog(thread,1,0,0);
       break;
 
     case connect_timeout:
-#ifdef DEBUG
-      syslog(LOG_DEBUG, "Timeout connecting HTTP server [%s:%d].",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port));
-#endif
-
-      /* check if server is currently alive */
-      if (thread_arg->svr->alive) {
-        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
-                   "DOWN", "=> HTTP CHECK failed on service : connection timeout <=\n\n");
-        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
-      }
-
-      /* reset iterator counters */
-      memset(thread_arg->checker_arg, 0, sizeof(struct http_thread_arg));
-
-      /* register next timer thread */
-      thread_add_timer(thread->master, http_connect_thread, thread_arg, 
-                       thread_arg->vs->delay_loop);
-
+      return timeout_epilog(thread,
+        "==> CHECK failed on service : connection timeout <=\n\n",
+        "connect, timeout");
       break;
 
-    case connect_success:
-      /* Remote HTTP server is connected.
-       * Register the next step thread http_request_thread.
-       */
-#ifdef DEBUG
-      syslog(LOG_DEBUG, "Remote HTTP server [%s:%d] connected.",
-                        inet_ntoa(thread_arg->svr->addr_ip),
-                        ntohs(thread_arg->svr->addr_port));
+    case connect_success: {
+      if (thread_arg->svr->method->type == SSL_GET_ID)
+        ret = ssl_connect(thread);
+        
+      if (ret) {
+        /* Remote WEB server is connected.
+         * Register the next step thread ssl_request_thread.
+         */
+#ifdef _DEBUG_
+        syslog(LOG_DEBUG, "Remote Web server [%s:%d] connected.",
+                          inet_ntoa(thread_arg->svr->addr_ip),
+                          ntohs(thread_arg->svr->addr_port));
 #endif
-      thread_add_write(thread->master, http_request_thread, thread_arg, thread->u.fd,
-                       thread_arg->svr->method->connection_to);
-      break;
+        thread_add_write(thread->master, http_request_thread, thread_arg, thread->u.fd,
+                         thread_arg->svr->method->connection_to);
+      } else {
+#ifdef _DEBUG_
+        syslog(LOG_DEBUG, "Connection problem host: [%s:%d].",
+                          inet_ntoa(thread_arg->svr->addr_ip),
+                          ntohs(thread_arg->svr->addr_port));
+        if (thread_arg->svr->method->type == SSL_GET_ID)
+          ssl_printerr(SSL_get_error(req->ssl, ret));
+#endif
+        return epilog(thread,1,0,0);
+      }
+    }
+    break;
   }
 
   return 0;
 }
 
-int
-http_connect_thread(struct thread *thread)
+int http_connect_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  int fd;
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  urls *fetched_url;
+  urls *pointerurls;
   enum connect_result status;
+  int fd;
+
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+
+  /* Find eventual url end */
+  pointerurls = thread_arg->svr->method->u.http_get->check_urls;
+  fetched_url = fetch_next_url(thread_arg);
+  thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+  if (fetched_url == NULL) {
+    /* All the url have been successfully checked.
+     * Check completed.
+     * check if server is currently alive.
+     */
+    if (!thread_arg->svr->alive) {
+      smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
+                 "UP", "=> CHECK succeed on service <=\n\n");
+      perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+    }
+    checker_arg->req = NULL;
+    return epilog(thread,1,0,0)+1;
+  }
 
-  thread_arg = THREAD_ARG(thread);
+  /* Allocate & clean request struct */
+  checker_arg->req = (REQ *)MALLOC(sizeof(REQ));
 
-  if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef DEBUG
-    syslog(LOG_DEBUG,"HTTP connect fail to create socket.");
+  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+#ifdef _DEBUG_
+    syslog(LOG_DEBUG, "WEB connection fail to create socket.");
 #endif
     return 0;
   }
index 8de5e4b..a02e8af 100644 (file)
@@ -5,9 +5,10 @@
  *
  * Part:        check_http.c include file.
  *
- * Version:     $Id: check_http.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check_http.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
- * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
  *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "ipwrapper.h"
 #include "scheduler.h"
 #include "layer4.h"
-#include "md5.h"
 
 /* global defs */
-#define SOCKET_ERROR   0
-#define SOCKET_SUCCESS 1
-
 #define MD5_BUFFER_LENGTH 32
 #define GET_REQUEST_BUFFER_LENGTH 128
 #define GET_BUFFER_LENGTH 2048
 #define MAX_BUFFER_LENGTH 4096
-#define LOGBUFFER_LENGTH 100
 
 /* http get processing command */
-#define GETCMD "GET %s HTTP/1.0\r\n\r\n"
-
-/* Prototypes defs */
-extern int http_connect_thread(struct thread *thread);
-
-extern void smtp_alert(struct thread_master *master,
-                       configuration_data *root,
-                       realserver *rserver,
-                       const char *subject,
-                       const char *body);
+#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
+                         "User-Agent:KeepAliveClient\r\n" \
+                         "Host: %s:%d\r\n\r\n"
+
+/* Define prototypes */
+extern int epilog(thread *thread, int metod, int t, int c);
+extern int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg);
+extern char *extract_html(char *buffer, int size_buffer);
+extern urls *fetch_next_url(thread_arg *thread_arg);
+extern int http_handle_response(thread *thread
+                                , unsigned char digest[16]
+                                , int empty_buffer);
+
+extern void smtp_alert(thread_master *
+                       , configuration_data *
+                       , realserver *
+                       , const char *
+                       , const char *);
 
 #endif
index 5a71b68..774af84 100644 (file)
@@ -6,9 +6,10 @@
  * 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 $
+ * Version:     $Id: check_misc.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
- * Author:      Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
  *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,8 +25,7 @@
 #include "check_misc.h"
 
 /* does this need to be threaded? */
-int
-misc_check_call(char* cmdline)
+int misc_check_call(char* cmdline)
 {
   int retval;
 
@@ -46,15 +46,14 @@ misc_check_call(char* cmdline)
   return retval;
 }
 
-int
-misc_check_thread(struct thread *thread)
+int misc_check_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
   int status;
 
   thread_arg = THREAD_ARG(thread);
 
-  status = misc_check_call(thread_arg->svr->method->misc_check_path);
+  status = misc_check_call(thread_arg->svr->method->u.misc_check_path);
 
   if (status == 0) {
     /* everything is good */
index d717344..8616dac 100644 (file)
@@ -5,9 +5,10 @@
  *
  * Part:        check_misc.c include file.
  *
- * Version:     $Id: check_misc.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check_misc.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
- * Author:      Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ * Author:      Alexandre Cassen, <acassen@linux-vs.org>
+ *              Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
  *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -33,6 +34,6 @@
 #include "smtp.h"
 
 /* Prototypes defs */
-extern int misc_check_thread(struct thread *thread);
+extern int misc_check_thread(thread *thread);
 
 #endif
diff --git a/check_ssl.c b/check_ssl.c
new file mode 100644 (file)
index 0000000..c6df174
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        SSL GET CHECK. Perform an ssl get query to a specified
+ *              url, compute a MD5 over this result and match it to the
+ *              expected value.
+ *
+ * Version:     $Id: check_ssl.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#include <openssl/err.h>
+#include "check_ssl.h"
+#include "memory.h"
+
+/* SSL primitives */
+/* Free an SSL context */
+void clear_ssl(SSL_DATA *ssl)
+{
+  if (ssl)
+    if (ssl->ctx)
+      SSL_CTX_free(ssl->ctx);
+}
+
+/* PEM password callback function */
+static int password_cb(char *buf, int num, int rwflag, void *userdata)
+{
+  SSL_DATA *ssl = (SSL_DATA *)userdata;
+
+  if (num < strlen(ssl->password)+1)
+    return(0);
+
+  strcpy(buf, ssl->password);
+  return(strlen(ssl->password));
+}
+
+/* Inititalize global SSL context */
+static BIO *bio_err = 0;
+static SSL_DATA *build_ssl_ctx(SSL_DATA *ssl)
+{
+  /* Library initialization */
+  SSL_library_init();
+
+  SSL_load_error_strings();
+  bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+
+  if (!ssl)
+    ssl = (SSL_DATA *)MALLOC(sizeof(ssl_data));
+
+  /* Initialize SSL context for SSL v2/3 */
+  ssl->meth = SSLv23_method();
+  ssl->ctx  = SSL_CTX_new(ssl->meth);
+
+  /* Load our keys and certificates */
+  if (strlen(ssl->keyfile) > 0)
+    if (!(SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->keyfile))) {
+      syslog(LOG_INFO, "SSL error : Cant load certificate file...");
+      return NULL;
+    }
+
+  /* Handle password callback using userdata ssl */
+  if (strlen(ssl->password) > 0) {
+    SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ssl);
+    SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb);
+  }
+
+  if (strlen(ssl->keyfile) > 0)
+    if (!(SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->keyfile, SSL_FILETYPE_PEM))) {
+      syslog(LOG_INFO, "SSL error : Cant load key file...");
+      return NULL;
+    }
+
+  /* Load the CAs we trust */
+  if (strlen(ssl->cafile) > 0)
+    if (!(SSL_CTX_load_verify_locations(ssl->ctx, ssl->cafile, 0))) {
+      syslog(LOG_INFO, "SSL error : Cant load CA file...");
+      return NULL;
+    }
+
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+  SSL_CTX_set_verify_depth(ssl->ctx,1);
+#endif
+
+  return ssl;
+}
+
+/*
+ * Initialize the SSL context, with or without specific
+ * configuration files.
+ */
+SSL_DATA *init_ssl_ctx(SSL_DATA *ssl)
+{
+  if (!(ssl = build_ssl_ctx(ssl))) {
+    syslog(LOG_INFO, "Error Initialize SSL, ctx Instance");
+    syslog(LOG_INFO, "  SSL  keyfile:%s", ssl->keyfile);
+    syslog(LOG_INFO, "  SSL password:%s", ssl->password);
+    syslog(LOG_INFO, "  SSL   cafile:%s", ssl->cafile);
+    syslog(LOG_INFO, "Terminate...\n");
+    clear_ssl(ssl);
+    return NULL;
+  }
+
+  return ssl;
+}
+
+/* Display SSL error to readable string */
+int ssl_printerr(int err)
+{
+  unsigned long extended_error = 0;
+  char *ssl_strerr;
+
+  switch (err) {
+    case SSL_ERROR_ZERO_RETURN:
+      syslog(LOG_DEBUG, "  SSL error: (zero return)");
+      break;
+    case SSL_ERROR_WANT_READ:
+      syslog(LOG_DEBUG, "  SSL error: (read error)");
+      break;
+    case SSL_ERROR_WANT_WRITE:
+      syslog(LOG_DEBUG, "  SSL error: (write error)");
+      break;
+    case SSL_ERROR_WANT_CONNECT:
+      syslog(LOG_DEBUG, "  SSL error: (connect error)");
+      break;
+    case SSL_ERROR_WANT_X509_LOOKUP:
+      syslog(LOG_DEBUG, "  SSL error: (X509 lookup error)");
+      break;
+    case SSL_ERROR_SYSCALL:
+      syslog(LOG_DEBUG, "  SSL error: (syscall error)");
+      break;
+    case SSL_ERROR_SSL: {
+      ssl_strerr = (char *)MALLOC(500);
+
+      extended_error = ERR_get_error();
+      ERR_error_string(extended_error, ssl_strerr);
+      syslog(LOG_DEBUG, "  SSL error: (%s)", ssl_strerr);
+      FREE(ssl_strerr);
+      break;
+    }
+  }
+  return 0;
+}
+
+int ssl_connect(thread *thread)
+{
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  REQ *req;
+
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
+
+  req->ssl = SSL_new(thread_arg->root->ssldata->ctx);
+  req->bio = BIO_new_socket(thread->u.fd, BIO_NOCLOSE);
+  SSL_set_bio(req->ssl, req->bio, req->bio);
+
+  return (SSL_connect(req->ssl) > 0)?1:0;
+}
+
+int ssl_send_request(SSL *ssl, char *str_request, int request_len)
+{
+  int err, r = 0;
+
+  while (1) {
+    err = 1;
+    r = SSL_write(ssl, str_request, request_len);
+    if (SSL_ERROR_NONE != SSL_get_error(ssl, r))
+      break;
+    err++;
+    if (request_len != r)
+      break;
+    err++;
+    break;
+  }
+  return (err == 3)?1:0;
+}
+
+/* Asynchronous SSL stream reader */
+int ssl_read_thread(thread *thread)
+{
+  thread_arg *thread_arg;
+  http_thread_arg *checker_arg;
+  unsigned char digest[16];
+  REQ *req;
+  int r = 0;
+
+  thread_arg  = THREAD_ARG(thread);
+  checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+  req         = checker_arg->req;
+
+  /* Handle read timeout */
+  if (thread->type == THREAD_READ_TIMEOUT) {
+    return timeout_epilog(thread,
+      "=> SSL CHECK failed on service : recevice data <=\n\n",
+      "SSL read");
+  }
+
+  /* read the SSL stream */
+  r = SSL_read(req->ssl, req->buffer+req->len, MAX_BUFFER_LENGTH-req->len);
+  req->error = SSL_get_error(req->ssl, r);
+
+  if (req->error) {
+
+    /* All the SSL streal has been parsed */
+    MD5_Final(digest, &req->context);
+    SSL_set_quiet_shutdown(req->ssl, 1); 
+
+    r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
+
+    if (r != 1) {
+      /* check if server is currently alive */
+      if (thread_arg->svr->alive) {
+        smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
+                   "DOWN", "=> SSL CHECK failed on service : cannot receive data <=\n\n");
+        perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+      }
+      return epilog(thread,1,0,0);
+    }
+
+    /* Handle response stream */
+    http_handle_response(thread, digest, (!req->extracted)?1:0);
+
+  } else if (r > 0 && req->error == 0) {
+
+    req->len += r;
+    if (!req->extracted) {
+       if ((req->extracted = extract_html(req->buffer, req->len))) { 
+         r = req->len-(req->extracted-req->buffer);
+         if (r) {
+           memcpy(req->buffer, req->extracted, r);
+           MD5_Update(&req->context, req->buffer, r);
+           r=0;
+         }
+         req->len = r;
+       } else {
+         /* minimize buffer using no 2*CR/LF found yet */
+         if (req->len > 3) {
+           memcpy(req->buffer, req->buffer + req->len - 3, 3);
+           req->len = 3;
+         }
+       }
+    } else {
+      if (req->len) {
+        MD5_Update(&req->context, req->buffer, req->len);
+        req->len = 0;
+      }
+    }
+
+    /*
+     * Register next ssl stream reader.
+     * Register itself to not perturbe global I/O multiplexer.
+     */
+    thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
+                    thread_arg->svr->method->connection_to);
+  }
+
+  return 0;
+}
diff --git a/check_ssl.h b/check_ssl.h
new file mode 100644 (file)
index 0000000..ab013ab
--- /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_http.c include file.
+ *
+ * Version:     $Id: check_http.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _SSL_H
+#define _SSL_H
+
+/* local includes */
+#include "check_http.h"
+
+/* Prototypes */
+extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
+extern void clear_ssl(SSL_DATA *ssl);
+extern int ssl_connect(thread *thread);
+extern int ssl_printerr(int err);
+extern int ssl_send_request(SSL *ssl, char *str_request, int request_len);
+extern int ssl_read_thread(thread *thread);
+
+#endif
index 26443b3..f9b6202 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        TCP checker.
  *
- * Version:     $Id: check_tcp.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check_tcp.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 
 #include "check_tcp.h"
 
-int
-tcp_check_thread(struct thread *thread)
+int tcp_check_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
   int status;
 
   thread_arg = THREAD_ARG(thread);
@@ -37,7 +36,7 @@ tcp_check_thread(struct thread *thread)
    */
   if (status == connect_success) {
 
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "TCP connection to [%s:%d] success.",
                       inet_ntoa(thread_arg->svr->addr_ip),
                       ntohs(thread_arg->svr->addr_port));
@@ -51,7 +50,7 @@ tcp_check_thread(struct thread *thread)
     }
 
   } else {
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "TCP connection to [%s:%d] failed !!!",
                       inet_ntoa(thread_arg->svr->addr_ip),
                       ntohs(thread_arg->svr->addr_port));
@@ -73,17 +72,16 @@ tcp_check_thread(struct thread *thread)
   return 0;
 }
 
-int
-tcp_connect_thread(struct thread *thread)
+int tcp_connect_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
   int fd;
   int status;
 
   thread_arg = THREAD_ARG(thread);
 
   if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "TCP connect fail to create socket.");
 #endif
     return 0;
index 1f852d7..52018a7 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        check_tcp.c include file.
  *
- * Version:     $Id: check_tcp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: check_tcp.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -36,6 +36,6 @@
 #include "smtp.h"
 
 /* Prototypes defs */
-extern int tcp_connect_thread(struct thread *thread);
+extern int tcp_connect_thread(thread *thread);
 
 #endif
index d781c0b..eed37cf 100644 (file)
@@ -12,6 +12,56 @@ global_defs {
    lvs_id LVS_DEVEL
 }
 
+;SSL {
+  password password
+  ca /etc/keepalived/root.pem
+  certificate /etc/keepalived/dh1024.pem
+  key /etc/keepalived/client.pem
+}
+
+vrrp_instance VI_1 {
+    state MASTER
+    interface eth0
+    virtual_router_id 51
+    priority 100
+    advert_int 1
+    authentication {
+        auth_type AH
+        auth_pass 1111
+    }
+    virtual_ipaddress {
+        192.168.200.16
+        192.168.200.17
+        192.168.200.18
+    }
+}
+
+virtual_server 192.168.200.100 443 {
+    delay_loop 6
+    lb_algo rr
+    lb_kind NAT
+    nat_mask 255.255.255.0
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.201.100 443 {
+        weight 1
+        SSL_GET {
+            url {
+              path /
+              digest ff20ad2481f97b1754ef3e12ecd3a9cc
+            }
+            url {
+              path /mrtg/
+              digest 9b3a0c85a887a256d6939da88aabd8cd
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+}
+
 virtual_server 10.10.10.2 1358 {
     delay_loop 6
     lb_algo rr 
diff --git a/genhash/AUTHORS b/genhash/AUTHORS
new file mode 100644 (file)
index 0000000..9434f73
--- /dev/null
@@ -0,0 +1,2 @@
+Alexandre Cassen <acassen@linux-vs.org>
+Jan Holmberg <jan@artech.se>
diff --git a/genhash/COPYING b/genhash/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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.
+
+    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.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/genhash/ChangeLog b/genhash/ChangeLog
new file mode 100644 (file)
index 0000000..2d6b8e7
--- /dev/null
@@ -0,0 +1,10 @@
+2001-11-29  Alexandre Cassen  <acassen@linux-vs.org>
+       * genhash 0.4.9 released.
+       * Rewrite the whole previous code
+       * Jan Holmberg, <jan@artech.se> and I added SSL support.
+       * Possibility to use specific SSL certificate.
+       * Added a command line parser using the popt library.
+       * Added error handling support.
+       * Review the MD5 computation.
+       * Added a dynamic buffer allocation for remote server
+         reply.
diff --git a/genhash/INSTALL b/genhash/INSTALL
new file mode 100644 (file)
index 0000000..2a2593d
--- /dev/null
@@ -0,0 +1,115 @@
+Needs
+=====
+
+  Before trying to compile genhash tool you need to install
+  OpenSSL 0.9.6b (http://www.openssl.org).
+
+Installation
+============
+
+  Simply 'make' & 'make install'
+
+Utilisation
+===========
+
+  The genhash tool give you the ability to generate MD5 digest
+  from remote HTTP/HTTPS server connected.
+
+  The global synopsis for the tool is :
+
+  [user@lvs]$ genhash --help
+  genhash Version 0.4.9 (30/11, 2001)
+  Usage:
+    genhash -s server-address -p port -u url
+    genhash -S -K priv-key-file -P pem-password -s server-address -p port -u url
+    genhash -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url
+    genhash -h
+    genhash -v
+
+  Commands:
+  Either long or short options are allowed.
+    genhash --use-ssl         -S       Use SSL connection to remote server.
+    genhash --server          -s       Use the specified remote server address.
+    genhash --port            -p       Use the specified remote server port.
+    genhash --url             -u       Use the specified remote server url.
+    genhash --use-private-key -K       Use the specified SSL private key.
+    genhash --use-password    -P       Use the specified SSL private key password.
+    genhash --use-certificate -C       Use the specified SSL Certificate file.
+    genhash --help            -h       Display this short inlined help screen.
+    genhash --version         -v       Display the version number
+
+  Imagine we have a remote HTTP/HTTPS server owning the IP address 192.168.200.10.
+  We want to generate a MD5SUM over the server root url (/).
+  To proceed, simply use :
+
+  [user@lvs]$ genhash -s 192.168.200.10 -p 80 -u / 
+  -----------------------[    HTTP Header Buffer    ]-----------------------
+  0000  48 54 54 50 2f 31 2e 31 - 20 32 30 30 20 4f 4b 0d   HTTP/1.1 200 OK.
+  0010  0a 44 61 74 65 3a 20 57 - 65 64 2c 20 32 38 20 4e   .Date: Wed, 28 N
+  ..........................................................................
+  -----------------------[ HTTP Header Ascii Buffer ]-----------------------
+  HTTP/1.1 200 OK
+  ..............
+  -----------------------[       HTML Buffer        ]-----------------------
+  0000  3c 21 44 4f 43 54 59 50 - 45 20 48 54 4d 4c 20 50   <!DOCTYPE HTML P
+  0010  55 42 4c 49 43 20 22 2d - 2f 2f 57 33 43 2f 2f 44   UBLIC "-//W3C//D
+  ..........................................................................
+  -----------------------[    HTML MD5 resulting    ]-----------------------
+  0000  ff 20 ad 24 81 f9 7b 17 - 54 ef 3e 12 ec d3 a9 cc   . .$..{.T.>.....
+  -----------------------[ HTML MD5 final resulting ]-----------------------
+  FF20AD2481F97B1754EF3E12ECD3A9CC
+
+  => So the Hash value generated for the remote HTTP root URL is :
+     http://192.168.200.10/ is FF20AD2481F97B1754EF3E12ECD3A9CC
+
+  Genhash can generate hash values over SSL content. Using the same sample
+  we will obtain :
+  [user@lvs]$ genhash -S -s 192.168.200.10 -p 443 -u / 
+  -----------------------[    HTTP Header Buffer    ]-----------------------
+  0000  48 54 54 50 2f 31 2e 31 - 20 32 30 30 20 4f 4b 0d   HTTP/1.1 200 OK.
+  0010  0a 44 61 74 65 3a 20 57 - 65 64 2c 20 32 38 20 4e   .Date: Wed, 28 N
+  ..........................................................................
+  -----------------------[ HTTP Header Ascii Buffer ]-----------------------
+  HTTP/1.1 200 OK
+  ..............
+  -----------------------[       HTML Buffer        ]-----------------------
+  0000  3c 21 44 4f 43 54 59 50 - 45 20 48 54 4d 4c 20 50   <!DOCTYPE HTML P
+  0010  55 42 4c 49 43 20 22 2d - 2f 2f 57 33 43 2f 2f 44   UBLIC "-//W3C//D
+  ..........................................................................
+  -----------------------[    HTML MD5 resulting    ]-----------------------
+  0000  ff 20 ad 24 81 f9 7b 17 - 54 ef 3e 12 ec d3 a9 cc   . .$..{.T.>.....
+  -----------------------[ HTML MD5 final resulting ]-----------------------
+  FF20AD2481F97B1754EF3E12ECD3A9CC
+
+  => So the Hash value generated for the remote HTTP root URL is :
+     https://192.168.200.10/ is FF20AD2481F97B1754EF3E12ECD3A9CC
+
+  => The same as http since the document root is a common location for
+     HTTP & HTTPS (in our sample).
+
+
+  In addition with this SSL support, we have added the capability to use
+  specific ssl private key and ssl certificate. Note that the private key
+  need to be generated into the PEM format. In our sample we have generated
+  the SSL file using the following openssl command lines :
+
+  [user@lvs]$ openssl genrsa -des3 -out ssl.key 1024
+    => we use the PEM password : password (really secure :) )
+  [user@lvs]$ openssl req -new -key ssl.key -out ssl.csr
+  [user@lvs]$ openssl req -x509 -key ssl.key -in ssl.csr -out ssl.crt
+  [user@lvs]$ cat ssl.key ssl.crt > ssl.pem
+
+  Then we perform a hash computation using this specific SSL file :
+
+  [user@lvs]$ genhash --use-ssl \
+                      --server=192.168.201.100 --port=443 --url=/ \
+                      --use-private-key=ssl.pem \
+                      --use-password=password \
+                      --use-certificate=ssl.crt
+  ..........................................................................
+  -----------------------[ HTML MD5 final resulting ]-----------------------
+  FF20AD2481F97B1754EF3E12ECD3A9CC
+
+
+Have fun with it !
+Alexandre
index 2f0e224..addb953 100644 (file)
@@ -1,25 +1,22 @@
 # Makefile
-# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
+# Alexandre Cassen <acassen@linux-vs.org>
 
-EXEC= genhash
-CC= gcc
-CFLAGS= -Wall
-DEFS= genhash.h md5.h
-OBJECTS= md5.o genhash.o
-INCLUDE= -I/usr/src/linux/include
-.c.o:  
-       $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+EXEC = genhash
 
-all:   $(EXEC)
-       strip $(EXEC)
-       @echo ""
-       @echo "Make complete"
+CC = gcc
+CFLAGS = -Wall -Wunused -Wstrict-prototypes -g -O2
+#LD = -lssl -lcrypto -dynamic -lpopt
+LD = -lssl -lcrypto -lpopt
 
-$(EXEC):       $(OBJECTS) $(DEFS)
-       $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+OBJS = main.o client.o common.o
 
+all:   genhash
+       strip genhash
+       @echo ""
+       @echo "Make complete"
+$(EXEC): $(OBJS)
+       $(CC) $(OBJS) -o $(EXEC) $(LD)
 clean:
        rm -f core *.o $(EXEC)
-
 install:       
        install -m 755 genhash /usr/bin/
diff --git a/genhash/README b/genhash/README
new file mode 100644 (file)
index 0000000..263baf3
--- /dev/null
@@ -0,0 +1,10 @@
+The main goal of the keepalived project is to add a strong & robust
+keepalive facility to the Linux Virtual Server project.
+It implements a multilayer TCP/IP stack checks. Keepalived implements
+a framework based on three family checks : Layer3, Layer4 & Layer5. 
+This framework gives the daemon the ability of checking a LVS server 
+pool states. Keepalived can be sumarize as a LVS driving daemon.
+
+To generate MD5SUM digest the this tool (genhash) is used.
+
+Keepalived is free software. See the file COPYING for copying conditions.
diff --git a/genhash/TODO b/genhash/TODO
new file mode 100644 (file)
index 0000000..bffe175
--- /dev/null
@@ -0,0 +1,3 @@
+* Create a generic function to handle remote server reply.
+  That way we will remove duplicate code for read reply.
+* beautifull the code.
diff --git a/genhash/client.c b/genhash/client.c
new file mode 100644 (file)
index 0000000..a7aa110
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ *
+ * Part:        Layer4 global functions.
+ *
+ * Version:     $Id: client.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              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 "client.h"
+
+int tcp_connect(int fd, char *host, int port)
+{
+  int long_inet = sizeof(struct sockaddr_in);
+  struct sockaddr_in adr_serv;
+  struct hostent *ip_serv;
+  int arglen;
+  struct timeval tv;
+  fd_set wfds;
+  int rc, val;
+
+  /* Proceed remote hostname */
+  memset(&ip_serv, 0, sizeof(struct hostent));
+  if ((ip_serv = gethostbyname(host)) == NULL)
+    return TCP_RESOLV_ERROR;
+
+  /* Fill in connection structure */
+  memset(&adr_serv, 0, long_inet);
+  adr_serv.sin_family = AF_INET;
+  adr_serv.sin_port = htons(port);
+  adr_serv.sin_addr = *(struct in_addr*)ip_serv->h_addr;
+
+  /* Set read/write socket nonblock */
+  val = fcntl(fd, F_GETFL);
+  fcntl(fd, F_SETFL, val | O_NONBLOCK);
+
+  /* Connect the remote host */
+  rc = connect(fd, (struct sockaddr *)&adr_serv, long_inet);
+  if (rc == -1) {
+    if (errno !=  EINPROGRESS) {
+      rc = errno;
+      return TCP_CONNECT_ERROR;
+    }
+  }
+
+  /* Timeout settings */
+  tv.tv_sec = SOCKET_TIMEOUT_READ;
+  tv.tv_usec = 0;
+  FD_ZERO(&wfds);
+  FD_SET(fd, &wfds);
+
+  rc = select(fd+1, NULL, &wfds, NULL, &tv);
+  if (!FD_ISSET(fd, &wfds)) 
+    return TCP_WRITE_TIMEOUT;
+
+  if (rc <= 0) return TCP_SELECT_ERROR;
+
+  rc = 0;
+  arglen = sizeof(int);
+  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &rc, &arglen) < 0)
+    rc = errno;
+  if (rc) return TCP_CONNECT_FAILED;
+
+  /* Restore socket parameters */
+  fcntl(fd, F_SETFL, val);
+
+  return TCP_CONNECT_SUCCESS;
+}
+
+int tcp_send(int fd, char *request, int len)
+{
+  if (send(fd, request, len, 0) == -1)
+    return TCP_SEND_ERROR;
+  return 0;
+}
+
+int tcp_read_to(int fd)
+{
+  struct timeval tv;
+  fd_set rfds;
+
+  /* Timeout settings */
+  tv.tv_sec = SOCKET_TIMEOUT_READ;
+  tv.tv_usec = 0;
+  FD_ZERO(&rfds);
+  FD_SET(fd, &rfds);
+
+  /* attempt read data */
+  select(fd+1, &rfds, NULL, NULL, &tv);
+  if (!FD_ISSET(fd, &rfds)) 
+    return TCP_READ_TIMEOUT;
+  return 0;
+}
+
+int tcp_sock(void)
+{
+  int fd;
+  struct sockaddr_in adr_local;
+
+  if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) return (-1);
+  memset(&adr_local, 0, sizeof(struct sockaddr_in));
+  adr_local.sin_family = AF_INET;
+  adr_local.sin_port = htons(0);
+  adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
+
+  if (bind(fd, (struct sockaddr *)&adr_local, sizeof(struct sockaddr_in))) return (-1);
+
+  return(fd);
+}
diff --git a/genhash/client.h b/genhash/client.h
new file mode 100644 (file)
index 0000000..137eb5f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ *
+ * Part:        client.c include file.
+ *
+ * Version:     $Id: client.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              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 _CLIENT_H
+#define _CLIENT_H
+
+/* System includes */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* Socket timeout */
+#define SOCKET_TIMEOUT_READ    3
+#define SOCKET_TIMEOUT_WRITE   3
+
+/* Return codes */
+/* systems predefined ret codes */
+#define OUT_OF_MEMORY          (1 << 0)
+
+/* TCP predefined ret codes */
+#define TCP_BIND_ERROR         (1 << 1)
+#define TCP_RESOLV_ERROR       (1 << 2)
+#define TCP_CONNECT_ERROR      (1 << 3)
+#define TCP_CONNECT_SUCCESS    (1 << 4)
+#define TCP_WRITE_TIMEOUT      (1 << 5)
+#define TCP_SELECT_ERROR       (1 << 6)
+#define TCP_CONNECT_FAILED     (1 << 7)
+#define TCP_SEND_ERROR         (1 << 8)
+#define TCP_READ_TIMEOUT       (1 << 9)
+
+/* Upper Layer - HTTP predefined ret codes */
+#define HTTP_GET_SUCCESS       (1 << 10)
+
+/* Upper Layer - SSL predefined ret codes */
+#define SSL_WRITE_ERROR                (1 << 11)
+#define SSL_INCOMPLETE_WRITE   (1 << 12)
+#define SSL_READ_ERROR         (1 << 13)
+#define SSL_SHUTDOWN_FAILED    (1 << 14)
+#define SSL_GET_SUCCESS                (1 << 15)
+
+/* Prototypes */
+extern int tcp_connect(int fd, char *host, int port);
+extern int tcp_send(int fd, char *request, int len);
+extern int tcp_read_to(int fd);
+extern int tcp_sock(void);
+
+#endif
+
diff --git a/genhash/common.c b/genhash/common.c
new file mode 100644 (file)
index 0000000..ead37da
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ *
+ * Part:        Common SSL functions.
+ *
+ * Version:     $Id: common.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#include <openssl/err.h>
+#include "common.h"
+
+static BIO *bio_err = 0;
+static char *pass;
+
+/* A simple error and exit routine*/
+int err_exit(char *string)
+{
+  fprintf(stderr, "%s\n", string);
+  exit(0);
+}
+
+/* Print SSL errors and exit*/
+int berr_exit(char *string)
+{
+  BIO_printf(bio_err, "%s\n", string);
+  ERR_print_errors(bio_err);
+  exit(0);
+}
+
+/*The password code is not thread safe*/
+static int password_cb(char *buf, int num, int rwflag, void *userdata)
+{
+  if (num < strlen(pass)+1)
+    return(0);
+
+  strcpy(buf, pass);
+  return(strlen(pass));
+}
+
+static void sigpipe_handle(int x) {
+}
+
+/* SSL context initializer */
+SSL_CTX *initialize_ctx(char *keyfile, char *password, char *cafile)
+{
+  SSL_METHOD *meth;
+  SSL_CTX *ctx;
+    
+  if (!bio_err){
+    /* Global system initialization*/
+    SSL_library_init();
+    SSL_load_error_strings();
+      
+    /* An error write context */
+    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+  }
+
+  /* Set up a SIGPIPE handler */
+  signal(SIGPIPE, sigpipe_handle);
+    
+  /* Create our context*/
+  meth = SSLv23_method();
+  ctx = SSL_CTX_new(meth);
+
+  /* Load our keys and certificates*/
+  if (keyfile)
+    if(!(SSL_CTX_use_certificate_chain_file(ctx, keyfile)))
+      berr_exit("Can't read certificate file");
+
+  if (password) {
+    pass = password;
+    SSL_CTX_set_default_passwd_cb(ctx, password_cb);
+  }
+  if (keyfile)
+    if(!(SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM)))
+      berr_exit("Can't read key file");
+
+  /* Load the CAs we trust*/
+  if (cafile)
+    if(!(SSL_CTX_load_verify_locations(ctx, cafile, 0)))
+      berr_exit("Can't read CA list");
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+  SSL_CTX_set_verify_depth(ctx,1);
+#endif
+
+  return ctx;
+}
+     
+void destroy_ctx(SSL_CTX *ctx)
+{
+  SSL_CTX_free(ctx);
+}
diff --git a/genhash/common.h b/genhash/common.h
new file mode 100644 (file)
index 0000000..116b897
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ *
+ * Part:        common.c include file.
+ *
+ * Version:     $Id: common.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              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 _COMMON_H
+#define _COMMON_H
+
+/* System includes */
+#include <string.h>
+#include <signal.h>
+#include <openssl/ssl.h>
+
+/* prototypes */
+extern int berr_exit(char *string);
+extern int err_exit(char *string);
+extern SSL_CTX *initialize_ctx(char *keyfile, char *password, char *cafile);
+extern void destroy_ctx(SSL_CTX *ctx);
+
+#ifndef ALLOW_OLD_VERSIONS
+#if(OPENSSL_VERSION_NUMBER < 0x00905100L)
+#error "Must use OpenSSL 0.9.6 or later"
+#endif
+#endif
+
+#endif
diff --git a/genhash/genhash.c b/genhash/genhash.c
deleted file mode 100644 (file)
index 715bed8..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/* 
- * Soft:        Genhash compute MD5 digest from a HTTP get result. This
- *              program is use to compute hash value that you will add
- *              into the /etc/keepalived/keepalived.conf for the 
- *              HTTP_GET_CHECK.
- *  
- * Version:     $Id: keepalived.c,v 0.3.0 2001/02/10 $
- * 
- * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- *              Alexandre Cassen : 2001/03/27 :
- *               <+> Use non blocking socket.
- *
- *              Alexandre Cassen : 2000/12/09      Initial release
- *               
- *              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 "genhash.h"
-
-void print_buffer(int count, char *buff)
-{
-  int i,j,c;
-  int printnext=1;
-
-  if(count) {
-    if(count%16)
-      c=count+(16-count%16);
-    else c=count;
-  } else
-    c=count;
-
-  for(i=0;i<c;i++) {
-    if(printnext) { 
-      printnext--;
-      printf("%.4x ",i&0xffff);
-    }
-    if(i<count)
-      printf("%3.2x",buff[i]&0xff);
-    else
-      printf("   ");
-    if(!((i+1)%8)) {
-      if((i+1)%16)
-        printf(" -");
-      else {
-        printf("   ");
-        for(j=i-15;j<=i;j++)
-          if(j<count) {
-            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
-              printf("%c",buff[j]&0xff);
-            else printf(".");
-          } else printf(" ");
-        printf("\n"); printnext=1;
-      }
-    }
-  }
-}
-
-char *extract_html(char *buffer, int size_buffer)
-{
-  char *end=buffer+size_buffer;
-
-  while ( buffer < end && !(*buffer++ == '\n' &&
-                          (*buffer == '\n' || (*buffer++ == '\r' && *buffer =='\n'))));
-
-  if (*buffer == '\n') return buffer+1;
-  return NULL;
-}
-
-int new_sock(int type)
-{
-  int sd;
-  struct sockaddr_in adr_local;
-  if ( (sd = socket(AF_INET, type, 0)) == -1 ) return (-1);
-
-  bzero(&adr_local, sizeof(struct sockaddr_in));
-  adr_local.sin_family = AF_INET;
-  adr_local.sin_port = htons(0);
-  adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
-
-  if ( bind(sd, (struct sockaddr *)&adr_local, sizeof(struct sockaddr_in)) ) return (-1);
-
-  return (sd);
-}
-
-int HTTP_GET(char *IP_DST, unsigned short int PORT_DST, char *URL, char *buffer)
-{
-  register int sdesc;
-  int long_inet;
-  int rcv_buffer_size=0;
-  long total_length=0;
-  char *str_request;
-  char *buffertmp;
-  struct hostent *ip_serv;
-  struct sockaddr_in adr_serv;
-  struct timeval tv;
-  fd_set rfds, wfds;
-  int rc,val;
-  int arglen;
-  str_request=(char *)malloc(GET_BUFFER_LENGTH);
-  buffertmp=(char *)malloc(RCV_BUFFER_LENGTH);
-  memset(buffertmp,0,RCV_BUFFER_LENGTH);
-
-  sprintf(str_request,GETCMD,URL);
-
-  if ( (sdesc=new_sock(SOCK_STREAM)) == -1 ) {
-    printf("-[ Can not bind remote address ]-\n");
-    free(str_request);
-    free(buffertmp);
-    return(ERROR_SOCKET);
-  }
-
-  long_inet = sizeof(struct sockaddr_in);
-
-  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
-    printf("-[ Can not resolve remote host ]-\n");
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  bzero(&adr_serv,long_inet);
-  adr_serv.sin_family=ip_serv->h_addrtype;
-  bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
-  adr_serv.sin_port=htons(PORT_DST);
-
-  /* Set read/write socket timeout */
-  val=fcntl(sdesc, F_GETFL);
-  fcntl(sdesc, F_SETFL, val | O_NONBLOCK);
-
-  /* Connect the remote host */
-  if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1 ) {
-    switch (errno) {
-      case ETIMEDOUT:
-      case EINTR:
-      case EHOSTUNREACH:
-        printf("-[ Connect error : Timeout ]-\n");
-        break;
-      case ECONNREFUSED:
-        printf("-[ Connect error : Connectiono refused ]-\n");
-        break;
-      case ENETUNREACH:
-        printf("-[ Connect error : Network unreachable ]-\n");
-        break;
-      case EINPROGRESS:
-        printf("-[ NONBLOCK socket connection in progress ]-\n");
-        goto next;
-      default:
-        printf("-[ Connect error : Error code %d (%s) ]-\n",errno,strerror(errno));
-    }
-
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-next:
-  /* Timeout settings */
-  tv.tv_sec=SOCKET_TIMEOUT_READ;
-  tv.tv_usec=0;
-  FD_ZERO(&rfds);
-  FD_ZERO(&wfds);
-  FD_SET(sdesc,&rfds);
-  FD_SET(sdesc,&wfds);
-
-  rc = select(sdesc+1,NULL,&wfds,NULL,&tv);
-  if (!FD_ISSET(sdesc,&wfds)) {
-    printf("-[ Timeout writing data ]-\n");
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  if (rc <= 0) {
-    printf("-[ select() bad returned descriptor ]-\n");
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  rc = 0;
-  arglen=sizeof(int);
-  if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
-    rc = errno;
-
-  if (rc) {
-    printf("-[ Connection failed - error : %d (%s) ]-\n",rc,strerror(rc));
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  if (send(sdesc,str_request,strlen(str_request),0) == -1) {
-    printf("-[ Can not send data to remote host ]-\n");
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  /* Proceed the HTTP server reply */
-  select(sdesc+1,&rfds,NULL,NULL,&tv);
-  if (!FD_ISSET(sdesc,&rfds)) {
-    printf("-[ Timeout reading data ]-\n");
-    free(str_request);
-    free(buffertmp);
-    close(sdesc);
-    return(ERROR_SOCKET);
-  }
-
-  while((rcv_buffer_size = read(sdesc,buffertmp,RCV_BUFFER_LENGTH)) != 0) {
-    if (rcv_buffer_size == -1) {
-      if(errno == EAGAIN) goto end;
-      free(str_request);
-      free(buffertmp);
-      close(sdesc);
-      return(ERROR_SOCKET);
-    }
-    printf("-[ Reading data from remote host ]-\n");
-    memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
-    memset(buffertmp,0,RCV_BUFFER_LENGTH);
-    total_length += rcv_buffer_size;
-  }
-
-end:
-  close(sdesc);
-  free(str_request);
-  free(buffertmp);
-  return(total_length);
-}
-
-
-int main(int argc, char **argv)
-{
-  char *buffer_http;
-  char *buffer_html;
-  int buffer_http_size=0;
-  char *MDResult;
-  md5_state_t state;
-  md5_byte_t digest[16];
-  int di;
-
-  printf(PROG" v"VERSION"\n");
-  if (argc < 4) {
-      printf("Usage: %s <IP address> <TCP port> <url path>\n", argv[0]);
-      return(0);
-  }
-
-  buffer_http=(char *)malloc(RCV_BUFFER_LENGTH);
-  MDResult=(char *)malloc(16*2*sizeof(char *));
-  memset(buffer_http,0,RCV_BUFFER_LENGTH);
-  memset(MDResult,0,16*2*sizeof(char *));
-
-  buffer_http_size=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
-  buffer_html=extract_html(buffer_http,buffer_http_size);
-
-  if(buffer_http_size > 0) {
-    printf("---------------------------[ Received Buffer ]----------------------------\n");
-    printf("%s\n",buffer_http);
-
-    printf("--------------------------[ HTTP Header Buffer ]--------------------------\n");
-    print_buffer(buffer_html-buffer_http,buffer_http);
-
-    printf("------------------------------[ HTML Buffer ]-----------------------------\n");
-    print_buffer(buffer_http_size-(buffer_html-buffer_http),buffer_html);
-
-    printf("----------------------------[ HTML MD5 resulting ]------------------------\n");
-    md5_init(&state);
-    md5_append(&state, buffer_html,buffer_http_size-(buffer_html-buffer_http));
-    md5_finish(&state,digest);
-
-    for (di=0; di < 16; ++di)
-      sprintf(MDResult+2*di,"%02x",digest[di]);
-
-    printf("MD5 Digest : %s\n",MDResult);
-  } else {
-    printf("No buffer returned...\n");
-  }
-
-  free(MDResult);
-  free(buffer_http);
-  return(1);
-}
diff --git a/genhash/genhash.h b/genhash/genhash.h
deleted file mode 100644 (file)
index fd0ed9f..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 
- * Soft:        Genhash compute MD5 digest from a HTTP get result. This
- *              program is use to compute hash value that you will add
- *              into the /etc/keepalived/keepalived.conf for the 
- *              HTTP_GET_CHECK.
- *
- * Part:        genhash.c include file.
- *  
- * Version:     $Id: keepalived.c,v 0.2.0 2000/12/09 $
- * 
- * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- *              Alexandre Cassen      :       Initial release
- *
- *              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 GENHASH_H
-#define GENHASH_H
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <termios.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <linux/if_ether.h>
-#include <netinet/tcp.h>
-#include <netinet/ip_icmp.h>
-#include <fcntl.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include "md5.h"
-
-#define GETCMD "GET %s HTTP/1.0\r\n\r\n"
-
-/* Socket Timeout */
-#define SOCKET_TIMEOUT_READ    3
-#define SOCKET_TIMEOUT_CONNECT 3
-
-/* Sockets connection errors codes */
-#define ERROR_SOCKET        0
-
-/* Data buffer length description */
-#define GET_BUFFER_LENGTH   180
-#define RCV_BUFFER_LENGTH   1024
-
-/* Build version */
-#define PROG    "genhash"
-#define VERSION "0.2.3 (27/03, 2001), Alexandre Cassen"
-
-#endif
diff --git a/genhash/main.c b/genhash/main.c
new file mode 100644 (file)
index 0000000..e7bafc9
--- /dev/null
@@ -0,0 +1,542 @@
+/* 
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ * 
+ * Part:        Main part performing get request and MD5SUM over content.
+ *
+ * Version:     $Id: main.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */     
+
+#include "main.h"
+#include "common.h"
+#include "client.h"
+
+/* Dump a buffer (ASCII or Binary) */
+static void print_buffer(int count, char *buff)
+{
+  int i,j,c;
+  int printnext=1;
+
+  if(count) {
+    if(count%16)
+      c=count+(16-count%16);
+    else c=count;
+  } else
+    c=count;
+
+  for(i=0;i<c;i++) {
+    if(printnext) { 
+      printnext--;
+      printf("%.4x ",i&0xffff);
+    }
+    if(i<count)
+      printf("%3.2x",buff[i]&0xff);
+    else
+      printf("   ");
+    if(!((i+1)%8)) {
+      if((i+1)%16)
+        printf(" -");
+      else {
+        printf("   ");
+        for(j=i-15;j<=i;j++)
+          if(j<count) {
+            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
+              printf("%c",buff[j]&0xff);
+            else printf(".");
+          } else printf(" ");
+        printf("\n"); printnext=1;
+      }
+    }
+  }
+}
+
+/* Allocate & clean a buffer */
+static char *xmalloc(const int size)
+{
+  char *buffer;
+
+  buffer = (char *)malloc(size);
+  if (!buffer) return NULL;
+  memset(buffer, 0, size);
+
+  return buffer;
+}
+
+/* Return the html header from a global HTTP buffer */
+static char *extract_html(char *buffer, int size_buffer)
+{
+  char *end=buffer+size_buffer;
+
+  while ( buffer < end && !(*buffer++ == '\n' &&
+                          (*buffer == '\n' || (*buffer++ == '\r' && *buffer =='\n'))));
+
+  if (*buffer == '\n') return buffer+1;
+  return NULL;
+}
+
+/* Build the GET request */
+static char *build_request(REQ* req)
+{
+  char *request;
+  int request_len = 0;
+
+  request_len = strlen(REQUEST_TEMPLATE) + strlen(req->host) + 12;
+  request = xmalloc(request_len);
+  if (!request) return NULL;
+
+  snprintf(request, request_len
+                  , REQUEST_TEMPLATE
+                  , req->url
+                  , req->host
+                  , req->port);
+  return request;
+}
+
+static int https_request(SSL *ssl, REQ *req)
+{
+  char *request = NULL;
+  int r, i, e = 0;
+  int request_len;
+  char *extracted;      
+  unsigned char digest[16];
+  MD5_CTX context;
+
+  /* Build the SSL request */
+  request = build_request(req);
+  if (!request) return OUT_OF_MEMORY;
+  request_len = strlen(request);
+
+  /* Send the SSL request */
+  r = SSL_write(ssl, request, request_len);
+  if (SSL_ERROR_NONE != SSL_get_error(ssl, r)) {
+    free(request);
+    return SSL_WRITE_ERROR;
+  }
+
+  /* Test for eventual imcomplete SSL write */
+  if (request_len != r) {
+    free(request);
+    return SSL_INCOMPLETE_WRITE;
+  }
+  /* Init MD5 context */
+  MD5_Init(&context);
+  extracted = NULL;
+  req->len  = 0;
+  e         = 0;
+
+  /* 
+   * Now read the server's response, assuming
+   * that it's terminated by a close.
+   *
+   * FIXME: Create a function to read data from remote
+   *        server instead of code duplication.
+   */
+  printf(HTTP_HEADER_HEXA);
+
+  while (!e) {
+    r = SSL_read(ssl, req->buffer+req->len, req->max-req->len);
+    e = SSL_get_error(ssl, r);
+    if (e != SSL_ERROR_NONE) break;
+    if (r > 0 && e == 0) {
+      req->len +=r;
+      /* Only header yet ? */
+      if (!extracted) {
+        /* Found something more than header ? */
+        if ((extracted = extract_html(req->buffer, req->len))) {
+          r = req->len-(extracted-req->buffer);
+          if (r) { 
+            print_buffer(r, req->buffer);
+            printf(HTTP_HEADER_ASCII);
+            for (i=0; i < extracted-req->buffer; i++)
+              printf("%c", req->buffer[i]);
+            printf("\n");
+            printf(HTML_HEADER_HEXA);
+            memcpy(req->buffer,extracted,r);
+            MD5_Update(&context, req->buffer, r);
+            r = 0;
+          }
+          req->len = r;
+        } else {
+          if ( req->len > 3 ) {
+            print_buffer(req->len - 3 , req->buffer);
+            printf(HTTP_HEADER_ASCII);
+            for (i=0; i < req->len -3  ; i++)
+             printf("%c", req->buffer[i]);
+            printf("\n");
+            printf(HTML_HEADER_HEXA);
+            memcpy( req->buffer, req->buffer+req->len-3, 3);
+            req->len = 3;
+          }
+        }
+      } else {
+        if ( req -> len ) {
+          print_buffer(req->len, req->buffer);
+          MD5_Update(&context, req->buffer, req->len);
+          req->len = 0;
+        }
+      } 
+    }  
+  }
+
+  /* Error handling */
+  if (e != SSL_ERROR_ZERO_RETURN && e != SSL_ERROR_SYSCALL) {
+    free(request);
+    return SSL_READ_ERROR;
+  }
+
+  if (e == SSL_ERROR_ZERO_RETURN)  
+  if (SSL_shutdown(ssl) != 1) {
+    free(request);
+    return SSL_SHUTDOWN_FAILED;
+  }
+
+  if (e != SSL_ERROR_SYSCALL)
+    SSL_free(ssl);
+
+  MD5_Final(digest, &context);
+  printf(HTML_MD5);
+  print_buffer(16, digest);
+
+  printf(HTML_MD5_FINAL);
+  for (r=0; r<16; r++)
+    printf("%02x", digest[r]);
+  printf("\n\n");
+
+  free(request);
+  return SSL_GET_SUCCESS;
+}
+
+/*
+ * Connect a remote SSL server and generate a MD5SUM
+ * Upon the remote HTML content returned.
+ */
+static int genhash_ssl(REQ * req)
+{
+  SSL_CTX *ctx;
+  SSL *ssl;
+  BIO *sbio;
+  int retcode = 0;
+  /* SSL context initialization */
+  ctx = initialize_ctx(req->keyfile, req->password, req->cafile);
+
+  /* TCP socket creation */
+  req->fd = tcp_sock();
+  if (req->fd == -1) {
+    destroy_ctx(ctx);
+    return TCP_BIND_ERROR;
+  }
+
+  /* TCP connect remote host */
+  retcode = tcp_connect(req->fd, req->host, req->port);
+  if (retcode != TCP_CONNECT_SUCCESS) goto end;
+
+  /* Create the SSL context */
+  ssl = SSL_new(ctx);
+  sbio = BIO_new_socket(req->fd, BIO_NOCLOSE);
+  SSL_set_bio(ssl, sbio, sbio);
+
+  /* Connect remote SSL server */
+  if (SSL_connect(ssl) <= 0) 
+    return -2;
+
+  /* Proceed the SSL server reply */
+  retcode = https_request(ssl, req);
+
+end:
+  /* Shutdown the socket */
+  destroy_ctx(ctx);
+  close(req->fd);
+  return(retcode);
+}
+
+/*
+ * Connect a remote HTTP server and generate a MD5SUM
+ * Upon the remote HTML content returned.
+ */
+static int genhash_http(REQ *req)
+{
+  int request_len = 0;
+  char *request = NULL;
+  char *buffertmp = NULL; 
+  int retcode = 0;
+  int r;
+  char *extracted;      
+  unsigned char digest[16];
+  MD5_CTX context;
+
+  /* Temporary get buffer allocation */
+  buffertmp = xmalloc(RCV_BUFFER_LENGTH);
+  if (!buffertmp) {
+    free(request);
+    return OUT_OF_MEMORY;
+  }
+
+  /* Build the HTTP request */
+  request = build_request(req);
+  if (!request) {
+    free(buffertmp);
+    return OUT_OF_MEMORY;
+  }
+  request_len = strlen(request);
+
+  /* TCP socket creation */
+  req->fd = tcp_sock();
+  if (req->fd == -1) {
+    free(request);
+    free(buffertmp);
+    return TCP_BIND_ERROR;
+  }
+
+  /* TCP connect remote host */
+  retcode = tcp_connect(req->fd, req->host, req->port);
+  if (retcode != TCP_CONNECT_SUCCESS) goto error;
+
+  /* Send the HTTP request */
+  retcode = tcp_send(req->fd, request, request_len);
+  if (retcode == TCP_SEND_ERROR) goto error;
+
+  /* Proceed the HTTP server reply */
+  retcode = tcp_read_to(req->fd);
+  if (retcode == TCP_READ_TIMEOUT) goto error;
+
+  MD5_Init(&context);
+  extracted = NULL;
+  req->len = 0;
+
+  /* 
+   * Now read the server's response.
+   *
+   * FIXME: Create a function to read data from remote
+   *        server instead of code duplication.
+   */
+  printf(HTTP_HEADER_HEXA);
+  while (1) {
+    r = read(req->fd, buffertmp, RCV_BUFFER_LENGTH);
+    if (r == -1 || r == 0) break; 
+    memcpy(req->buffer+req->len, buffertmp, r);
+    req->len += r;
+    if (!extracted &&
+        (extracted = extract_html(req->buffer, req->len))) {
+      print_buffer(extracted-req->buffer, req->buffer);
+      printf(HTTP_HEADER_ASCII);
+      for ( r=0; r < extracted-req->buffer; r++)
+        printf("%c", req->buffer[r]);
+      printf("\n");
+
+      printf(HTML_HEADER_HEXA);
+      r = req->len - (extracted-req->buffer); 
+      if (r)  
+        memcpy(req->buffer,extracted,r);
+      req->len  = r;
+    }
+
+    if (extracted && req->len) { 
+      print_buffer(req->len, req->buffer);
+      MD5_Update(&context, req->buffer, req->len);
+      req->len = 0;
+    }
+  }
+  
+  MD5_Final(digest, &context);
+  printf(HTML_MD5);
+  print_buffer(16, digest);
+
+  printf(HTML_MD5_FINAL);
+  for (r=0; r<16; r++)
+    printf("%02x", digest[r]);
+  printf("\n\n");
+
+  /* All is fine just return a success code */
+  retcode = HTTP_GET_SUCCESS;
+
+error:
+  close(req->fd);
+  free(request);
+  free(buffertmp);
+  return(retcode);
+}
+
+/* Error return function */
+static void print_error(int err)
+{
+  switch (err) {
+    /* System errors */
+    case OUT_OF_MEMORY:      err_exit("Out Of Memery");                break;
+
+    /* TCP errors */
+    case TCP_BIND_ERROR:     err_exit("TCP Bind error");        break;
+    case TCP_RESOLV_ERROR:   err_exit("TCP Resolv error");     break;
+    case TCP_CONNECT_ERROR:  err_exit("TCP Connect error");    break;
+    case TCP_WRITE_TIMEOUT:  err_exit("TCP Write TimeOut");    break;
+    case TCP_READ_TIMEOUT:   err_exit("TCP Read error");       break;
+    case TCP_SELECT_ERROR:   err_exit("TCP Select error");     break;
+    case TCP_CONNECT_FAILED: err_exit("TCP Connectin failed"); break;
+    case TCP_SEND_ERROR:     err_exit("TCP Send error");       break;
+
+    /* SSL errors */
+    case SSL_WRITE_ERROR:    err_exit("SSL Write error");       break;
+    case SSL_INCOMPLETE_WRITE: err_exit("SSL Incomplete write");break;
+    case SSL_READ_ERROR:     err_exit("SSL Read error");       break;
+    case SSL_SHUTDOWN_FAILED:err_exit("SSL Shutdown failed");  break;
+  }
+}
+
+/* Usage function */
+static void usage(const char *prog)
+{
+  fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+  fprintf(stderr, 
+    "Usage:\n"
+    "  %s -s server-address -p port -u url\n"
+    "  %s -S -K priv-key-file -P pem-password -s server-address -p port -u url\n"
+    "  %s -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url\n"
+    "  %s -h\n"
+    "  %s -v\n\n",
+    prog, prog, prog, prog, prog);
+  fprintf(stderr, 
+    "Commands:\n"
+    "Either long or short options are allowed.\n"
+    "  %s --use-ssl         -S       Use SSL connection to remote server.\n"
+    "  %s --server          -s       Use the specified remote server address.\n"
+    "  %s --port            -p       Use the specified remote server port.\n"
+    "  %s --url             -u       Use the specified remote server url.\n"
+    "  %s --use-private-key -K       Use the specified SSL private key.\n"
+    "  %s --use-password    -P       Use the specified SSL private key password.\n"
+    "  %s --use-certificate -C       Use the specified SSL Certificate file.\n"
+    "  %s --help            -h       Display this short inlined help screen.\n"
+    "  %s --version         -v       Display the version number\n",
+    prog, prog, prog, prog, prog, prog, prog, prog, prog);
+}
+
+/* Command line parser */
+static int parse_cmdline(int argc, char **argv, REQ *req)
+{
+  poptContext context;
+  char *optarg = NULL;
+  int c;
+
+  struct poptOption options_table[] = {
+    {"version",         'v', POPT_ARG_NONE,      NULL, 'v'},
+    {"help",            'h', POPT_ARG_NONE,      NULL, 'h'},
+    {"use-ssl",         'S', POPT_ARG_NONE,      NULL, 'S'},
+    {"server",          's', POPT_ARG_STRING, &optarg, 's'},
+    {"port",            'p', POPT_ARG_STRING, &optarg, 'p'},
+    {"url",             'u', POPT_ARG_STRING, &optarg, 'u'},
+    {"use-private-key", 'K', POPT_ARG_STRING, &optarg, 'K'},
+    {"use-password",    'P', POPT_ARG_STRING, &optarg, 'P'},
+    {"use-certificate", 'C', POPT_ARG_STRING, &optarg, 'C'},
+    {NULL, 0, 0, NULL, 0}
+  };
+
+  context = poptGetContext(PROG, argc, (const char **)argv
+                                     , options_table, 0);
+  if ((c = poptGetNextOpt(context)) < 0) {
+    usage(argv[0]);
+    return CMD_LINE_ERROR;
+  }
+
+  /* The first option car */
+  switch (c) {
+    case 'v':
+      fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+      break;
+    case 'h':
+      usage(argv[0]);
+      break;
+    case 'S':
+      req->ssl = 1;
+      break;
+    case 's':
+      req->host = optarg;
+      break;
+    default:
+      usage(argv[0]);
+      return CMD_LINE_ERROR;
+  }
+
+  /* the others */
+  while ((c = poptGetNextOpt(context)) >= 0) {
+    switch (c) {
+      case 's':
+        req->host = optarg;
+        break;
+      case 'p':
+        req->port = atoi(optarg);
+        break;
+      case 'u':
+        req->url = optarg;
+        break;
+      case 'K':
+        req->keyfile = optarg;
+        break;
+      case 'P':
+        req->password = optarg;
+        break;
+      case 'C':
+        req->cafile = optarg;
+        break;
+      default:
+        usage(argv[0]);
+        return CMD_LINE_ERROR;
+    }
+  }
+
+  /* check unexpected arguments */
+  if ((optarg = (char *)poptGetArg(context))) {
+    fprintf(stderr, "unexpected argument %s", optarg);
+    return CMD_LINE_ERROR;
+  }
+
+  /* free the allocated context */
+  poptFreeContext(context);
+  
+  return CMD_LINE_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+  REQ *req;
+  char *buffer;
+  int err=0;
+
+  /* Allocate the room */
+  req    = (REQ *)xmalloc(sizeof(REQ));
+  buffer = (char *)xmalloc(RCV_BUFFER_LENGTH);
+
+  /* Command line parser */
+  if (!parse_cmdline(argc, argv, req))
+    exit(0);
+
+  /* Check minimum configuration need */
+  if (!req->host && !req->port && !req->url) {
+    exit(0);
+  }
+
+  /* finalize req initialisation  */
+  req->buffer = buffer;
+  req->max    = RCV_BUFFER_LENGTH; 
+
+  /* Now make our HTTP/SSL request */
+  err = req->ssl ? genhash_ssl(req) : genhash_http(req);
+  print_error(err); 
+
+  free(req);
+  return(1);
+}
diff --git a/genhash/main.h b/genhash/main.h
new file mode 100644 (file)
index 0000000..d9f63ce
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for HTTP_GET
+ *              & SSL_GET keepalive method.
+ *
+ * Part:        main.c include file.
+ *
+ * Version:     $Id: main.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.se>
+ *
+ *              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 _MAIN_H
+#define _MAIN_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <openssl/md5.h>
+#include <popt.h>
+
+/* Build version */
+#define PROG    "genhash"
+#define VERSION "0.4.9 (05/12, 2001)"
+
+/* HTTP/HTTPS GET command */
+#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
+                         "User-Agent:KeepAliveClient\r\n" \
+                         "Host: %s:%d\r\n\r\n"
+
+/* HTTP/HTTPS request structure */
+typedef struct {
+  char *host;
+  char *buffer;
+  int error;
+  int max;
+  int len;
+  char *url;
+  unsigned short int port;
+  int fd;
+  int ssl;
+  char *keyfile;
+  char *password;
+  char *cafile;
+} REQ;
+
+/* Output delimiters */
+#define DELIM_BEGIN "-----------------------["
+#define DELIM_END   "]-----------------------\n"
+#define HTTP_HEADER_HEXA  DELIM_BEGIN"    HTTP Header Buffer    "DELIM_END
+#define HTTP_HEADER_ASCII DELIM_BEGIN" HTTP Header Ascii Buffer "DELIM_END
+#define HTML_HEADER_HEXA  DELIM_BEGIN"       HTML Buffer        "DELIM_END
+#define HTML_MD5          DELIM_BEGIN"    HTML MD5 resulting    "DELIM_END
+#define HTML_MD5_FINAL    DELIM_BEGIN" HTML MD5 final resulting "DELIM_END
+
+/* Data buffer length description */
+#define RCV_BUFFER_LENGTH   512
+#define BUFSIZE             1024
+
+/* Command line error handling */
+#define CMD_LINE_ERROR   0
+#define CMD_LINE_SUCCESS 1
+
+#endif
diff --git a/genhash/md5.c b/genhash/md5.c
deleted file mode 100644 (file)
index 9a3b957..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*\r
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.\r
-\r
-  This software is provided 'as-is', without any express or implied\r
-  warranty.  In no event will the authors be held liable for any damages\r
-  arising from the use of this software.\r
-\r
-  Permission is granted to anyone to use this software for any purpose,\r
-  including commercial applications, and to alter it and redistribute it\r
-  freely, subject to the following restrictions:\r
-\r
-  1. The origin of this software must not be misrepresented; you must not\r
-     claim that you wrote the original software. If you use this software\r
-     in a product, an acknowledgment in the product documentation would be\r
-     appreciated but is not required.\r
-  2. Altered source versions must be plainly marked as such, and must not be\r
-     misrepresented as being the original software.\r
-  3. This notice may not be removed or altered from any source distribution.\r
-\r
-  L. Peter Deutsch\r
-  ghost@aladdin.com\r
-\r
- */\r
-/*$Id: md5.c $ */\r
-/*\r
-  Independent implementation of MD5 (RFC 1321).\r
-\r
-  This code implements the MD5 Algorithm defined in RFC 1321.\r
-  It is derived directly from the text of the RFC and not from the\r
-  reference implementation.\r
-\r
-  The original and principal author of md5.c is L. Peter Deutsch\r
-  <ghost@aladdin.com>.  Other authors are noted in the change history\r
-  that follows (in reverse chronological order):\r
-\r
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).\r
-  1999-05-03 lpd Original version.\r
- */\r
-\r
-#include "md5.h"\r
-\r
-#define T1 0xd76aa478\r
-#define T2 0xe8c7b756\r
-#define T3 0x242070db\r
-#define T4 0xc1bdceee\r
-#define T5 0xf57c0faf\r
-#define T6 0x4787c62a\r
-#define T7 0xa8304613\r
-#define T8 0xfd469501\r
-#define T9 0x698098d8\r
-#define T10 0x8b44f7af\r
-#define T11 0xffff5bb1\r
-#define T12 0x895cd7be\r
-#define T13 0x6b901122\r
-#define T14 0xfd987193\r
-#define T15 0xa679438e\r
-#define T16 0x49b40821\r
-#define T17 0xf61e2562\r
-#define T18 0xc040b340\r
-#define T19 0x265e5a51\r
-#define T20 0xe9b6c7aa\r
-#define T21 0xd62f105d\r
-#define T22 0x02441453\r
-#define T23 0xd8a1e681\r
-#define T24 0xe7d3fbc8\r
-#define T25 0x21e1cde6\r
-#define T26 0xc33707d6\r
-#define T27 0xf4d50d87\r
-#define T28 0x455a14ed\r
-#define T29 0xa9e3e905\r
-#define T30 0xfcefa3f8\r
-#define T31 0x676f02d9\r
-#define T32 0x8d2a4c8a\r
-#define T33 0xfffa3942\r
-#define T34 0x8771f681\r
-#define T35 0x6d9d6122\r
-#define T36 0xfde5380c\r
-#define T37 0xa4beea44\r
-#define T38 0x4bdecfa9\r
-#define T39 0xf6bb4b60\r
-#define T40 0xbebfbc70\r
-#define T41 0x289b7ec6\r
-#define T42 0xeaa127fa\r
-#define T43 0xd4ef3085\r
-#define T44 0x04881d05\r
-#define T45 0xd9d4d039\r
-#define T46 0xe6db99e5\r
-#define T47 0x1fa27cf8\r
-#define T48 0xc4ac5665\r
-#define T49 0xf4292244\r
-#define T50 0x432aff97\r
-#define T51 0xab9423a7\r
-#define T52 0xfc93a039\r
-#define T53 0x655b59c3\r
-#define T54 0x8f0ccc92\r
-#define T55 0xffeff47d\r
-#define T56 0x85845dd1\r
-#define T57 0x6fa87e4f\r
-#define T58 0xfe2ce6e0\r
-#define T59 0xa3014314\r
-#define T60 0x4e0811a1\r
-#define T61 0xf7537e82\r
-#define T62 0xbd3af235\r
-#define T63 0x2ad7d2bb\r
-#define T64 0xeb86d391\r
-\r
-static void\r
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)\r
-{\r
-    md5_word_t\r
-       a = pms->abcd[0], b = pms->abcd[1],\r
-       c = pms->abcd[2], d = pms->abcd[3];\r
-    md5_word_t t;\r
-\r
-#ifndef ARCH_IS_BIG_ENDIAN\r
-# define ARCH_IS_BIG_ENDIAN 1  /* slower, default implementation */\r
-#endif\r
-#if ARCH_IS_BIG_ENDIAN\r
-\r
-    /*\r
-     * On big-endian machines, we must arrange the bytes in the right\r
-     * order.  (This also works on machines of unknown byte order.)\r
-     */\r
-    md5_word_t X[16];\r
-    const md5_byte_t *xp = data;\r
-    int i;\r
-\r
-    for (i = 0; i < 16; ++i, xp += 4)\r
-       X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);\r
-\r
-#else  /* !ARCH_IS_BIG_ENDIAN */\r
-\r
-    /*\r
-     * On little-endian machines, we can process properly aligned data\r
-     * without copying it.\r
-     */\r
-    md5_word_t xbuf[16];\r
-    const md5_word_t *X;\r
-\r
-    if (!((data - (const md5_byte_t *)0) & 3)) {\r
-       /* data are properly aligned */\r
-       X = (const md5_word_t *)data;\r
-    } else {\r
-       /* not aligned */\r
-       memcpy(xbuf, data, 64);\r
-       X = xbuf;\r
-    }\r
-#endif\r
-\r
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\r
-\r
-    /* Round 1. */\r
-    /* Let [abcd k s i] denote the operation\r
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */\r
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))\r
-#define SET(a, b, c, d, k, s, Ti) t = a + F(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
-    /* Do the following 16 operations. */\r
-    SET(a, b, c, d,  0,  7,  T1);\r
-    SET(d, a, b, c,  1, 12,  T2);\r
-    SET(c, d, a, b,  2, 17,  T3);\r
-    SET(b, c, d, a,  3, 22,  T4);\r
-    SET(a, b, c, d,  4,  7,  T5);\r
-    SET(d, a, b, c,  5, 12,  T6);\r
-    SET(c, d, a, b,  6, 17,  T7);\r
-    SET(b, c, d, a,  7, 22,  T8);\r
-    SET(a, b, c, d,  8,  7,  T9);\r
-    SET(d, a, b, c,  9, 12, T10);\r
-    SET(c, d, a, b, 10, 17, T11);\r
-    SET(b, c, d, a, 11, 22, T12);\r
-    SET(a, b, c, d, 12,  7, T13);\r
-    SET(d, a, b, c, 13, 12, T14);\r
-    SET(c, d, a, b, 14, 17, T15);\r
-    SET(b, c, d, a, 15, 22, T16);\r
-#undef SET\r
-\r
-     /* Round 2. */\r
-     /* Let [abcd k s i] denote the operation\r
-          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */\r
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))\r
-#define SET(a, b, c, d, k, s, Ti) t = a + G(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
-     /* Do the following 16 operations. */\r
-    SET(a, b, c, d,  1,  5, T17);\r
-    SET(d, a, b, c,  6,  9, T18);\r
-    SET(c, d, a, b, 11, 14, T19);\r
-    SET(b, c, d, a,  0, 20, T20);\r
-    SET(a, b, c, d,  5,  5, T21);\r
-    SET(d, a, b, c, 10,  9, T22);\r
-    SET(c, d, a, b, 15, 14, T23);\r
-    SET(b, c, d, a,  4, 20, T24);\r
-    SET(a, b, c, d,  9,  5, T25);\r
-    SET(d, a, b, c, 14,  9, T26);\r
-    SET(c, d, a, b,  3, 14, T27);\r
-    SET(b, c, d, a,  8, 20, T28);\r
-    SET(a, b, c, d, 13,  5, T29);\r
-    SET(d, a, b, c,  2,  9, T30);\r
-    SET(c, d, a, b,  7, 14, T31);\r
-    SET(b, c, d, a, 12, 20, T32);\r
-#undef SET\r
-\r
-     /* Round 3. */\r
-     /* Let [abcd k s t] denote the operation\r
-          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */\r
-#define H(x, y, z) ((x) ^ (y) ^ (z))\r
-#define SET(a, b, c, d, k, s, Ti) t = a + H(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
-     /* Do the following 16 operations. */\r
-    SET(a, b, c, d,  5,  4, T33);\r
-    SET(d, a, b, c,  8, 11, T34);\r
-    SET(c, d, a, b, 11, 16, T35);\r
-    SET(b, c, d, a, 14, 23, T36);\r
-    SET(a, b, c, d,  1,  4, T37);\r
-    SET(d, a, b, c,  4, 11, T38);\r
-    SET(c, d, a, b,  7, 16, T39);\r
-    SET(b, c, d, a, 10, 23, T40);\r
-    SET(a, b, c, d, 13,  4, T41);\r
-    SET(d, a, b, c,  0, 11, T42);\r
-    SET(c, d, a, b,  3, 16, T43);\r
-    SET(b, c, d, a,  6, 23, T44);\r
-    SET(a, b, c, d,  9,  4, T45);\r
-    SET(d, a, b, c, 12, 11, T46);\r
-    SET(c, d, a, b, 15, 16, T47);\r
-    SET(b, c, d, a,  2, 23, T48);\r
-#undef SET\r
-\r
-     /* Round 4. */\r
-     /* Let [abcd k s t] denote the operation\r
-          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */\r
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))\r
-#define SET(a, b, c, d, k, s, Ti) t = a + I(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
-     /* Do the following 16 operations. */\r
-    SET(a, b, c, d,  0,  6, T49);\r
-    SET(d, a, b, c,  7, 10, T50);\r
-    SET(c, d, a, b, 14, 15, T51);\r
-    SET(b, c, d, a,  5, 21, T52);\r
-    SET(a, b, c, d, 12,  6, T53);\r
-    SET(d, a, b, c,  3, 10, T54);\r
-    SET(c, d, a, b, 10, 15, T55);\r
-    SET(b, c, d, a,  1, 21, T56);\r
-    SET(a, b, c, d,  8,  6, T57);\r
-    SET(d, a, b, c, 15, 10, T58);\r
-    SET(c, d, a, b,  6, 15, T59);\r
-    SET(b, c, d, a, 13, 21, T60);\r
-    SET(a, b, c, d,  4,  6, T61);\r
-    SET(d, a, b, c, 11, 10, T62);\r
-    SET(c, d, a, b,  2, 15, T63);\r
-    SET(b, c, d, a,  9, 21, T64);\r
-#undef SET\r
-\r
-     /* Then perform the following additions. (That is increment each\r
-        of the four registers by the value it had before this block\r
-        was started.) */\r
-    pms->abcd[0] += a;\r
-    pms->abcd[1] += b;\r
-    pms->abcd[2] += c;\r
-    pms->abcd[3] += d;\r
-}\r
-\r
-void\r
-md5_init(md5_state_t *pms)\r
-{\r
-    pms->count[0] = pms->count[1] = 0;\r
-    pms->abcd[0] = 0x67452301;\r
-    pms->abcd[1] = 0xefcdab89;\r
-    pms->abcd[2] = 0x98badcfe;\r
-    pms->abcd[3] = 0x10325476;\r
-}\r
-\r
-void\r
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)\r
-{\r
-    const md5_byte_t *p = data;\r
-    int left = nbytes;\r
-    int offset = (pms->count[0] >> 3) & 63;\r
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);\r
-\r
-    if (nbytes <= 0)\r
-       return;\r
-\r
-    /* Update the message length. */\r
-    pms->count[1] += nbytes >> 29;\r
-    pms->count[0] += nbits;\r
-    if (pms->count[0] < nbits)\r
-       pms->count[1]++;\r
-\r
-    /* Process an initial partial block. */\r
-    if (offset) {\r
-       int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);\r
-\r
-       memcpy(pms->buf + offset, p, copy);\r
-       if (offset + copy < 64)\r
-           return;\r
-       p += copy;\r
-       left -= copy;\r
-       md5_process(pms, pms->buf);\r
-    }\r
-\r
-    /* Process full blocks. */\r
-    for (; left >= 64; p += 64, left -= 64)\r
-       md5_process(pms, p);\r
-\r
-    /* Process a final partial block. */\r
-    if (left)\r
-       memcpy(pms->buf, p, left);\r
-}\r
-\r
-void\r
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])\r
-{\r
-    static const md5_byte_t pad[64] = {\r
-       0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
-    };\r
-    md5_byte_t data[8];\r
-    int i;\r
-\r
-    /* Save the length before padding. */\r
-    for (i = 0; i < 8; ++i)\r
-       data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));\r
-    /* Pad to 56 bytes mod 64. */\r
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);\r
-    /* Append the length. */\r
-    md5_append(pms, data, 8);\r
-    for (i = 0; i < 16; ++i)\r
-       digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));\r
-}\r
diff --git a/genhash/md5.h b/genhash/md5.h
deleted file mode 100644 (file)
index 72ddcb8..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*\r
-  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.\r
-\r
-  This software is provided 'as-is', without any express or implied\r
-  warranty.  In no event will the authors be held liable for any damages\r
-  arising from the use of this software.\r
-\r
-  Permission is granted to anyone to use this software for any purpose,\r
-  including commercial applications, and to alter it and redistribute it\r
-  freely, subject to the following restrictions:\r
-\r
-  1. The origin of this software must not be misrepresented; you must not\r
-     claim that you wrote the original software. If you use this software\r
-     in a product, an acknowledgment in the product documentation would be\r
-     appreciated but is not required.\r
-  2. Altered source versions must be plainly marked as such, and must not be\r
-     misrepresented as being the original software.\r
-  3. This notice may not be removed or altered from any source distribution.\r
-\r
-  L. Peter Deutsch\r
-  ghost@aladdin.com\r
-\r
- */\r
-/*$Id: md5.h $ */\r
-/*\r
-  Independent implementation of MD5 (RFC 1321).\r
-\r
-  This code implements the MD5 Algorithm defined in RFC 1321.\r
-  It is derived directly from the text of the RFC and not from the\r
-  reference implementation.\r
-\r
-  The original and principal author of md5.h is L. Peter Deutsch\r
-  <ghost@aladdin.com>.  Other authors are noted in the change history\r
-  that follows (in reverse chronological order):\r
-\r
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);\r
-       added conditionalization for C++ compilation from Martin\r
-       Purschke <purschke@bnl.gov>.\r
-  1999-05-03 lpd Original version.\r
- */\r
-\r
-#ifndef md5_INCLUDED\r
-#  define md5_INCLUDED\r
-\r
-/*\r
- * This code has some adaptations for the Ghostscript environment, but it\r
- * will compile and run correctly in any environment with 8-bit chars and\r
- * 32-bit ints.  Specifically, it assumes that if the following are\r
- * defined, they have the same meaning as in Ghostscript: P1, P2, P3,\r
- * ARCH_IS_BIG_ENDIAN.\r
- */\r
-\r
-typedef unsigned char md5_byte_t; /* 8-bit byte */\r
-typedef unsigned int md5_word_t; /* 32-bit word */\r
-\r
-/* Define the state of the MD5 Algorithm. */\r
-typedef struct md5_state_s {\r
-    md5_word_t count[2];       /* message length in bits, lsw first */\r
-    md5_word_t abcd[4];                /* digest buffer */\r
-    md5_byte_t buf[64];                /* accumulate block */\r
-} md5_state_t;\r
-\r
-#ifdef __cplusplus\r
-extern "C" \r
-{\r
-#endif\r
-\r
-/* Initialize the algorithm. */\r
-#ifdef P1\r
-void md5_init(P1(md5_state_t *pms));\r
-#else\r
-void md5_init(md5_state_t *pms);\r
-#endif\r
-\r
-/* Append a string to the message. */\r
-#ifdef P3\r
-void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));\r
-#else\r
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);\r
-#endif\r
-\r
-/* Finish the message and return the digest. */\r
-#ifdef P2\r
-void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));\r
-#else\r
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);\r
-#endif\r
-\r
-#ifdef __cplusplus\r
-}  /* end extern "C" */\r
-#endif\r
-\r
-#endif /* md5_INCLUDED */\r
diff --git a/genhash/ssl.crt b/genhash/ssl.crt
new file mode 100644 (file)
index 0000000..a8fc8bd
--- /dev/null
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICoDCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMB4XDTAxMTEyODE1MzcwMFoXDTAxMTIyODE1MzcwMFowRTELMAkGA1UE
+BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
+ZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqaHao73f
+HpyErd5yhBcY9MS0oN0uHFtSXsz63VXjfEwhl/7bgaw+9qR1a/iY8lW7NL7yON+9
+6o1wToTV/8gDs19rlUY+tpFiIsJzHUO2Xknnyp87dUPOU+bNu+r525DVnTvf4uxV
+6H56CPqqGDYKpG1dyjDtdiTgayIcehQNsiECAwEAAaOBnzCBnDAdBgNVHQ4EFgQU
+E3xmxdjFNxXJLa/NlzpeQtqwNZcwbQYDVR0jBGYwZIAUE3xmxdjFNxXJLa/Nlzpe
+QtqwNZehSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
+HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAAOBgQCMAF/IJrmL7wSdY/YWjbj8+PKzIMzJmz6w6c8V
+LhbLHYreMurG5830Ljnd1udm7o7g+16qLNfq0rEwrWhnxDnC1Id8nHXxhUHO6IEg
+YDPBWMte7zOC7skgDzvJc585HiMNxXEuX1pwnBvHv+qqu36TtVZSXeOKZcOOmkwE
+eY40Bg==
+-----END CERTIFICATE-----
diff --git a/genhash/ssl.csr b/genhash/ssl.csr
new file mode 100644 (file)
index 0000000..70c01d3
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEh
+MB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCpodqjvd8enISt3nKEFxj0xLSg3S4cW1JezPrdVeN8TCGX
+/tuBrD72pHVr+JjyVbs0vvI4373qjXBOhNX/yAOzX2uVRj62kWIiwnMdQ7ZeSefK
+nzt1Q85T5s276vnbkNWdO9/i7FXofnoI+qoYNgqkbV3KMO12JOBrIhx6FA2yIQID
+AQABoAAwDQYJKoZIhvcNAQEEBQADgYEAJr5QWBjpWL1qsrHaNAP+qP17IAUWuZsz
+Zdy72zGnQcsrk3mn6b1z9OS7WOPKcKkSq2q1+DlQS7vfhPaYRM1g/sqOMbnPv+MJ
+CCvHvBcI+nKBjUS7WofEuZSvVzo8bdwoVyYLdQWKFi6w3Z+O8D3YxRlvXseWWOkI
+lj4W75ypRVU=
+-----END CERTIFICATE REQUEST-----
diff --git a/genhash/ssl.key b/genhash/ssl.key
new file mode 100644 (file)
index 0000000..0e250fe
--- /dev/null
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,45FBDBEBCB52B1ED
+
+q6RONp0/s4kRRhz1n//irIU+QIed+F0Vu7ijixGARCJkkp+ZoXbGqOYwLJXjJXtH
+iC08SodwhFZLdLgCTttTn6IZvKR6Ye0K6or0JvSLQ+3+qdDy7GmgEnctPhE7j4Nk
+ptZejNPjjauh5tpu/rrIIq14ApE0zDuJpx97co4/i7VrGpB/HVVtJ61As3ry4aRL
+T8WvuQEIM5TLKC8tSxPb8rQKM5soY2IHd+GmMgYkiNg+Vcg6I7N34EQkse0CHNxA
+PUl2kPwP9kg981mR/xks22oNNM5AAkTuWXB8R3zDuyaVdYcpbSEiOeOBMPFo43CR
+yFsYRVOer9Dp97KSkYQ3VOwoYil2m6ddrpYBr9qDZ/PF9VBhdrJT37rA73+1V6AO
+YFkQvbWiL/SUsvByXFHes68Y09fCHkbCkbtY3tNvTK8Z37iI6ZuTPdBIYblTRYil
+51RDJkrCuUyLx3dzkPxQqq1nkBRx9QLz2DaY0xRc9PEgM01C/Q5T/7mwosSsE/zZ
+5oJB3upN8/1kmy+gTLLoE5kSyEZup8NsEHEqhU1z2z+t6DKOnFR8eg0YXdItIfHP
+y7QNKmFaSghtkNPQUrXz/s4Bh/9bEAicIOjj6Om2uVKG0vXEa+0b+Qz8sUcHvFB+
+IX2NJUCmFQgjFt6a3IYo6P0ajLy1g/ES+nPWwjYAMVXe0RHrB+Q0pwib9koWGvZN
+4N2xti19DEdKBNMgWRo7SBzTNtkv5Eo6btLw4M9oeqonC1YJfGThFUSssyC5ZCcY
+H+QeYs48mWoQwXwAufOr8CwALLmeAGhgBiIy6dcbvHpO7IQzTRRcIA==
+-----END RSA PRIVATE KEY-----
diff --git a/genhash/ssl.pem b/genhash/ssl.pem
new file mode 100644 (file)
index 0000000..71dcd6f
--- /dev/null
@@ -0,0 +1,35 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,45FBDBEBCB52B1ED
+
+q6RONp0/s4kRRhz1n//irIU+QIed+F0Vu7ijixGARCJkkp+ZoXbGqOYwLJXjJXtH
+iC08SodwhFZLdLgCTttTn6IZvKR6Ye0K6or0JvSLQ+3+qdDy7GmgEnctPhE7j4Nk
+ptZejNPjjauh5tpu/rrIIq14ApE0zDuJpx97co4/i7VrGpB/HVVtJ61As3ry4aRL
+T8WvuQEIM5TLKC8tSxPb8rQKM5soY2IHd+GmMgYkiNg+Vcg6I7N34EQkse0CHNxA
+PUl2kPwP9kg981mR/xks22oNNM5AAkTuWXB8R3zDuyaVdYcpbSEiOeOBMPFo43CR
+yFsYRVOer9Dp97KSkYQ3VOwoYil2m6ddrpYBr9qDZ/PF9VBhdrJT37rA73+1V6AO
+YFkQvbWiL/SUsvByXFHes68Y09fCHkbCkbtY3tNvTK8Z37iI6ZuTPdBIYblTRYil
+51RDJkrCuUyLx3dzkPxQqq1nkBRx9QLz2DaY0xRc9PEgM01C/Q5T/7mwosSsE/zZ
+5oJB3upN8/1kmy+gTLLoE5kSyEZup8NsEHEqhU1z2z+t6DKOnFR8eg0YXdItIfHP
+y7QNKmFaSghtkNPQUrXz/s4Bh/9bEAicIOjj6Om2uVKG0vXEa+0b+Qz8sUcHvFB+
+IX2NJUCmFQgjFt6a3IYo6P0ajLy1g/ES+nPWwjYAMVXe0RHrB+Q0pwib9koWGvZN
+4N2xti19DEdKBNMgWRo7SBzTNtkv5Eo6btLw4M9oeqonC1YJfGThFUSssyC5ZCcY
+H+QeYs48mWoQwXwAufOr8CwALLmeAGhgBiIy6dcbvHpO7IQzTRRcIA==
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIICoDCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMB4XDTAxMTEyODE1MzcwMFoXDTAxMTIyODE1MzcwMFowRTELMAkGA1UE
+BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
+ZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqaHao73f
+HpyErd5yhBcY9MS0oN0uHFtSXsz63VXjfEwhl/7bgaw+9qR1a/iY8lW7NL7yON+9
+6o1wToTV/8gDs19rlUY+tpFiIsJzHUO2Xknnyp87dUPOU+bNu+r525DVnTvf4uxV
+6H56CPqqGDYKpG1dyjDtdiTgayIcehQNsiECAwEAAaOBnzCBnDAdBgNVHQ4EFgQU
+E3xmxdjFNxXJLa/NlzpeQtqwNZcwbQYDVR0jBGYwZIAUE3xmxdjFNxXJLa/Nlzpe
+QtqwNZehSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
+HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQQFAAOBgQCMAF/IJrmL7wSdY/YWjbj8+PKzIMzJmz6w6c8V
+LhbLHYreMurG5830Ljnd1udm7o7g+16qLNfq0rEwrWhnxDnC1Id8nHXxhUHO6IEg
+YDPBWMte7zOC7skgDzvJc585HiMNxXEuX1pwnBvHv+qqu36TtVZSXeOKZcOOmkwE
+eY40Bg==
+-----END CERTIFICATE-----
index 63589ad..80c4229 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: ipfwwrapper.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 9269a88..ca54077 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipfwwrapper.c include file.
  *
- * Version:     $Id: ipfwwrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: ipfwwrapper.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 6435423..10cebdc 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: ipvswrapper.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -23,7 +23,7 @@
 
 #include "ipvswrapper.h"
 
-#ifdef KERNEL_2_2  /* KERNEL 2.2 LVS handling */
+#ifdef _KRNL_2_2_  /* KERNEL 2.2 LVS handling */
 
 int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
 {
@@ -48,8 +48,12 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
   ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
   
   /* VS specific */
-  ctl.u.vs_user.vaddr = vserver->addr_ip.s_addr;
-  ctl.u.vs_user.vport = vserver->addr_port;
+  if (vserver->vfwmark) {
+    ctl.u.vs_user.vfwmark = vserver->vfwmark;
+  } else {
+    ctl.u.vs_user.vaddr = vserver->addr_ip.s_addr;
+    ctl.u.vs_user.vport = vserver->addr_port;
+  }
 
   /* SVR specific */
   if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST) {
@@ -106,9 +110,12 @@ int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
   urule.vs_flags = (urule.timeout != 0)?IP_VS_SVC_F_PERSISTENT:0;
 
   /* VS specific */
-  urule.vaddr = vserver->addr_ip.s_addr;
-  urule.vport = vserver->addr_port;
-
+  if (vserver->vfwmark) {
+    urule.vfwmark = vserver->vfwmark;
+  } else {
+    urule.vaddr = vserver->addr_ip.s_addr;
+    urule.vport = vserver->addr_port;
+  }
   /* SVR specific */
   if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
     urule.weight = rserver->weight;
index df8b3e1..0c5d6bb 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipvswrapper.c include file.
  *
- * Version:     $Id: ipvswrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: ipvswrapper.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -36,7 +36,7 @@
 #include <netinet/udp.h>
 #include <netinet/tcp.h>
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
   #include <linux/ip_fw.h>
   #include <net/ip_masq.h>
 #endif
index 8b0190e..704637d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Manipulation functions for IPVS & IPFW wrappers.
  *
- * Version:     $id: ipwrapper.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $id: ipwrapper.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -34,7 +34,7 @@ int clear_service_vs(virtualserver *vserver)
       return 0;
     }
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
     /* IPFW cleaning server entry if granularity = /32 */
     if (vserver->nat_mask.s_addr == HOST_NETMASK)
       if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
@@ -58,7 +58,7 @@ int clear_services(virtualserver *vserver)
     if (!clear_service_vs(vserver))
       return 0;
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
     /* IPFW cleaner processing */
     if (vserver->nat_mask.s_addr != HOST_NETMASK)
       if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
@@ -99,7 +99,7 @@ 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
+#ifdef _KRNL_2_2_
         ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->s_svr);
 #endif
       }
@@ -111,7 +111,7 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
            inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
     ipvs_cmd(LVS_CMD_ADD_DEST, vserver, rserver);
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
     if (vserver->nat_mask.s_addr == HOST_NETMASK)
       ipfw_cmd(IP_FW_CMD_ADD, vserver, rserver);
 #endif
@@ -126,7 +126,7 @@ 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
+#ifdef _KRNL_2_2_
     if (vserver->nat_mask.s_addr == HOST_NETMASK)
       ipfw_cmd(IP_FW_CMD_DEL, vserver, rserver);
 #endif
@@ -141,7 +141,7 @@ void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
       vserver->s_svr->alive = 1;
       ipvs_cmd(LVS_CMD_ADD_DEST, vserver, vserver->s_svr);
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
       ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->s_svr);
 #endif
     }
@@ -160,7 +160,7 @@ int init_service_vs(virtualserver *vserver)
       return 0;
     }
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
     /* if we have a /32 mask, we create one nat rules per
      * realserver.
      */
@@ -187,7 +187,7 @@ int init_services(virtualserver *vserver)
     if (!ipvs_cmd(LVS_CMD_ADD, vserver, vserver->svr))
       return 0;
 
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
     /* work if all realserver ip address are in the
      * same network (it is assumed).
      */
index a768653..03e575e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        ipwrapper.c include file.
  *
- * Version:     $Id: ipwrapper.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: ipwrapper.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -42,7 +42,7 @@
 #define DOWN 0
 
 /* LVS command set by kernel */
-#ifdef KERNEL_2_2
+#ifdef _KRNL_2_2_
   #define LVS_CMD_ADD      IP_MASQ_CMD_ADD
   #define LVS_CMD_DEL      IP_MASQ_CMD_DEL
   #define LVS_CMD_ADD_DEST IP_MASQ_CMD_ADD_DEST
index 40762ec..162ba89 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: layer4.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -67,22 +67,21 @@ tcp_connect (int fd, uint32_t IP_DST, uint16_t PORT_DST)
   return connect_in_progress;
 }
 
-enum connect_result
-tcp_socket_state(int fd, struct thread *thread,
-                         int (*func) (struct thread *))
+enum connect_result tcp_socket_state(int fd, thread *thread
+                                    , int (*func) (struct _thread *))
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
   int status;
   int slen;
   int ret = 0;
-  struct timeval timer_now;
-  struct timeval timer_min;
+  TIMEVAL timer_now;
+  TIMEVAL timer_min;
 
   thread_arg = THREAD_ARG(thread);
 
   /* Handle connection timeout */
   if(thread->type == THREAD_WRITE_TIMEOUT) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     if (thread_arg->svr)
       syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d].",
                           inet_ntoa(thread_arg->svr->addr_ip),
@@ -99,7 +98,7 @@ tcp_socket_state(int fd, struct thread *thread,
 
   /* Connection failed !!! */
   if (ret) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     if (thread_arg->svr)
       syslog(LOG_DEBUG, "TCP connection failed to [%s:%d].",
                           inet_ntoa(thread_arg->svr->addr_ip), 
@@ -115,7 +114,7 @@ tcp_socket_state(int fd, struct thread *thread,
    * Recompute the write timeout (or pending connection).
    */
   if (status != 0) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     if (thread_arg->svr)
       syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS.",
                         inet_ntoa(thread_arg->svr->addr_ip),
@@ -138,18 +137,17 @@ tcp_socket_state(int fd, struct thread *thread,
   return connect_success;
 }
 
-void
-tcp_connection_state(int fd, enum connect_result status,
-                             struct thread *thread,
-                             int (*func) (struct thread *))
+void tcp_connection_state(int fd, enum connect_result status
+                         , thread *thread
+                         , int (*func) (struct _thread *))
 {
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
 
   thread_arg = THREAD_ARG(thread);
 
   switch (status) {
     case connect_error:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG,"TCP connection ERROR to [%s:%d].",
                        inet_ntoa(thread_arg->svr->addr_ip),
                        ntohs(thread_arg->svr->addr_port));
@@ -158,7 +156,7 @@ tcp_connection_state(int fd, enum connect_result status,
       break;
 
     case connect_success:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG,"TCP connection SUCCESS to [%s:%d].",
                        inet_ntoa(thread_arg->svr->addr_ip),
                        ntohs(thread_arg->svr->addr_port));
@@ -169,7 +167,7 @@ tcp_connection_state(int fd, enum connect_result status,
 
     /* Checking non-blocking connect, we wait until socket is writable */
     case connect_in_progress:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG,"TCP connection to [%s:%d] now IN_PROGRESS.",
                        inet_ntoa(thread_arg->svr->addr_ip),
                        ntohs(thread_arg->svr->addr_port));
index 22b166f..6532b58 100644 (file)
--- a/layer4.h
+++ b/layer4.h
@@ -5,7 +5,7 @@
  *
  * Part:        layer4.c include file.
  *
- * Version:     $Id: layer4.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: layer4.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -46,12 +46,12 @@ extern enum connect_result
 tcp_connect(int fd, uint32_t IP_DST, uint16_t PORT_DST);
 
 extern enum connect_result
-tcp_socket_state(int fd, struct thread *thread,
-                         int (*func) (struct thread *));
+tcp_socket_state(int fd, thread *thread,
+                         int (*func) (struct _thread *));
 
 extern void
 tcp_connection_state(int fd, enum connect_result status,
-                             struct thread *thread,
-                             int (*func) (struct thread *));
+                             thread *thread,
+                             int (*func) (struct _thread *));
 
 #endif
index e76726a..955e72f 100644 (file)
@@ -444,7 +444,7 @@ struct ipfwc_fwrule *ipfwc_get_rules(unsigned int *num_rules, int zero)
 }
 
 /* Get raw socket. */
-int ipfwc_get_raw_socket()
+int ipfwc_get_raw_socket(void)
 {
        return sockfd;
 }
index bac8ad3..4c8200b 100644 (file)
@@ -80,7 +80,7 @@ int ipfwc_delete_chain(const ip_chainlabel chain);
 int ipfwc_set_policy(const ip_chainlabel chain, const ip_chainlabel policy);
 
 /* Get raw socket. */
-int ipfwc_get_raw_socket();
+int ipfwc_get_raw_socket(void);
 
 /* Translates errno numbers into more human-readable form than strerror. */
 const char *ipfwc_strerror(int err);
diff --git a/main.c b/main.c
index 94effca..53b764e 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,7 +5,7 @@
  *
  * Part:        Main program structure.
  *
- * Version:     $Id: main.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: main.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -21,6 +21,7 @@
  */
 
 #include "main.h"
+#include "memory.h"
 
 /* SIGHUP handler */
 void sighup(int sig)
@@ -31,8 +32,20 @@ void sighup(int sig)
   thread_add_terminate_event(master);
 }
 
+/* SIGCHLD handler */
+void sigchld(int sig)
+{
+  int child;
+
+  wait(&child);
+  child >>= 9;
+  if (child)
+    syslog(LOG_INFO, "Error from notify program, code:%d, %s"
+                   , child, strerror(child));
+}
+
 /* Signal wrapper */
-void * signal_set(int signo, void (*func)(int))
+void *signal_set(int signo, void (*func)(int))
 {
   int ret;
   struct sigaction sig;
@@ -54,22 +67,22 @@ void * signal_set(int signo, void (*func)(int))
 }
 
 /* Initialize signal handler */
-void signal_init()
+void signal_init(void)
 {
-  signal_set (SIGHUP,  sighup);
-  signal_set (SIGINT,  sighup);
-  signal_set (SIGTERM, sighup);
-  signal_set (SIGKILL, sighup);
+  signal_set(SIGHUP,  sighup);
+  signal_set(SIGINT,  sighup);
+  signal_set(SIGTERM, sighup);
+  signal_set(SIGKILL, sighup);
+  signal_set (SIGCHLD, sigchld);
 }
 
 /* Daemonization function coming from zebra source code */
-int daemon (int nochdir, int noclose)
+int daemon(int nochdir, int noclose)
 {
   pid_t pid;
 
-  pid = fork ();
-
   /* In case of fork is error. */
+  pid = fork ();
   if (pid < 0) {
     perror ("fork");
     return -1;
@@ -81,14 +94,13 @@ int daemon (int nochdir, int noclose)
 
   /* Become session leader and get pid. */
   pid = setsid();
-
   if (pid < -1) {
     perror ("setsid");
     return -1;
   }
 
   /* Change directory to root. */
-  if (! nochdir)
+  if (!nochdir)
     chdir ("/");
 
   /* File descriptor close. */
@@ -106,17 +118,131 @@ int daemon (int nochdir, int noclose)
   }
 
   umask (0);
-
   return 0;
 }
 
+/* Usage function */
+static void usage(const char *prog)
+{
+  fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+  fprintf(stderr,
+    "Usage:\n"
+    "  %s\n"
+    "  %s -n\n"
+    "  %s -f keepalived.conf\n"
+    "  %s -d\n"
+    "  %s -h\n"
+    "  %s -v\n\n",
+    prog, prog, prog, prog, prog, prog);
+  fprintf(stderr,
+    "Commands:\n"
+    "Either long or short options are allowed.\n"
+    "  %s --dont-fork       -n       Dont fork the daemon process.\n"
+    "  %s --use-file        -f       Use the specified configuration file.\n"
+    "                                Default is /etc/keepalived/keepalived.conf.\n"
+    "  %s --dump-conf       -d       Dump the configuration data.\n"
+    "  %s --log-console     -l       Log message to local console.\n"
+    "  %s --help            -h       Display this short inlined help screen.\n"
+    "  %s --version         -v       Display the version number\n",
+    prog, prog, prog, prog, prog, prog);
+}
+
+/* Command line parser */
+static char *parse_cmdline(int argc, char **argv)
+{
+  poptContext context;
+  char *optarg = NULL;
+  char *conf_file = NULL;
+  int c;
+
+  struct poptOption options_table[] = {
+    {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
+    {"help", 'h', POPT_ARG_NONE, NULL, 'h'},
+    {"log-console", 'l', POPT_ARG_NONE, NULL, 'l'},
+    {"dont-fork", 'n', POPT_ARG_NONE, NULL, 'n'},
+    {"dump-conf", 'd', POPT_ARG_NONE, NULL, 'd'},
+    {"use-file", 'f', POPT_ARG_STRING, &optarg, 'f'},
+    {NULL, 0, 0, NULL, 0}
+  };
+
+  context = poptGetContext(PROG, argc, (const char **)argv
+                                     , options_table, 0);
+  if ((c = poptGetNextOpt(context)) < 0) {
+    return NULL;
+  }
+
+  /* The first option car */
+  switch (c) {
+    case 'v':
+      fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+      exit(0);
+      break;
+    case 'h':
+      usage(argv[0]);
+      exit(0);
+      break;
+    case 'l':
+      debug |= 1;
+      break;
+    case 'n':
+      debug |= 2;
+      break;
+    case 'd':
+      debug |= 4;
+      break;
+    case 'f':
+      conf_file = optarg;
+      break;
+  }
+
+  /* the others */
+  while ((c = poptGetNextOpt(context)) >= 0) {
+    switch (c) {
+      case 'l':
+        debug |= 1;
+        break;
+      case 'n':
+        debug |= 2;
+        break;
+      case 'd':
+        debug |= 4;
+        break;
+      case 'f':
+        conf_file = optarg;
+        break;
+    }
+  }
+
+  /* check unexpected arguments */
+  if ((optarg = (char *)poptGetArg(context))) {
+    fprintf(stderr, "unexpected argument %s\n", optarg);
+    return NULL;
+  }
+
+  /* free the allocated context */
+  poptFreeContext(context);
+
+  return((conf_file)?conf_file:NULL);
+}
+
 /* Entry point */
 int main(int argc, char **argv)
 {
   configuration_data *conf_data;
-  struct thread thread;
+  char *conf_file = NULL;
+  thread thread;
 
-  openlog(PROG,LOG_PID, LOG_DAEMON);
+  /* Init debugging level */
+  debug = 0;
+
+  /*
+   * Parse command line and set debug level.
+   * bits 0..7 reserved by main.c
+   */
+  conf_file = parse_cmdline(argc, argv);
+
+  openlog(PROG, LOG_PID | (debug & 1)?LOG_CONS:0
+              , LOG_DAEMON);
   syslog(LOG_INFO, "Starting "PROG" v"VERSION);
 
   /* Check if keepalived is already running */
@@ -127,7 +253,9 @@ int main(int argc, char **argv)
   }
 
   /* daemonize process */
-  daemon(0, 0);
+  if (!(debug & 2)) {
+    daemon(0, 0);
+  }
 
   /* write the pidfile */
   if (!pidfile_write(getpid())) {
@@ -137,14 +265,20 @@ int main(int argc, char **argv)
   }
 
   /* Parse the configuration file */
-  if (!(conf_data = (configuration_data *)conf_reader())) {
+  if (!(conf_data = (configuration_data *)conf_reader(conf_file))) {
+    syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
     closelog();
     exit(0);
   }
 
-#ifdef DEBUG
-  dump_conf(conf_data);
-#endif
+  /* SSL load static data & initialize common ctx context */
+  if (!(conf_data->ssldata = init_ssl_ctx(conf_data->ssldata))) {
+    closelog();
+    exit(0);
+  }
+
+  if (debug & 4) 
+    dump_conf(conf_data);
 
   if (!init_services(conf_data->lvstopology)) {
     syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
@@ -163,22 +297,35 @@ int main(int argc, char **argv)
   register_worker_thread(master, conf_data);
 
   /* processing the master thread queues, return and execute one ready thread */
-  while(thread_fetch(master, &thread))
+  while(thread_fetch(master, &thread)) {
+
+    /* Run until error, used for debuging only */
+#ifdef _DEBUG_
+    if ((debug & 520) == 520) {
+      debug &= ~520;
+      thread_add_terminate_event(master);
+    }
+#endif
     thread_call(&thread);
+  }
 
   /* Reached when terminate signal catched */
   syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
 
-  /* We then cleanup the room & closelog */
+  /* Just cleanup memory & exit */
   thread_destroy_master(master);
   clear_services(conf_data->lvstopology);
-
-  /* Stop VRRP instances */
   clear_vrrp_instance(conf_data->vrrp);
+  clear_ssl(conf_data->ssldata);
   clear_conf(conf_data);
-  closelog();
+
   pidfile_rm();
 
+#ifdef _DEBUG_
+  keepalived_free_final();
+#endif
+
+  closelog();
   /* finally return from system */
   exit(0);
 }
diff --git a/main.h b/main.h
index ef815ce..1618a84 100644 (file)
--- a/main.h
+++ b/main.h
@@ -5,7 +5,7 @@
  *
  * Part:        Main program include file.
  *
- * Version:     $Id: main.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: main.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -25,6 +25,8 @@
 
 /* global includes */
 #include <sys/stat.h>
+#include <sys/wait.h>
+#include <popt.h>
 
 /* local includes */
 #include "utils.h"
 #include "scheduler.h"
 #include "ipwrapper.h"
 #include "smtp.h"
+#include "vrrp.h"
+#include "check_ssl.h"
 
 /* global var */
-struct thread_master *master;
+thread_master *master;
+unsigned int debug;
+
+/* SSL support */
+extern void clear_ssl(SSL_DATA *ssl);
+extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
 
 /* Build version */
 #define PROG    "keepalived"
-#define VERSION "0.4.8 (20/11, 2001)"
+#define VERSION "0.4.9 (10/12, 2001)"
 
 #endif
diff --git a/md5.c b/md5.c
deleted file mode 100644 (file)
index 3e2dc33..0000000
--- a/md5.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * The rest of the code is derived from MD5C.C by RSADSI. Minor cosmetic
- * changes to accomodate it in the kernel by ji.
- * Minor changes to make 64 bit clean by Peter Onion (i.e. using u_int*_t).
- */
-
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/*
- * Additions by JI
- *
- * HAVEMEMCOPY is defined if mem* routines are available
- *
- * HAVEHTON is defined if htons() and htonl() can be used
- * for big/little endian conversions
- *
- */
-
-#include <stddef.h>
-#include <string.h>
-#include <sys/types.h> /* for u_int*_t */
-
-#include "md5.h"
-#include "endian.h"   /* sets BYTE_ORDER, LITTLE_ENDIAN, and BIG_ENDIAN */
-
-#define HAVEMEMCOPY 1  /* use ISO C's memcpy and memset */
-
-/* Constants for MD5Transform routine.
- */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-#define MD5Transform _MD5Transform
-
-static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
-
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define Encode MD5_memcpy
-#define Decode MD5_memcpy
-#else
-static void Encode PROTO_LIST
-  ((unsigned char *, UINT4 *, unsigned int));
-static void Decode PROTO_LIST
-  ((UINT4 *, unsigned char *, unsigned int));
-#endif
-
-#ifdef HAVEMEMCOPY
-#include <memory.h>
-#define MD5_memcpy     memcpy
-#define MD5_memset     memset
-#else
-#ifdef HAVEBCOPY
-#define MD5_memcpy(_a,_b,_c) memcpy((_a), (_b),(_c))
-#define MD5_memset(_a,_b,_c) memset((_a), '\0',(_c))
-#else
-static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
-static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
-#endif
-#endif
-static unsigned char PADDING[64] = {
-  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-void MD5Init (context)
-MD5_CTX *context;                                        /* context */
-{
-  context->count[0] = context->count[1] = 0;
-  /* Load magic initialization constants.
-*/
-  context->state[0] = 0x67452301;
-  context->state[1] = 0xefcdab89;
-  context->state[2] = 0x98badcfe;
-  context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
-  operation, processing another message block, and updating the
-  context.
- */
-void MD5Update (context, input, inputLen)
-MD5_CTX *context;                                        /* context */
-unsigned char *input;                                /* input block */
-UINT4 inputLen;                            /* length of input block */
-{
-  UINT4 i;
-  unsigned int index, partLen;
-
-  /* Compute number of bytes mod 64 */
-  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
-  /* Update number of bits */
-  if ((context->count[0] += (inputLen << 3)) < (inputLen << 3))
-       context->count[1]++;
-  context->count[1] += (inputLen >> 29);
-
-  partLen = 64 - index;
-
-  /* Transform as many times as possible. */
-  if (inputLen >= partLen) {
-       MD5_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
-       MD5Transform (context->state, context->buffer);
-
-       for (i = partLen; i + 63 < inputLen; i += 64)
-           MD5Transform (context->state, &input[i]);
-
-       index = 0;
-  }
-  else
-       i = 0;
-
-  /* Buffer remaining input */
-  MD5_memcpy((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
-  the message digest and zeroizing the context.
- */
-void MD5Final (digest, context)
-unsigned char digest[16];                         /* message digest */
-MD5_CTX *context;                                       /* context */
-{
-  unsigned char bits[8];
-  unsigned int index, padLen;
-
-  /* Save number of bits */
-  Encode (bits, context->count, 8);
-
-  /* Pad out to 56 mod 64.
-*/
-  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
-  padLen = (index < 56) ? (56 - index) : (120 - index);
-  MD5Update (context, PADDING, padLen);
-
-  /* Append length (before padding) */
-  MD5Update (context, bits, 8);
-
-  if (digest != NULL)                  /* Bill Simpson's padding */
-  {
-         /* store state in digest */
-         Encode (digest, context->state, 16);
-
-         /* Zeroize sensitive information.
-          */
-         MD5_memset ((POINTER)context, 0, sizeof (*context));
-  }
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform (state, block)
-UINT4 state[4];
-unsigned char block[64];
-{
-  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
-  Decode (x, block, 64);
-
-  /* Round 1 */
-  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
-  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
-  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
-  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
-  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
-  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
-  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
-  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
-  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
-  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
-  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
-  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
-  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
-  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
-  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
-  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
-  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
-  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
-  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
-  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
-  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
-  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
-  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
-  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
-  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
-  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
-  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
-  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
-  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
-  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
-  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
-  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
-  /* Round 3 */
-  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
-  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
-  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
-  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
-  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
-  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
-  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
-  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
-  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
-  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
-  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
-  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
-  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
-  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
-  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
-  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
-  /* Round 4 */
-  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
-  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
-  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
-  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
-  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
-  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
-  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
-  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
-  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
-  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
-  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
-  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
-  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
-  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
-  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
-  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
-  state[0] += a;
-  state[1] += b;
-  state[2] += c;
-  state[3] += d;
-
-  /* Zeroize sensitive information.
-*/
-  MD5_memset ((POINTER)x, 0, sizeof (x));
-}
-
-#if BYTE_ORDER != LITTLE_ENDIAN
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
-  a multiple of 4.
- */
-static void Encode (output, input, len)
-unsigned char *output;
-UINT4 *input;
-unsigned int len;
-{
-  unsigned int i, j;
-
-  for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
-  }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
-  a multiple of 4.
- */
-static void Decode (output, input, len)
-UINT4 *output;
-unsigned char *input;
-unsigned int len;
-{
-  unsigned int i, j;
-
-  for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
-   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-}
-
-#endif
-
-#ifndef HAVEMEMCOPY
-#ifndef HAVEBCOPY
-/* Note: Replace "for loop" with standard memcpy if possible.
- */
-
-static void MD5_memcpy (output, input, len)
-POINTER output;
-POINTER input;
-unsigned int len;
-{
-  unsigned int i;
-
-  for (i = 0; i < len; i++)
-
- output[i] = input[i];
-}
-
-/* Note: Replace "for loop" with standard memset if possible.
- */
-static void MD5_memset (output, value, len)
-POINTER output;
-int value;
-unsigned int len;
-{
-  unsigned int i;
-
-  for (i = 0; i < len; i++)
- ((char *)output)[i] = (char)value;
-}
-#endif
-#endif
-
diff --git a/md5.h b/md5.h
deleted file mode 100644 (file)
index 7da4c94..0000000
--- a/md5.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* GLOBAL.H - RSAREF types and constants
- */
-
-/* PROTOTYPES should be set to one if and only if the compiler supports
-     function argument prototyping.
-   The following makes PROTOTYPES default to 0 if it has not already
-     been defined with C compiler flags.
- */
-#ifndef PROTOTYPES
-#define PROTOTYPES 1
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-
-/* UINT2 defines a two byte word */
-typedef u_int16_t UINT2;
-
-/* UINT4 defines a four byte word */
-typedef u_int32_t UINT4;
-
-/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
-   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
-     returns an empty list.
- */
-
-#if PROTOTYPES
-#define PROTO_LIST(list) list
-#else
-#define PROTO_LIST(list) ()
-#endif
-
-
-/* MD5.H - header file for MD5C.C
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/* MD5 context. */
-typedef struct {
-  UINT4 state[4];                                   /* state (ABCD) */
-  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
-  unsigned char buffer[64];                         /* input buffer */
-} MD5_CTX;
-
-void MD5Init PROTO_LIST ((MD5_CTX *));
-void MD5Update PROTO_LIST
-  ((MD5_CTX *, unsigned char *, UINT4));
-void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
-
-#define _MD5_H_
diff --git a/memory.c b/memory.c
new file mode 100644 (file)
index 0000000..8b23abe
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,369 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        Memory management framework. This framework is used to
+ *              find any memory leak.
+ *
+ * Version:     $Id: memory.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#include "memory.h"
+
+
+void *xalloc(unsigned long size)
+{
+  void *mem;
+
+  if ((mem = malloc(size)))
+    memset(mem, 0, size);
+  return mem;
+}
+
+/* KeepAlived memory management. in debug mode,
+ * help finding eventual memory leak.
+ * Allocation memory types manipulated are :
+ *
+ * +type+--------meaning--------+
+ * ! 0  ! Free slot             !
+ * ! 1  ! Overrun               !
+ * ! 2  ! free null             !
+ * ! 3  ! realloc null          !
+ * ! 4  ! Not previus allocated !
+ * ! 8  ! Last free list        !
+ * ! 9  ! Allocated             !
+ * +----+-----------------------+
+ *
+ * global variabel debug bit 9 ( 512 ) used to
+ * flag some memory error.
+ *
+ */
+
+#ifdef _DEBUG_
+extern void print_buffer(int,char *);
+
+typedef struct {
+  int           type;
+  int           line;
+  char          *func;
+  char          *file;
+  void          *ptr;
+  unsigned long size;
+  long          csum;
+} MEMCHECK;
+
+/* Last free pointers */
+static MEMCHECK free_list [256];
+
+static MEMCHECK alloc_list[512];
+static int number_alloc_list = 0;
+static int n                 = 0; /* Alloc list pointer */
+static int f                 = 0; /* Free list pointer */
+static int s                 = 0; /* Indent counter */
+
+static char * nspace(int n)
+{
+
+  return "";
+
+/*
+ static char buf[64];
+ int start = 0; 
+ char *p;
+ p = buf;
+ while ( n-- > start ) {       
+  *p++ = ' '; 
+ }
+ *p=0;
+
+ return buf;
+*/
+
+}
+
+char *keepalived_malloc(unsigned long size, char *file, char *function, int line)
+{
+  void *buf;
+  int i = 0;
+  long check;
+
+  buf = xalloc(size+sizeof(long)) ;
+
+  check =  0xa5a5 + size;
+  *(long *)((char *)buf+size) = check;
+
+  while (i < number_alloc_list) {
+    if (alloc_list[i].type == 0)
+      break;
+    i++;
+  }
+
+  if (i == number_alloc_list)
+    number_alloc_list++;
+
+  alloc_list[i].ptr  = buf;
+  alloc_list[i].size = size;
+  alloc_list[i].file = file;
+  alloc_list[i].func = function;
+  alloc_list[i].line = line;
+  alloc_list[i].csum = check;
+  alloc_list[i].type = 9;
+
+  if (debug & 1)
+    printf("%sxalloc[%3d:%3d], %p, %4ld at %s, %3d, %s\n"
+           ,nspace(s++), i, number_alloc_list, buf, size, file, line, function);
+
+  n++;
+  return buf;
+}
+
+int keepalived_free(void * buffer, char *file, char *function, int line)
+{
+  int i = 0;
+  void *buf;
+
+  /* If nullpointer remember */
+  if (buffer == NULL) {
+    i = number_alloc_list++;
+    alloc_list[i].ptr  = buffer;
+    alloc_list[i].size = 0;
+    alloc_list[i].file = file;
+    alloc_list[i].func = function;
+    alloc_list[i].line = line;
+    alloc_list[i].type = 2;
+    if (debug & 1)
+      printf("%sfree NULL in %s, %3d, %s\n", nspace(s),file, line, function);
+
+    debug |= 512;      /* Memory Error detect */
+
+    return n;
+  } else
+    buf = buffer;
+
+  while (i < number_alloc_list) {
+    if (alloc_list[i].type == 9 && alloc_list[i].ptr == buf) {
+      if (*((long *)((char *)alloc_list[i].ptr+alloc_list[i].size)) == alloc_list[i].csum)
+        alloc_list[i].type = 0; /* Release */
+      else {
+        alloc_list[i].type = 1; /* Overrun */
+        if (debug & 1) {  
+          printf("%sfree corrupt, buffer overrun [%3d:%3d], %p, %4ld at %s, %3d, %s\n"
+                 ,nspace(--s), i, number_alloc_list, buf, alloc_list[i].size, file, line, function);
+          print_buffer(alloc_list[i].size + sizeof(long), alloc_list[i].ptr);
+          printf("%sCheck_sum\n", nspace(i));
+          print_buffer(sizeof(long), (char *) & alloc_list[i].csum);
+
+          debug |= 512;   /* Memory Error detect */
+        }    
+      }
+      break;
+    }
+    i++;
+  }
+
+  /*  Not found */
+  if (i == number_alloc_list) {
+    printf("Free ERROR %p\n", buffer);
+    number_alloc_list++;
+    alloc_list[i].ptr  = buf;
+    alloc_list[i].size = 0;
+    alloc_list[i].file = file;
+    alloc_list[i].func = function;
+    alloc_list[i].line = line;
+    alloc_list[i].type = 4;
+    debug |= 512;
+
+    return n;
+  }
+
+  if (buffer != NULL)
+    free(buffer);
+
+  if (debug & 1)
+    printf("%sfree  [%3d:%3d], %p, %4ld at %s, %3d, %s\n"
+           , nspace(--s), i, number_alloc_list, buf, alloc_list[i].size, file, line, function);
+
+  free_list[f].file = file;
+  free_list[f].line = line;
+  free_list[f].func = function;
+  free_list[f].ptr  = buffer;
+  free_list[f].type = 8;
+  free_list[f].csum = i;  /* Using this field for row id */
+
+  f++;
+  f&=255;
+  n--;
+
+  return n;
+}
+
+void keepalived_free_final(void)
+{
+  unsigned int sum=0, overrun=0, badptr=0;
+  int i, j;
+  i = 0;
+
+  printf("\n---[Keepalived memory dump]---\n\n");
+
+  while (i < number_alloc_list) {
+    switch (alloc_list[i].type ) {
+      case 3:
+        badptr++;
+        printf("null pointer to realloc(nil,%ld)! at %s, %3d, %s\n"
+               , alloc_list[i].size
+               , alloc_list[i].file
+               , alloc_list[i].line
+               , alloc_list[i].func);
+        break;
+      case 4:
+        badptr++;
+        printf("pointer not found in table to free(%p) [%3d:%3d], at %s, %3d, %s\n"
+               , alloc_list[i].ptr
+               , i, number_alloc_list
+               , alloc_list[i].file
+               , alloc_list[i].line
+               , alloc_list[i].func);
+        for (j=0; j< 256; j++)
+          if (free_list[j].ptr == alloc_list[i].ptr)
+            if (free_list[j].type == 8)
+              printf("  -> pointer allready released at [%3d:%3d], at %s, %3d, %s\n"
+                     , (int) free_list[j].csum, number_alloc_list
+                     , free_list[j].file
+                     , free_list[j].line
+                     , free_list[j].func);
+        break;
+      case 2:
+        badptr++;
+        printf("null pointer to free(nil)! at %s, %3d, %s\n"
+               , alloc_list[i].file
+               , alloc_list[i].line
+               , alloc_list[i].func);
+        break;
+      case 1:
+        overrun ++;
+        printf("%p [%3d:%3d], %4ld buffer overrun!:\n"
+               , alloc_list[i].ptr
+               , i, number_alloc_list
+               , alloc_list[i].size);
+        printf(" --> source of malloc: %s, %3d, %s\n"
+               , alloc_list[i].file
+               , alloc_list[i].line
+               , alloc_list[i].func);
+        break;
+      case 9:
+        sum += alloc_list[i].size;
+        printf("%p [%3d:%3d], %4ld not released!:\n"
+               , alloc_list[i].ptr
+               , i, number_alloc_list
+               , alloc_list[i].size);
+        printf(" --> source of malloc: %s, %3d, %s\n"
+               , alloc_list[i].file
+               , alloc_list[i].line
+               , alloc_list[i].func);
+        break;
+    }
+    i++;
+  }
+
+  printf("\n\n---[Keepalived memory dump summary]---\n");
+  printf("Total number of bytes not freed...: %d\n", sum);
+  printf("Number of entries not freed.......: %d\n", n);
+  printf("Maximum allocated entries.........: %d\n", number_alloc_list);
+  printf("Number of bad entries.............: %d\n", badptr);
+  printf("Number of buffer overrun..........: %d\n\n", overrun);
+
+  if (sum || n || badptr || overrun)
+    printf("=> Program seems to have some memory problem !!!\n\n");
+  else
+    printf("=> Program seems to be memory allocation safe...\n\n");
+}
+
+void *keepalived_realloc(void * buffer, unsigned long size, char *file, char* function, int line)
+{
+  int i = 0;
+  void *buf, *buf2;
+  long check;
+
+  if (buffer == NULL) {
+    printf("realloc %p %s, %3d %s\n", buffer, file, line, function);
+    i = number_alloc_list++;
+    alloc_list[i].ptr  = buf;
+    alloc_list[i].size = 0;
+    alloc_list[i].file = file;
+    alloc_list[i].func = function;
+    alloc_list[i].line = line;
+    alloc_list[i].type = 3;
+    return keepalived_malloc(size, file, function, line);
+  }
+
+  buf = buffer;
+
+  while (i < number_alloc_list) {
+    if (alloc_list[i].ptr == buf) {
+      buf = alloc_list[i].ptr;
+      alloc_list[i].ptr = NULL;
+        break;
+    }
+    i++;
+  }
+
+  /* not found */
+  if (i == number_alloc_list) {
+    printf("realloc ERROR no matching xalloc %p \n", buffer);
+    number_alloc_list++;
+    alloc_list[i].ptr  = buf;
+    alloc_list[i].size = 0;
+    alloc_list[i].file = file;
+    alloc_list[i].func = function;
+    alloc_list[i].line = line;
+    alloc_list[i].type = 9;
+    debug |= 512;                     /* Memory Error detect */
+    return NULL;
+  }
+
+  buf2 = ((char *)buf)+alloc_list[i].size;
+
+  if (*(long *)(buf2) != alloc_list[i].csum) {
+    alloc_list[i].type = 1;
+    debug |= 512;                    /* Memory Error detect */
+  }
+  buf = realloc(buffer, size+sizeof(long));
+
+  check                       = 0xa5a5 + size;
+  *(long *)((char *)buf+size) = check;
+  alloc_list[i].csum          = check;
+
+  if (debug & 1)
+    printf("%srealloc [%3d:%3d] %p, %4ld %s %d %s -> %p %4ld %s %d %s\n"
+           , nspace(s),i, number_alloc_list
+           , alloc_list[i].ptr
+           , alloc_list[i].size, file, line, function, buf, size
+           , alloc_list[i].file
+           , alloc_list[i].line
+           , alloc_list[i].func);
+
+  alloc_list[i].ptr  = buf;
+  alloc_list[i].size = size;
+  alloc_list[i].file = file;
+  alloc_list[i].line = line;
+  alloc_list[i].func = function;
+
+  return buf;
+}
+
+#endif
diff --git a/memory.h b/memory.h
new file mode 100644 (file)
index 0000000..6614f51
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,60 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        memory.c include file.
+ *
+ * Version:     $Id: memory.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
+ *
+ * Authors:     Alexandre Cassen, <acassen@linux-vs.org>
+ *              Jan Holmberg, <jan@artech.net>
+ *
+ *              This program is distributed in the hope that it will be useful,
+ *              but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *              See the GNU General Public License for more details.
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _MEMORY_H
+#define _MEMORY_H
+
+/* system includes */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* extern types */
+extern unsigned int debug;
+
+/* Local defines */
+#ifdef _DEBUG_
+
+#define MALLOC(n)    ( keepalived_malloc((n), \
+                      (__FILE__), (__FUNCTION__), (__LINE__)) )
+#define FREE(b)      ( keepalived_free((b), \
+                      (__FILE__), (__FUNCTION__), (__LINE__)) )
+#define REALLOC(b,n) ( keepalived_realloc((b), (n), \
+                      (__FILE__), (__FUNCTION__), (__LINE__)) )
+
+/* Memory debug prototypes defs */
+extern char *keepalived_malloc(unsigned long, char *, char *, int);
+extern int keepalived_free(void *, char *, char*, int);
+extern void *keepalived_realloc(void *, unsigned long, char *, char *, int);
+extern void keepalived_free_final(void);
+
+#else
+
+#define MALLOC(n)    (xalloc(n))
+#define FREE(p)      (free(p))
+#define REALLOC(p,n) (realloc((p),(n)))
+
+#endif
+
+#endif
index bcd7736..d9e9ec7 100644 (file)
--- a/pidfile.c
+++ b/pidfile.c
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile utility.
  *
- * Version:     $Id: pidfile.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: pidfile.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -37,13 +37,13 @@ int pidfile_write(int pid)
 }
 
 /* Remove the running daemon pidfile */
-void pidfile_rm()
+void pidfile_rm(void)
 {
   unlink(PIDFILENAME);
 }
 
 /* return the daemon running state */
-int keepalived_running()
+int keepalived_running(void)
 {
   FILE *pidfile = fopen(PIDFILENAME,"r");
   pid_t pid;
index 1360a2e..72cce4e 100644 (file)
--- a/pidfile.h
+++ b/pidfile.h
@@ -5,7 +5,7 @@
  *
  * Part:        pidfile.c include file.
  *
- * Version:     $Id: pidfile.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: pidfile.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -35,7 +35,7 @@
 
 /* Prototypes */
 extern int pidfile_write(int pid);
-extern void pidfile_rm();
-extern int keepalived_running();
+extern void pidfile_rm(void);
+extern int keepalived_running(void);
 
 #endif
diff --git a/samples/client.pem b/samples/client.pem
new file mode 100644 (file)
index 0000000..06f2e6c
--- /dev/null
@@ -0,0 +1,32 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D3B09E4CA5421FF
+
+SaDJA2MhJ12ZmDxfGkSLhQgjYPEQYqVfs5b4DZTz+9pJqzuNxHrZZU43oArbWBdB
+3DKc1THejbyHF2lY7xgPLk/5iax5r+CXesDKZroSliHyERBIOCUgDN6ecwvVGtYv
+C8IhlwGPEXyxr59lyV37RjkSUVXYBqiRbLlNIcQtp5T6GkFe+yftOnv6/UADCLTS
+Pu8xwkda1rf7dgPwYIKuk2SOTTe1VMDtWacRUGu8NteTJ4aiVaeeo9wdsKId5U2b
+Z7NTJjOjvdXOLRonfkGvDXmrmN4eICks0bV0ZBtkULAfGjKNGs6riY+XNGKNRmjI
+idRRB0za+EGorpiJ/vbe7n7uaFXIJlfqCwhTi4Up3mS8sR4tLHfmdjp85GV9P9B3
+xX3CHIeG5/EYDt0Qn1gRL5ODL/0O7nFGJslhcQUS6bMmcg9nSzhClTE2gREz0j9g
+pwzvRpEkIl3Tw4niZLIX8fW2cEIyKTBMCCG2MDwHHgXRL3SUXkOGeitFefkcXN/z
+/UWRS8XQcX7/lGWCiuEpgn+esoirjf8lFNVsx6OT0UXj3oBxGrz1iB/vpu/PMBVQ
+JsbEPSh/ElHSDUItw2ytjJmkolRtM01b7cFj16ZxbHjinXWTIGZFWUYIlaeA2zHK
+D/NRMFJwjrQYhjRgPqltvbw7M01Co7SNFBwSotARr36FBjsxbOH3F1jY6w+kXvJU
+X5m83C9UONM2K7kkKYXbE2yW+kzJF2LFX0Uu4yDluxNG767/WwqiQSI63aIzNAPp
+rSsaIMBSbVZia8q49gcvGyuvqBZpwm/PcZwr/PHJjvGs8hdU1ACmyQ==
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIICFTCCAX4CAgECMA0GCSqGSIb3DQEBBAUAMFcxCzAJBgNVBAYTAlVTMRMwEQYD
+VQQKEwpSVEZNLCBJbmMuMRkwFwYDVQQLExBXaWRnZXRzIERpdmlzaW9uMRgwFgYD
+VQQDEw9UZXN0IENBMjAwMTA1MTcwHhcNMDEwNTE3MTYxMTM2WhcNMDQwMzA2MTYx
+MTM2WjBOMQswCQYDVQQGEwJVUzETMBEGA1UEChMKUlRGTSwgSW5jLjEZMBcGA1UE
+CxMQV2lkZ2V0cyBEaXZpc2lvbjEPMA0GA1UEAxMGY2xpZW50MIGfMA0GCSqGSIb3
+DQEBAQUAA4GNADCBiQKBgQCHNWSoNh6msUwYGGd7TYQDsdSG0ao6QXaYjk+78ZyM
+QeZUBu2dZFjG4wnzkKwrD4rp/J5PLR9AdxR72lb9AavEOKL2UDHJGsscZkGVw/bz
+ZbxrKF2rvdpZSvKP1OhV1MOds/WTpRm1gcmVSoV5vLOMqVjzjHoxQ/+1zpjzMxWL
+0wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACTJhRR5tv8A7dc5+zmKR1Q/i8qE3Mrn
+mp/MOXHfX+ifJ/w+twoc/yd4En+7pr+hGsiTofct1JOZDW9Akq/ZGu1+NpVRT7Cw
+53EdMwpi7ArwZAsLIUBsKA7QmLTbdwjU5S7WlZ24eygZHyqZrK4Few+JuzlFkkoI
+FIDCfinyz24m
+-----END CERTIFICATE-----
diff --git a/samples/dh1024.pem b/samples/dh1024.pem
new file mode 100644 (file)
index 0000000..aa68d98
--- /dev/null
@@ -0,0 +1,5 @@
+-----BEGIN DH PARAMETERS-----
+MIGHAoGBANmAnfkETuKHOCWaE+W+F3kM/e7z5A8hZb7OqwGMQrUOaBEAr4BWeZBn
+G/87hhwZgNP69/KUchm714qd/PpOspCaUJ20x6PcmKujpAgca/f19HGMBjRawQMk
+R9oaBwazuQT0l0rTTKmvpMEcrQQIcVWii3CZI56I56oqF8biGPD7AgEC
+-----END DH PARAMETERS-----
diff --git a/samples/keepalived.conf.SSL_GET b/samples/keepalived.conf.SSL_GET
new file mode 100644 (file)
index 0000000..bb1626b
--- /dev/null
@@ -0,0 +1,87 @@
+# 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
+}
+
+;SSL {
+  password password
+  ca /etc/keepalived/root.pem
+  certificate /etc/keepalived/dh1024.pem
+  key /etc/keepalived/client.pem
+}
+
+vrrp_instance VI_1 {
+    state MASTER
+    interface eth0
+    virtual_router_id 51
+    priority 100
+    advert_int 1
+    authentication {
+        auth_type AH
+        auth_pass 1111
+    }
+    virtual_ipaddress {
+        192.168.200.16
+        192.168.200.17
+        192.168.200.18
+    }
+}
+
+virtual_server 192.168.200.100 443 {
+    delay_loop 6
+    lb_algo rr 
+    lb_kind NAT
+    nat_mask 255.255.255.0
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.201.100 443 {
+        weight 1
+        SSL_GET {
+            url { 
+              path /
+              digest ff20ad2481f97b1754ef3e12ecd3a9cc
+            }
+            url { 
+              path /mrtg/
+              digest 9b3a0c85a887a256d6939da88aabd8cd
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+}
+
+virtual_server 192.168.200.100 80 {
+    delay_loop 6
+    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
+        HTTP_GET {
+            url { 
+              path /
+              digest ff20ad2481f97b1754ef3e12ecd3a9cc
+            }
+            url { 
+              path /mrtg/
+              digest 9b3a0c85a887a256d6939da88aabd8cd
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+}
diff --git a/samples/keepalived.conf.ssl b/samples/keepalived.conf.ssl
new file mode 100644 (file)
index 0000000..62592c8
--- /dev/null
@@ -0,0 +1,33 @@
+# 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 192.168.200.100 80 {
+    delay_loop 6
+    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
+        SSL_GET {
+            url { 
+              path /
+              digest FF20AD2481F97B1754EF3E12ECD3A9CC
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 3
+        }
+    }
+}
diff --git a/samples/root.pem b/samples/root.pem
new file mode 100644 (file)
index 0000000..db0c59f
--- /dev/null
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICIjCCAYugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJVUzET
+MBEGA1UEChMKUlRGTSwgSW5jLjEZMBcGA1UECxMQV2lkZ2V0cyBEaXZpc2lvbjEY
+MBYGA1UEAxMPVGVzdCBDQTIwMDEwNTE3MB4XDTAxMDUxNzE2MDExNFoXDTA2MTIy
+NTE2MDExNFowVzELMAkGA1UEBhMCVVMxEzARBgNVBAoTClJURk0sIEluYy4xGTAX
+BgNVBAsTEFdpZGdldHMgRGl2aXNpb24xGDAWBgNVBAMTD1Rlc3QgQ0EyMDAxMDUx
+NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmkX40warmH0+lnwD9YjsJhRz
+ZX6qXadFry0y2trZ6gMs8Mv33IKPwOu8TE7V+3PESEtjI2wr8juV9OkbIPOm+td5
+M8+6vXyIW+JBo3ch99i0QMTf5/jTgsW+3IjV8yEdiGcZFp2NWKLRvZPq2VRbuF7R
+1pvgcaRuBJ0wGOohwnsCAwEAATANBgkqhkiG9w0BAQQFAAOBgQCUB8zMKIlX5io8
+TalbzH9Qke7BcvFAL+wp/5w1ToVsWkNrINSWKv6bl/jcqOD3aPhK7qhaeOU8ZWKL
+PoPPCnRl9Wo+1JtsOO3qIgJP79Bl9ooLGahixF2v/gea5qNISjQvwYllLSa//APP
+6kXHngO0RIRbiTBYHSkAzm6hDdsvVA==
+-----END CERTIFICATE-----
index 338cd82..d1991d0 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: scheduler.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  */
 
 #include "scheduler.h"
+#include "memory.h"
 
 /* Make thread master. */
-struct thread_master *
-thread_make_master ()
+thread_master *thread_make_master(void)
 {
-  struct thread_master *new;
+  thread_master *new;
 
-  new = (struct thread_master *)malloc(sizeof (struct thread_master));
-  memset(new,0,sizeof(struct thread_master));
+  new = (thread_master *)MALLOC(sizeof(thread_master));
 
   return new;
 }
 
 /* Make a new http thread arg */
-struct http_thread_arg *
-thread_http_checker_arg_new()
+http_thread_arg *thread_http_checker_arg_new(void)
 {
-  struct http_thread_arg *new;
+  http_thread_arg *new;
 
   /* Allocate & prepare the thread argument structure */
-  new = (struct http_thread_arg *)malloc(sizeof (struct http_thread_arg));
-  memset(new, 0, sizeof(struct http_thread_arg));
+  new = (http_thread_arg *)MALLOC(sizeof(http_thread_arg));
 
   return new;
 }
 
 /* Make a new global thread arg */
-struct thread_arg *
-thread_arg_new(configuration_data *root,
-               virtualserver *vserver,
-               realserver *rserver)
+thread_arg *thread_arg_new(configuration_data *root
+                          , virtualserver *vserver
+                          , realserver *rserver)
 {
-  struct thread_arg *new;
+  thread_arg *new;
 
   /* Allocate & prepare the thread argument structure */
-  new = (struct thread_arg *)malloc(sizeof (struct thread_arg));
-  memset(new, 0, sizeof(struct thread_arg));
+  new = (thread_arg *)MALLOC(sizeof(thread_arg));
 
   /* Assign structure elements */
   new->root = root;
@@ -71,8 +66,7 @@ thread_arg_new(configuration_data *root,
 }
 
 /* Add a new thread to the list. */
-static void
-thread_list_add (struct thread_list *list, struct thread *thread)
+static void thread_list_add(thread_list *list, thread *thread)
 {
   thread->next = NULL;
   thread->prev = list->tail;
@@ -85,10 +79,9 @@ thread_list_add (struct thread_list *list, struct thread *thread)
 }
 
 /* Add a new thread to the list. */
-void
-thread_list_add_before (struct thread_list *list, 
-                       struct thread *point, 
-                       struct thread *thread)
+void thread_list_add_before(thread_list *list
+                           , thread *point
+                           , thread *thread)
 {
   thread->next = point;
   thread->prev = point->prev;
@@ -101,8 +94,7 @@ thread_list_add_before (struct thread_list *list,
 }
 
 /* timer compare */
-int
-thread_timer_cmp (struct timeval a, struct timeval b)
+int thread_timer_cmp(TIMEVAL a, TIMEVAL b)
 {
   if (a.tv_sec > b.tv_sec) 
     return 1;
@@ -116,10 +108,9 @@ thread_timer_cmp (struct timeval a, struct timeval b)
 }
 
 /* Add a thread in the list sorted by timeval */
-void
-thread_list_add_timeval(struct thread_list *list, struct thread *thread)
+void thread_list_add_timeval(thread_list *list, thread *thread)
 {
-  struct thread *tt;
+  struct _thread *tt;
 
   for (tt = list->head; tt; tt = tt->next)
     if (thread_timer_cmp (thread->sands, tt->sands) <= 0)
@@ -132,8 +123,7 @@ thread_list_add_timeval(struct thread_list *list, struct thread *thread)
 }
 
 /* Delete a thread from the list. */
-struct thread *
-thread_list_delete (struct thread_list *list, struct thread *thread)
+thread *thread_list_delete(thread_list *list, thread *thread)
 {
   if (thread->next)
     thread->next->prev = thread->prev;
@@ -149,76 +139,80 @@ thread_list_delete (struct thread_list *list, struct thread *thread)
 }
 
 /* Free all unused thread. */
-static void
-thread_clean_unuse (struct thread_master *m)
+static void thread_clean_unuse(thread_master *m)
 {
-  struct thread *thread;
+  thread *thread;
 
   thread = m->unuse.head;
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
+    thread_arg *ta;
 
     t = thread;
     thread = t->next;
 
-    thread_list_delete (&m->unuse, t);
+    thread_list_delete(&m->unuse, t);
+    ta = t->arg;
 
-    /* FIXME : Need to add thread_arg memory cleanup */
+    /* thread_arg memory cleanup */
+    if (ta) {
+      if (ta->checker_arg)
+        FREE(ta->checker_arg);
+      /* Free the arg if it is a thread_arg entry. */
+      if (ta->vs)
+        FREE(ta);
+    }
 
     /* free the thread */
-    free(t);
+    FREE(t);
     m->alloc--;
   }
 }
 
 /* Move thread to unuse list. */
-static void
-thread_add_unuse (struct thread_master *m, struct thread *thread)
+static void thread_add_unuse(thread_master *m, thread *thread)
 {
-  assert (m != NULL);
-  assert (thread->next == NULL);
-  assert (thread->prev == NULL);
-  assert (thread->type == THREAD_UNUSED);
-  thread_list_add (&m->unuse, thread);
+  assert(m != NULL);
+  assert(thread->next == NULL);
+  assert(thread->prev == NULL);
+  assert(thread->type == THREAD_UNUSED);
+  thread_list_add(&m->unuse, thread);
 }
 
 /* Move list element to unuse queue */
-void
-thread_destroy_list(struct thread_master *m, struct thread_list thread_list)
+void thread_destroy_list(thread_master *m, thread_list thread_list)
 {
-  struct thread *thread;
+  thread *thread;
 
   thread = thread_list.head;
 
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
 
     t = thread;
     thread = t->next;
 
-    thread_list_delete (&thread_list, t);
+    thread_list_delete(&thread_list, t);
     t->type = THREAD_UNUSED;
-    thread_add_unuse (m, t);
+    thread_add_unuse(m, t);
   }
 }
 
 /* Stop thread scheduler. */
-void
-thread_destroy_master (struct thread_master *m)
+void thread_destroy_master(thread_master *m)
 {
-  thread_destroy_list(m,m->read);
-  thread_destroy_list(m,m->write);
-  thread_destroy_list(m,m->timer);
-  thread_destroy_list(m,m->event);
-  thread_destroy_list(m,m->ready);
-
-  thread_clean_unuse (m);
-  free(m);
+  thread_destroy_list(m, m->read);
+  thread_destroy_list(m, m->write);
+  thread_destroy_list(m, m->timer);
+  thread_destroy_list(m, m->event);
+  thread_destroy_list(m, m->ready);
+
+  thread_clean_unuse(m);
+  FREE(m);
 }
 
 /* Delete top of the list and return it. */
-struct thread *
-thread_trim_head (struct thread_list *list)
+thread *thread_trim_head(thread_list *list)
 {
   if (list->head)
     return thread_list_delete (list, list->head);
@@ -226,43 +220,40 @@ thread_trim_head (struct thread_list *list)
 }
 
 /* Make new thread. */
-struct thread *
-thread_new (struct thread_master *m)
+thread *thread_new(thread_master *m)
 {
-  struct thread *new;
+  thread *new;
 
   /* If one thread is already allocated return it */
   if (m->unuse.head) {
     new = thread_trim_head(&m->unuse);
-    memset(new,0,sizeof(struct thread));
+    memset(new, 0, sizeof(thread));
     return new;
   }
 
-  new = (struct thread *)malloc(sizeof(struct thread));
-  memset(new,0,sizeof(struct thread));
+  new = (thread *)MALLOC(sizeof(thread));
   m->alloc++;
   return new;
 }
 
 /* Add new read thread. */
-struct thread *
-thread_add_read (struct thread_master *m, 
-                int (*func)(struct thread *),
-                void *arg,
-                int fd,
-                 long timer)
+thread *thread_add_read(thread_master *m
+                       , int (*func)(thread *)
+                       , void *arg
+                       , int fd
+                       , long timer)
 {
-  struct thread *thread;
-  struct timeval timer_now;
+  thread *thread;
+  TIMEVAL timer_now;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
   if (FD_ISSET (fd, &m->readfd)) {
     syslog(LOG_WARNING, "There is already read fd [%d]", fd);
     return NULL;
   }
 
-  thread = thread_new (m);
+  thread = thread_new(m);
   thread->type = THREAD_READ;
   thread->id = 0;
   thread->master = m;
@@ -288,24 +279,23 @@ thread_add_read (struct thread_master *m,
 }
 
 /* Add new write thread. */
-struct thread *
-thread_add_write (struct thread_master *m,
-                int (*func)(struct thread *),
-                void *arg,
-                int fd,
-                 long timer)
+thread *thread_add_write(thread_master *m
+                        , int (*func)(thread *)
+                        , void *arg
+                        , int fd
+                        , long timer)
 {
-  struct thread *thread;
-  struct timeval timer_now;
+  thread *thread;
+  TIMEVAL timer_now;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
   if (FD_ISSET (fd, &m->writefd)) {
     syslog(LOG_WARNING, "There is already write fd [%d]", fd);
     return NULL;
   }
 
-  thread = thread_new (m);
+  thread = thread_new(m);
   thread->type = THREAD_WRITE;
   thread->id = 0;
   thread->master = m;
@@ -331,18 +321,17 @@ thread_add_write (struct thread_master *m,
 }
 
 /* Add timer event thread. */
-struct thread *
-thread_add_timer (struct thread_master *m,
-                 int (*func)(struct thread *),
-                 void *arg,
-                 long timer)
+thread *thread_add_timer (thread_master *m
+                         , int (*func)(thread *)
+                         , void *arg
+                         , long timer)
 {
-  struct timeval timer_now;
-  struct thread *thread;
+  thread *thread;
+  TIMEVAL timer_now;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
-  thread = thread_new (m);
+  thread = thread_new(m);
   thread->type = THREAD_TIMER;
   thread->id = 0;
   thread->master = m;
@@ -366,17 +355,16 @@ thread_add_timer (struct thread_master *m,
 }
 
 /* Add simple event thread. */
-struct thread *
-thread_add_event (struct thread_master *m,
-                 int (*func)(struct thread *), 
-                 void *arg,
-                 int val)
+thread *thread_add_event(thread_master *m
+                        , int (*func)(thread *)
+                        , void *arg
+                        , int val)
 {
-  struct thread *thread;
+  thread *thread;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
-  thread = thread_new (m);
+  thread = thread_new(m);
   thread->type = THREAD_EVENT;
   thread->id = 0;
   thread->master = m;
@@ -389,28 +377,26 @@ thread_add_event (struct thread_master *m,
 }
 
 /* Add simple event thread. */
-struct thread *
-thread_add_terminate_event (struct thread_master *m)
+thread *thread_add_terminate_event(thread_master *m)
 {
-  struct thread *thread;
+  thread *thread;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
-  thread = thread_new (m);
+  thread = thread_new(m);
   thread->type = THREAD_TERMINATE;
   thread->id = 0;
   thread->master = m;
   thread->func = NULL;
   thread->arg = NULL;
   thread->u.val = 0;
-  thread_list_add (&m->event, thread);
+  thread_list_add(&m->event, thread);
 
   return thread;
 }
 
 /* Cancel thread from scheduler. */
-void
-thread_cancel (struct thread *thread)
+void thread_cancel(thread *thread)
 {
   switch (thread->type) {
     case THREAD_READ:
@@ -437,18 +423,17 @@ thread_cancel (struct thread *thread)
   }
 
   thread->type = THREAD_UNUSED;
-  thread_add_unuse (thread->master, thread);
+  thread_add_unuse(thread->master, thread);
 }
 
 /* Delete all events which has argument value arg. */
-void
-thread_cancel_event (struct thread_master *m, void *arg)
+void thread_cancel_event(thread_master *m, void *arg)
 {
-  struct thread *thread;
+  thread *thread;
 
   thread = m->event.head;
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
 
     t = thread;
     thread = t->next;
@@ -462,10 +447,9 @@ thread_cancel_event (struct thread_master *m, void *arg)
 }
 
 /* timer sub */
-struct timeval
-thread_timer_sub (struct timeval a, struct timeval b)
+TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b)
 {
-  struct timeval ret;
+  TIMEVAL ret;
 
   ret.tv_usec = a.tv_usec - b.tv_usec;
   ret.tv_sec = a.tv_sec - b.tv_sec;
@@ -478,7 +462,7 @@ thread_timer_sub (struct timeval a, struct timeval b)
   return ret;
 }
 
-static int thread_timer_null(struct timeval timer)
+static int thread_timer_null(TIMEVAL timer)
 {
   if (timer.tv_sec == 0 && timer.tv_usec == 0)
     return 1;
@@ -487,11 +471,10 @@ static int thread_timer_null(struct timeval timer)
 }
 
 /* Compute the wait timer. Take care of timeouted fd */
-struct timeval *
-thread_compute_timer(struct thread_master *m, struct timeval *timer_wait)
+TIMEVAL *thread_compute_timer(thread_master *m, TIMEVAL *timer_wait)
 {
-  struct timeval timer_now;
-  struct timeval timer_min;
+  TIMEVAL timer_now;
+  TIMEVAL timer_min;
 
   timer_min.tv_sec = 0;
   timer_min.tv_usec = 0;
@@ -531,29 +514,27 @@ thread_compute_timer(struct thread_master *m, struct timeval *timer_wait)
 }
 
 /* Fetch next ready thread. */
-struct thread *
-thread_fetch (struct thread_master *m, struct thread *fetch)
+thread *thread_fetch(thread_master *m, thread *fetch)
 {
   int ret;
-  struct thread *thread;
+  thread *thread;
   fd_set readfd;
   fd_set writefd;
   fd_set exceptfd;
-  struct timeval timer_now;
-  struct timeval *timer_wait;
+  TIMEVAL timer_now;
+  TIMEVAL *timer_wait;
 
-  assert (m != NULL);
+  assert(m != NULL);
 
   /* Timer allocation */
-  timer_wait = (struct timeval *)malloc(sizeof(struct timeval));
-  memset(timer_wait,0,sizeof(struct timeval));
+  timer_wait = (TIMEVAL *)MALLOC(sizeof(TIMEVAL));
 
 retry:  /* When thread can't fetch try to find next thread again. */
 
   /* If there is event process it first. */
   while ((thread = thread_trim_head(&m->event))) {
     *fetch = *thread;
-    free(timer_wait);
+    FREE(timer_wait);
 
     /* If daemon hanging event is received return NULL pointer */ 
     if (thread->type == THREAD_TERMINATE) {
@@ -571,7 +552,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
     *fetch = *thread;
     thread->type = THREAD_UNUSED;
     thread_add_unuse(m, thread);
-    free(timer_wait);
+    FREE(timer_wait);
     return fetch;
   }
 
@@ -601,7 +582,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
   thread = m->read.head;
 
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
       
     t = thread;
     thread = t->next;
@@ -627,7 +608,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
   thread = m->write.head;
 
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
 
     t = thread;
     thread = t->next;
@@ -655,7 +636,7 @@ retry:  /* When thread can't fetch try to find next thread again. */
 
   thread = m->timer.head;
   while (thread) {
-    struct thread *t;
+    struct _thread *t;
 
     t = thread;
     thread = t->next;
@@ -678,59 +659,66 @@ retry:  /* When thread can't fetch try to find next thread again. */
   thread->type = THREAD_UNUSED;
   thread_add_unuse (m, thread);
   
-  free(timer_wait);
+  FREE(timer_wait);
   return fetch;
 }
 
 /* Make unique thread id for non pthread version of thread manager. */
-unsigned long int
-thread_get_id ()
+unsigned long int thread_get_id(void)
 {
   static unsigned long int counter = 0;
   return ++counter;
 }
 
 /* Call thread ! */
-void
-thread_call (struct thread *thread)
+void thread_call(thread *thread)
 {
   thread->id = thread_get_id ();
-  (*thread->func) (thread);
+  (*thread->func)(thread);
 }
 
 /* Register worker thread. One per realserver of each virtualserver */
-void
-register_vs_worker_thread(struct thread_master *master, 
-                          configuration_data *root,
-                          virtualserver *lstptr)
+void register_vs_worker_thread(thread_master *master
+                              , configuration_data *root
+                              , virtualserver *lstptr)
 {
   realserver *pointersvr;
-  struct thread_arg *thread_arg;
+  thread_arg *thread_arg;
 
   pointersvr = lstptr->svr;
 
   while (lstptr->svr) {
 
     switch (lstptr->svr->method->type) {
+      /* Implemented section */
       case TCP_CHECK_ID:
-        thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
-        thread_add_timer(master, tcp_connect_thread, thread_arg,
-                         thread_arg->vs->delay_loop);
-        break;
       case HTTP_GET_ID:
-        thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
-        thread_arg->checker_arg = (struct http_thread_arg *)thread_http_checker_arg_new();
-        thread_add_timer(master, http_connect_thread, thread_arg,
-                         thread_arg->vs->delay_loop);
-        break;
       case SSL_GET_ID:
+      case MISC_CHECK_ID:
+        thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
+
+        switch (lstptr->svr->method->type ) {
+          case TCP_CHECK_ID:
+            thread_add_timer(master, tcp_connect_thread, thread_arg
+                                   , BOOTSTRAP_DELAY);
+            break;
+          case HTTP_GET_ID:
+          case SSL_GET_ID:
+            thread_arg->checker_arg = (http_thread_arg *)thread_http_checker_arg_new();
+            thread_add_timer(master, http_connect_thread, thread_arg
+                                   , BOOTSTRAP_DELAY);
+            break;
+          case MISC_CHECK_ID:
+            thread_add_timer(master, misc_check_thread, thread_arg
+                                   , BOOTSTRAP_DELAY);
+            break;
+        }
+
         break;
+
+      /* Not yet implemented section */
       case LDAP_GET_ID:
         break;
-      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,8 +730,7 @@ register_vs_worker_thread(struct thread_master *master,
 }
 
 /* Register each virtualserver realservers worker thread */
-void
-register_worker_thread(struct thread_master *master, configuration_data *lstptr)
+void register_worker_thread(thread_master *master, configuration_data *lstptr)
 {
   virtualserver *pointervs;
 
index 318de41..8453e59 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        scheduler.c include file.
  *
- * Version:     $Id: scheduler.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: scheduler.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 #include "cfreader.h"
 #include "check.h"
 
+/* Thread itself. */
+typedef struct timeval TIMEVAL;
+typedef struct _thread {
+  unsigned long id;
+  unsigned char type;                  /* thread type */
+  struct _thread *next;                        /* next pointer of the thread */
+  struct _thread *prev;                        /* previous pointer of the thread */
+  struct _thread_master *master;       /* pointer to the struct thread_master. */
+  int (*func) (struct _thread *);      /* event function */
+  void *arg;                           /* event argument */
+  TIMEVAL sands;                       /* rest of time sands value. */
+  union {
+    int val;                           /* second argument of the event. */
+    int fd;                            /* file descriptor in case of read/write. */
+  } u;
+} thread;
+
 /* Linked list of thread. */
-struct thread_list
-{
-  struct thread *head;
-  struct thread *tail;
+typedef struct _thread_list {
+  thread *head;
+  thread *tail;
   int count;
-};
+} thread_list;
 
 /* Master of the theads. */
-struct thread_master
-{
-  struct thread_list read;
-  struct thread_list write;
-  struct thread_list timer;
-  struct thread_list event;
-  struct thread_list ready;
-  struct thread_list unuse;
+typedef struct _thread_master {
+  thread_list read;
+  thread_list write;
+  thread_list timer;
+  thread_list event;
+  thread_list ready;
+  thread_list unuse;
   fd_set readfd;
   fd_set writefd;
   fd_set exceptfd;
   unsigned long alloc;
-};
-
-/* Thread itself. */
-struct thread
-{
-  unsigned long id;
-  unsigned char type;          /* thread type */
-  struct thread *next;         /* next pointer of the thread */
-  struct thread *prev;         /* previous pointer of the thread */
-  struct thread_master *master;        /* pointer to the struct thread_master. */
-  int (*func) (struct thread *); /* event function */
-  void *arg;                   /* event argument */
-  struct timeval sands;        /* rest of time sands value. */
-  union {
-    int val;                   /* second argument of the event. */
-    int fd;                    /* file descriptor in case of read/write. */
-  } u;
-};
+} thread_master;
 
 /* Thread types. */
 #define THREAD_READ           0
@@ -87,6 +85,7 @@ struct thread
 /* MICRO SEC def */
 #define TIMER_SEC_MICRO 1000000
 #define TIMER_MAX_SEC   1000
+#define BOOTSTRAP_DELAY 1
 
 /* Macros. */
 #define THREAD_ARG(X) ((X)->arg)
@@ -95,80 +94,58 @@ struct thread
 #define THREAD_VAL(X) ((X)->u.val)
 
 /* Prototypes. */
-struct thread_master *thread_make_master ();
-
-struct thread *
-thread_add_terminate_event (struct thread_master *m);
+thread_master *thread_make_master(void);
 
-void
-thread_destroy_master (struct thread_master *m);
+thread *thread_add_terminate_event(thread_master *m);
 
-struct thread_arg *
-thread_arg_new (configuration_data *root,
-                virtualserver *vserver,
-                realserver *rserver);
+void thread_destroy_master(thread_master *m);
 
-struct thread *
-thread_add_read (struct thread_master *m, 
-                int (*func)(struct thread *),
-                void *arg,
-                int fd,
-                 long timeout);
+thread_arg *thread_arg_new(configuration_data *root
+                          , virtualserver *vserver
+                          , realserver *rserver);
 
-struct thread *
-thread_add_write (struct thread_master *m,
-                int (*func)(struct thread *),
-                void *arg,
-                int fd,
-                 long timeout);
+thread *thread_add_read(thread_master *m
+                       , int (*func)(thread *)
+                       , void *arg
+                       , int fd
+                       , long timeout);
 
-struct thread *
-thread_add_timer (struct thread_master *m,
-                 int (*func)(struct thread *),
-                 void *arg,
-                 long timer);
+thread *thread_add_write(thread_master *m
+                        , int (*func)(thread *)
+                        , void *arg
+                        , int fd
+                        , long timeout);
 
-struct thread *
-thread_add_event (struct thread_master *m,
-                 int (*func)(struct thread *), 
-                 void *arg,
-                 int val);
+thread *thread_add_timer(thread_master *m
+                        , int (*func)(thread *)
+                        , void *arg
+                        , long timer);
 
+thread *thread_add_event(thread_master *m
+                        , int (*func)(thread *)
+                        , void *arg
+                        , int val);
 
-void
-thread_cancel (struct thread *thread);
+void thread_cancel(thread *thread);
 
-void
-thread_cancel_event (struct thread_master *m, void *arg);
+void thread_cancel_event(thread_master *m, void *arg);
 
-struct thread *
-thread_fetch (struct thread_master *m, 
-             struct thread *fetch);
+thread *thread_fetch(thread_master *m, thread *fetch);
 
-void
-thread_call (struct thread *thread);
+void thread_call(thread *thread);
 
-int
-thread_timer_cmp (struct timeval a, struct timeval b);
+int thread_timer_cmp(TIMEVAL a, TIMEVAL b);
 
-struct timeval
-thread_timer_sub (struct timeval a, struct timeval b);
+TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b);
 
-void
-register_worker_thread(struct thread_master *master,
-                       configuration_data *lstptr);
+void register_worker_thread(thread_master *master
+                           , configuration_data *lstptr);
 
 /* extern prototypes */
-extern int
-tcp_connect_thread(struct thread *thread);
-
-extern int
-http_connect_thread(struct thread *thread);
-
-extern int
-misc_check_thread(struct thread *thread);
-
-extern int
-vrrp_dispatcher_init_thread(struct thread *thread);
+extern int tcp_connect_thread(thread *thread);
+extern int http_connect_thread(thread *thread);
+extern int ssl_connect_thread(thread *thread);
+extern int misc_check_thread(thread *thread);
+extern int vrrp_dispatcher_init_thread(thread *thread);
 
 #endif
diff --git a/smtp.c b/smtp.c
index 7ea3d9a..b50d897 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: smtp.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
  */
 
 #include "smtp.h"
+#include "memory.h"
 
 /* static prototype */
-static int smtp_send_cmd_thread(struct thread *thread);
+static int smtp_send_cmd_thread(thread *thread);
 
-static void free_smtp_arg(struct smtp_thread_arg *smtp_arg)
+static void free_smtp_arg(smtp_thread_arg *smtp_arg)
 {
-  free(smtp_arg->subject);
-  free(smtp_arg->body);
-  free(smtp_arg);
+  FREE(smtp_arg->subject);
+  FREE(smtp_arg->body);
+  FREE(smtp_arg);
 }
 
-static char *fetch_next_email(struct thread_arg *thread_arg)
+static void free_smtp_all(thread_arg *thread_arg)
 {
-  struct smtp_thread_arg *smtp_arg;
+  free_smtp_arg(THREAD_ARG_CHECKER_ARG(thread_arg));
+  FREE(thread_arg);
+}
+
+static char *fetch_next_email(thread_arg *thread_arg)
+{
+  smtp_thread_arg *smtp_arg;
   int i = 0;
 
   smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
@@ -50,10 +57,10 @@ static char *fetch_next_email(struct thread_arg *thread_arg)
   return NULL;
 }
 
-static int smtp_read_cmd_thread(struct thread *thread)
+static int smtp_read_cmd_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  struct smtp_thread_arg *smtp_arg;
+  thread_arg *thread_arg;
+  smtp_thread_arg *smtp_arg;
   notification_email *pointeremail;
   char *fetched_email;
   long total_length = 0;
@@ -65,20 +72,20 @@ static int smtp_read_cmd_thread(struct thread *thread)
   smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
 
   if (thread->type == THREAD_READ_TIMEOUT) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "Timeout reading data to remote SMTP server [%s:%d].",
                       inet_ntoa(thread_arg->root->smtp_server),
                       SMTP_PORT);
 #endif
-    free_smtp_arg(smtp_arg);
+    free_smtp_all(thread_arg);
     thread_arg->checker_arg = NULL;
     close(thread->u.fd);
     return 0;
   }
 
   /* Allocate the get buffers */
-  buffer = (char *)malloc(SMTP_BUFFER_MAX);
-  buffer_tmp = (char *)malloc(SMTP_BUFFER_LENGTH);
+  buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
+  buffer_tmp = (char *)MALLOC(SMTP_BUFFER_LENGTH);
 
   /* Cleanup the room */
   memset(buffer, 0, SMTP_BUFFER_MAX);
@@ -87,32 +94,32 @@ static int smtp_read_cmd_thread(struct thread *thread)
   while ((rcv_buffer_size = read(thread->u.fd, buffer_tmp, SMTP_BUFFER_LENGTH)) != 0) {
     if (rcv_buffer_size == -1) {
       if (errno == EAGAIN) goto end;
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Error reading data to remote SMTP server [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(thread->u.fd);
-      free(buffer);
-      free(buffer_tmp);
+      FREE(buffer);
+      FREE(buffer_tmp);
       return 0;
     }
 
     /* received data overflow buffer size ? */
     if (total_length >= SMTP_BUFFER_MAX) {
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Received buffer from remote SMTP server [%s:%d]"
                         " overflow our get read buffer length.",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(thread->u.fd);
-      free(buffer);
-      free(buffer_tmp);
+      FREE(buffer);
+      FREE(buffer_tmp);
       return 0;
     } else {
       memcpy(buffer+total_length, buffer_tmp, rcv_buffer_size);
@@ -192,11 +199,11 @@ end:
 
     case quit:
       /* final state, we are disconnected from the remote host */
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(thread->u.fd);
-      free(buffer);
-      free(buffer_tmp);
+      FREE(buffer);
+      FREE(buffer_tmp);
       return 0;
       break;
 
@@ -208,13 +215,13 @@ end:
   thread_add_write(thread->master, smtp_send_cmd_thread, thread_arg, thread->u.fd,
                    thread_arg->root->smtp_connection_to);
 
-  free(buffer);
-  free(buffer_tmp);
+  FREE(buffer);
+  FREE(buffer_tmp);
   return 0;
 }
 
 /* Getting localhost official canonical name */
-static char *get_local_name()
+static char *get_local_name(void)
 {
   struct hostent *host;
   struct utsname name;
@@ -228,10 +235,10 @@ static char *get_local_name()
   return host->h_name;
 }
 
-static int smtp_send_cmd_thread(struct thread *thread)
+static int smtp_send_cmd_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  struct smtp_thread_arg *smtp_arg;
+  thread_arg *thread_arg;
+  smtp_thread_arg *smtp_arg;
   notification_email *pointeremail;
   char *fetched_email;
   char *buffer;
@@ -240,20 +247,19 @@ static int smtp_send_cmd_thread(struct thread *thread)
   smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
 
   if (thread->type == THREAD_WRITE_TIMEOUT) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "Timeout sending data to remote SMTP server [%s:%d].",
                       inet_ntoa(thread_arg->root->smtp_server),
                       SMTP_PORT);
 #endif
-    free_smtp_arg(smtp_arg);
+    free_smtp_all(thread_arg);
     thread_arg->checker_arg = NULL;
     close(thread->u.fd);
     return 0;
   }
 
   /* allocate temporary command buffer */
-  buffer = (char *)malloc(SMTP_BUFFER_MAX);
-  memset(buffer, 0, SMTP_BUFFER_MAX);
+  buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
 
   switch (smtp_arg->stage) {
     case connection:
@@ -312,16 +318,16 @@ static int smtp_send_cmd_thread(struct thread *thread)
       break;
 
     case error:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
       /* we just cleanup the room */
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(thread->u.fd);
-      free(buffer);
+      FREE(buffer);
       return 0;
       break;
   }
@@ -332,15 +338,15 @@ static int smtp_send_cmd_thread(struct thread *thread)
   thread_add_read(thread->master, smtp_read_cmd_thread, thread_arg, thread->u.fd,
                   thread_arg->root->smtp_connection_to);
 
-  free(buffer);
+  FREE(buffer);
   return 0;
 }
 
 /* SMTP checkers threads */
-static int smtp_check_thread(struct thread *thread)
+static int smtp_check_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  struct smtp_thread_arg *smtp_arg;
+  thread_arg *thread_arg;
+  smtp_thread_arg *smtp_arg;
   int status;
 
   thread_arg = THREAD_ARG(thread);
@@ -350,22 +356,22 @@ static int smtp_check_thread(struct thread *thread)
 
   switch (status) {
     case connect_error:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Error connecting SMTP server [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       break;
 
     case connect_timeout:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       break;
 
@@ -373,7 +379,7 @@ static int smtp_check_thread(struct thread *thread)
       /* Remote SMTP server is connected.
        * Register the next step thread smtp_cmd_thread.
        */
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected.",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
@@ -387,10 +393,10 @@ static int smtp_check_thread(struct thread *thread)
   return 0;
 }
 
-static int smtp_connect_thread(struct thread *thread)
+static int smtp_connect_thread(thread *thread)
 {
-  struct thread_arg *thread_arg;
-  struct smtp_thread_arg *smtp_arg;
+  thread_arg *thread_arg;
+  smtp_thread_arg *smtp_arg;
   enum connect_result status;
   int fd;
 
@@ -398,7 +404,7 @@ static int smtp_connect_thread(struct thread *thread)
   smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
 
   if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef DEBUG
+#ifdef _DEBUG_
     syslog(LOG_DEBUG, "SMTP connect fail to create socket.");
 #endif
     return 0;
@@ -408,31 +414,31 @@ static int smtp_connect_thread(struct thread *thread)
 
   switch (status) {
     case connect_error:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "SMTP connection ERROR to [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(fd);
       return 0;
       break;
 
     case connect_timeout:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "Timeout connecting SMTP server [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
 #endif
-      free_smtp_arg(smtp_arg);
+      free_smtp_all(thread_arg);
       thread_arg->checker_arg = NULL;
       close(fd);
       return 0;
       break;
 
     case connect_success:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "SMTP connection SUCCESS to [%s:%d].",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
@@ -441,7 +447,7 @@ static int smtp_connect_thread(struct thread *thread)
 
     /* Checking non-blocking connect, we wait until socket is writable */
     case connect_in_progress:
-#ifdef DEBUG
+#ifdef _DEBUG_
       syslog(LOG_DEBUG, "SMTP connection to [%s:%d] now IN_PROGRESS.",
                         inet_ntoa(thread_arg->root->smtp_server),
                         SMTP_PORT);
@@ -456,14 +462,14 @@ static int smtp_connect_thread(struct thread *thread)
   return 1;
 }
 
-void smtp_alert(struct thread_master *master,
-                configuration_data *root,
-                realserver *rserver,
-                const char *subject,
-                const char *body)
+void smtp_alert(thread_master *master
+                , configuration_data *root
+                , realserver *rserver
+                , const char *subject
+                , const char *body)
 {
-  struct thread_arg *thread_arg;
-  struct smtp_thread_arg *smtp_arg;
+  thread_arg *thread_arg;
+  smtp_thread_arg *smtp_arg;
 
   /* Only send mail if email specified */
   if (root->email) {
@@ -471,13 +477,9 @@ void smtp_alert(struct thread_master *master,
     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));
-
-    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 = (smtp_thread_arg *)MALLOC(sizeof(smtp_thread_arg));
+    smtp_arg->subject = (char *)MALLOC(MAX_SUBJECT_LENGTH);
+    smtp_arg->body = (char *)MALLOC(MAX_BODY_LENGTH);
 
     smtp_arg->stage = connection; /* first smtp command set to HELO */
 
diff --git a/smtp.h b/smtp.h
index 1a6a78b..bca819c 100644 (file)
--- a/smtp.h
+++ b/smtp.h
@@ -5,7 +5,7 @@
  *
  * Part:        smtp.c include file.
  *
- * Version:     $Id: smtp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: smtp.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -54,12 +54,12 @@ enum smtp_cmd {
 #define MAX_SUBJECT_LENGTH 256
 #define MAX_BODY_LENGTH    512
 
-struct smtp_thread_arg {
+typedef struct _smtp_thread_arg {
   enum smtp_cmd stage;
   int email_it;
   char *subject;
   char *body;
-};
+} smtp_thread_arg;
 
 /* Smtp error code */
 #define SMTP_CONNECT   "220"
@@ -80,10 +80,10 @@ struct smtp_thread_arg {
 #define SMTP_QUIT_CMD    "QUIT\n"
 
 /* Prototypes defs */
-extern void smtp_alert(struct thread_master *master,
-                       configuration_data *root,
-                       realserver *rserver,
-                       const char *subject,
-                       const char *body);
+extern void smtp_alert(thread_master *
+                       , configuration_data *
+                       , realserver *
+                       , const char *
+                       , const char *);
 
 #endif
diff --git a/utils.c b/utils.c
index e50581d..f78db3a 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -5,7 +5,7 @@
  *
  * Part:        General program utils.
  *
- * Version:     $Id: utils.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: utils.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
diff --git a/utils.h b/utils.h
index 3c4430b..ec6c7f3 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -1,5 +1,27 @@
-#ifndef _UTILES_H
-#define _UTILES_H
+/*
+ * 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:        utils.h include file.
+ *
+ * Version:     $Id: utils.h,v 0.4.9 2001/12/10 10:52:33 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 _UTILS_H
+#define _UTILS_H
 
 /* system includes */
 #include <stdio.h>
diff --git a/vrrp.c b/vrrp.c
index 0ba8d5e..2d95952 100644 (file)
--- a/vrrp.c
+++ b/vrrp.c
@@ -1,10 +1,14 @@
 /*
- * Soft:        Vrrpd is an implementation of VRRPv2 as specified in rfc2338.
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        VRRP implementation of VRRPv2 as specified in rfc2338.
  *              VRRP is a protocol which elect a master server on a LAN. If the
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
 /* local include */
 #include "vrrp_scheduler.h"
 #include "vrrp.h"
+#include "memory.h"
+
+/* Close all FDs >= a specified value */
+void closeall(int fd)
+{
+  int fdlimit = sysconf(_SC_OPEN_MAX);
+
+  while (fd < fdlimit)
+    close(fd++);
+}
+
+static char *notify_get_name(vrrp_rt *vsrv)
+{
+  static char notifyfile[FILENAME_MAX+1];
+
+  if (vsrv->notify_exec) {
+    if (vsrv->notify_file != NULL)
+      strncpy(notifyfile,vsrv->notify_file, FILENAME_MAX);
+    else
+      snprintf( notifyfile, sizeof(notifyfile),"%s/" VRRP_NOTIFY_FORMAT
+                          , VRRP_NOTIFY_DFL
+                          , vsrv->vif->ifname
+                          , vsrv->vrid );
+  }
+  return notifyfile;
+}
+
+/* Execute extern script/program */
+static int notify_exec( vrrp_rt *vsrv , char *cmd)
+{
+  char *name = notify_get_name(vsrv);
+  FILE *fOut = fopen(name, "r");
+  static char mycmd[FILENAME_MAX + 1 + 32];
+  char tmp[16];
+  int err;
+
+  pid_t pid;
+
+  if (!fOut) {
+    syslog(LOG_INFO, "Can't open %s (errno %d %s)\n", name
+                   , errno
+                   , strerror(errno));
+    return -1;
+  }
+  fclose(fOut);
+
+  pid = fork();
+
+  /* In case of fork is error. */
+  if (pid < 0) {
+    syslog (LOG_INFO, "Failed fork process");
+    return -1;
+  }
+
+  /* In case of this is parent process. */
+  if (pid) {
+    return (0);
+  }
+
+  closeall(0);
+
+  open("/dev/null", O_RDWR);
+  dup(0);
+  dup(0);
+
+  name  = notify_get_name(vsrv);
+
+  if (strlen(name) + strlen(cmd) + 32 >  FILENAME_MAX + 32) {
+    syslog(LOG_INFO,"To long exec stmt");
+    exit (1);
+  }
+
+  strcpy(mycmd,name);
+  strcat(mycmd," ");
+  strcat(mycmd,cmd);
+  strcat(mycmd," ");
+  snprintf(tmp,16,"%d",vsrv->vrid);
+  strcat(mycmd, tmp);
+
+  if (vsrv->debug > 0)
+   syslog(LOG_INFO, "Trying to exec %s", mycmd);
+
+  err = system(mycmd);
+
+  if (err != 0) {
+    if (err == 127)
+      syslog(LOG_ALERT, "Failed to exec %s", mycmd);
+    else
+      syslog(LOG_ALERT, "Error running %s, error: %d", mycmd, err);
+  }
+
+  exit(0);
+}
+
 
 /* compute checksum */
 static u_short in_csum( u_short *addr, int len, u_short csum)
@@ -178,7 +276,7 @@ static int vrrp_iphdr_len(vrrp_rt *vsrv)
 }
 
 /* IPSEC AH header length */
-int vrrp_ipsecah_len()
+int vrrp_ipsecah_len(void)
 {
   return sizeof(ipsec_ah);
 }
@@ -216,7 +314,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
+#ifdef _DEBUG_
 //  syslog(LOG_DEBUG, "IPSEC AH : SEQUENCE NUMBER : %d\n", ah->seq_number);
 #endif
     vsrv->ipsecah_counter->seq_number = ah->seq_number;
@@ -230,8 +328,7 @@ static int vrrp_in_chk_ipsecah(vrrp_rt *vsrv, char *buffer)
    * then compute a ICV to compare with the one present in AH pkt.
    * alloc a temp memory space to stock the ip mutable fields
    */
-  digest=(unsigned char *)malloc(16*sizeof(unsigned char *));
-  memset(digest, 0, 16*sizeof(unsigned char *));
+  digest = (unsigned char *)MALLOC(16*sizeof(unsigned char *));
 
   /* zero the ip mutable fields */
   ip->tos = 0;
@@ -251,7 +348,7 @@ static int vrrp_in_chk_ipsecah(vrrp_rt *vsrv, char *buffer)
     return 1;
   }
 
-  free(digest);
+  FREE(digest);
   return 0;
 }
 
@@ -440,8 +537,7 @@ static void vrrp_build_ipsecah(vrrp_rt *vsrv, char *buffer, int buflen)
   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 = (ICV_mutable_fields *)MALLOC(sizeof(ICV_mutable_fields));
 
   /* fill in next header filed --rfc2402.2.1 */
   ah->next_header = IPPROTO_VRRP;
@@ -504,8 +600,7 @@ static void vrrp_build_ipsecah(vrrp_rt *vsrv, char *buffer, int buflen)
      => No padding needed.
      -- rfc2402.3.3.3.1.1.1 & rfc2401.5
   */
-  digest=(unsigned char *)malloc(16*sizeof(unsigned char *));
-  memset(digest, 0, 16*sizeof(unsigned char *));
+  digest = (unsigned char *)MALLOC(16*sizeof(unsigned char *));
   hmac_md5(buffer, buflen,vsrv->vif->auth_data, sizeof(vsrv->vif->auth_data), digest);
   memcpy(ah->auth_data, digest, HMAC_MD5_TRUNC);
 
@@ -515,8 +610,8 @@ static void vrrp_build_ipsecah(vrrp_rt *vsrv, char *buffer, int buflen)
   ip->frag_off = ip_mutable_fields->frag_off;
   ip->check    = ip_mutable_fields->check;
 
-  free(ip_mutable_fields);
-  free(digest);
+  FREE(ip_mutable_fields);
+  FREE(digest);
 }
 
 /* build VRRP header */
@@ -616,8 +711,8 @@ static int vrrp_send_adv(vrrp_rt *vsrv, int prio)
   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();
-  buffer = calloc(buflen, 1);
-  memset(buffer,0,buflen);
+
+  buffer = MALLOC(buflen);
 
   /* build the packet  */
   vrrp_build_pkt(vsrv, prio, buffer, buflen);
@@ -626,7 +721,7 @@ static int vrrp_send_adv(vrrp_rt *vsrv, int prio)
   ret = vrrp_send_pkt(vsrv, buffer, buflen);
 
   /* free the memory */
-  free(buffer);
+  FREE(buffer);
   return ret;
 }
 
@@ -726,6 +821,14 @@ void vrrp_state_goto_master(vrrp_instance *vrrp_instance)
   syslog(LOG_INFO, "VRRP_Instance(%s) Entering MASTER STATE"
                  , vrrp_instance->iname);
 
+  if (vsrv->notify_exec) {
+    notify_exec(vsrv, "master");
+    if (vsrv->debug > 0)
+      syslog(LOG_INFO, "notify:%s, flg:%d"
+                     , vsrv->notify_file
+                     , vsrv->notify_exec);
+  }
+
   vsrv->state = VRRP_STATE_MAST;
 }
 
@@ -750,6 +853,14 @@ void vrrp_state_leave_master(vrrp_instance *instance)
   syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE"
                  , instance->iname);
 
+  if (vsrv->notify_exec) {
+    notify_exec(vsrv, "backup");
+    if  (vsrv->debug > 0)
+      syslog(LOG_INFO, "notify:%s, flg:%d"
+                     , vsrv->notify_file
+                     , vsrv->notify_exec);
+  }
+
   /* register the vrrp backup handler */
   vsrv->state = VRRP_STATE_BACK;
 }
@@ -757,10 +868,10 @@ void vrrp_state_leave_master(vrrp_instance *instance)
 /* BACKUP state processing */
 void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen)
 {
-  int ret = 0;
-  vrrp_rt *vsrv = instance->vsrv;
-  struct iphdr *iph = (struct iphdr *)buf;
-  vrrp_pkt *hd;
+  int ret      = 0;
+  vrrp_rt      *vsrv = instance->vsrv;
+  struct iphdr *iph  = (struct iphdr *)buf;
+  vrrp_pkt     *hd   = NULL;
 
   /* Fill the VRRP header */
   switch (iph->protocol) {
@@ -800,10 +911,10 @@ void vrrp_state_master_tx(vrrp_instance *instance, const int prio)
 
 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;
+  int ret            = 0;
+  vrrp_rt      *vsrv = instance->vsrv;
+  struct iphdr *iph  = (struct iphdr *)buf;
+  vrrp_pkt     *hd   = NULL; 
 
   /* Fill the VRRP header */
   switch (iph->protocol) {
diff --git a/vrrp.h b/vrrp.h
index f7db1bb..91d1d95 100644 (file)
--- a/vrrp.h
+++ b/vrrp.h
@@ -4,7 +4,9 @@
  *              master fails, a backup server takes over.
  *              The original implementation has been made by jerome etienne.
  *
- * Version:     $Id: vrrp.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Part:        vrrp.c program include file.
+ *
+ * Version:     $Id: vrrp.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              Based on the Jerome Etienne, <jetienne@arobas.net> code.
 #include "vrrp_ipsecah.h"
 #include "utils.h"
 
+
+/* Default dir to notify file */
+#define VRRP_NOTIFY_DFL "/etc/init.d"
+
+/* notify name (vrrpd-eth0-101) */
+#define VRRP_NOTIFY_FORMAT "vrrpd-%s-%d"
+
 typedef struct {       /* rfc2338.5.1 */
        uint8_t         vers_type;      /* 0-3=type, 4-7=version */
        uint8_t         vrid;           /* virtual router id */
@@ -102,6 +111,11 @@ typedef struct {
        int     wantstate;      /* user explicitly wants a state (back/mast) */
        int     fd;             /* the socket descriptor */
 
+        int     debug;          /* Debug level 0-4 */
+        int     notify_exec;
+        char    notify_file[FILENAME_MAX ];
+
+
        /* rfc2336.6.2 */
        uint32_t        ms_down_timer;
        struct timeval  sands;
@@ -127,13 +141,17 @@ typedef struct {
 #define VRRP_PACKET_KO       1
 #define VRRP_PACKET_DROP     2
 #define VRRP_PACKET_NULL     3
+#define VRRP_PACKET_OTHER    4      /* Muliple VRRP on LAN, Identify "other" VRRP */
 #define VRRP_PACKET_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_ADVERT_INT(d)      ((d)<1)
+
+#define VRRP_IS_BAD_DEBUG_INT(d)       ((d)<0 || (d)>4)
+
 
 #define VRRP_TIMER_HZ          1000000
 #define VRRP_TIMER_SKEW(srv)   ((256-(srv)->priority)*VRRP_TIMER_HZ/256) 
@@ -142,7 +160,7 @@ typedef struct {
 #define VRRP_MAX(a, b) ((a) > (b)?(a):(b))
 
 /* prototypes */
-extern int vrrp_ipsecah_len();
+extern int vrrp_ipsecah_len(void);
 extern int complete_vrrp_init(vrrp_rt *vsrv);
 extern void vrrp_state_stop_instance(vrrp_rt *vsrv);
 
index 975bfbe..d7b6405 100644 (file)
@@ -3,12 +3,9 @@
  *              <www.linuxvirtualserver.org>. It monitor & manipulate
  *              a loadbalanced server pool using multi-layer checks.
  *
- * Part:        VRRP implementation of VRRPv2 as specified in rfc2338.
- *              VRRP is a protocol which elect a master server on a LAN. If the
- *              master fails, a backup server takes over.
- *              The original implementation has been made by jerome etienne.
+ * Part:        NETLINK IPv4 address manipulation.
  *
- * Version:     $Id: vrrp_ipaddress.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 2abc17c..bb9bf40 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipaddress.c include file.
  *
- * Version:     $Id: vrrp_ipaddress.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_ipaddress.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 39f77a5..24a3687 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.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -23,7 +23,7 @@
  */
 
 #include "vrrp_ipsecah.h"
-#include "md5.h"
+#include <openssl/md5.h>
 
 /* hmac_md5 computation according to the RFCs 2085 & 2104 */
 void hmac_md5(unsigned char *buffer,int buffer_len,
@@ -45,9 +45,9 @@ void hmac_md5(unsigned char *buffer,int buffer_len,
     MD5_CTX tctx;
 
     /* Compute the MD5 digest */
-    MD5Init(&tctx);
-    MD5Update(&tctx,key,key_len);
-    MD5Final(tk,&tctx);
+    MD5_Init(&tctx);
+    MD5_Update(&tctx,key,key_len);
+    MD5_Final(tk,&tctx);
 
     key = tk;
     key_len = 16;
@@ -72,14 +72,14 @@ void hmac_md5(unsigned char *buffer,int buffer_len,
   }
 
   /* Compute inner MD5 */
-  MD5Init(&context);                     /* Init context for 1st pass */
-  MD5Update(&context,k_ipad,64);         /* start with inner pad */
-  MD5Update(&context,buffer,buffer_len); /* next with buffer datagram */
-  MD5Final(digest,&context);             /* Finish 1st pass */
+  MD5_Init(&context);                     /* Init context for 1st pass */
+  MD5_Update(&context,k_ipad,64);         /* start with inner pad */
+  MD5_Update(&context,buffer,buffer_len); /* next with buffer datagram */
+  MD5_Final(digest,&context);             /* Finish 1st pass */
 
   /* Compute outer MD5 */
-  MD5Init(&context);                     /* Init context for 2nd pass */
-  MD5Update(&context,k_opad,64);         /* start with inner pad */
-  MD5Update(&context,digest,16);         /* next result of 1st pass */
-  MD5Final(digest,&context);             /* Finish 2nd pass */
+  MD5_Init(&context);                     /* Init context for 2nd pass */
+  MD5_Update(&context,k_opad,64);         /* start with inner pad */
+  MD5_Update(&context,digest,16);         /* next result of 1st pass */
+  MD5_Final(digest,&context);             /* Finish 2nd pass */
 }
index eca257b..0844008 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_ipsecah.c include file.
  * 
- * Version:     $Id: vrrp_ipsecah.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_ipsecah.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
index d65e45e..d269d4c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        NETLINK kernel command channel.
  *
- * Version:     $Id: vrrp_netlink.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_netlink.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index e5e5a88..1ef780c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_netlink.c include file.
  *
- * Version:     $Id: vrrp_netlink.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_netlink.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
index 867cabd..0b5667f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        Sheduling framework for vrrp code.
  *
- * Version:     $Id: vrrp_scheduler.c,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.c,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *
@@ -23,6 +23,7 @@
 #include "vrrp_scheduler.h"
 #include "vrrp_ipsecah.h"
 #include "vrrp.h"
+#include "memory.h"
 
 /*
  * Initialize state handling
@@ -80,10 +81,10 @@ static void vrrp_init_sands(vrrp_instance *instance)
 }
 
 /* Timer functions */
-static struct timeval vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
+static TIMEVAL vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
 {
   vrrp_instance *ptr = vrrp;
-  struct timeval timer;
+  TIMEVAL timer;
 
   /* clean the memory */
   memset(&timer, 0, sizeof(struct timeval));
@@ -104,9 +105,9 @@ static struct timeval vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
   return timer;
 }
 
-static struct timeval vrrp_timer_delta(struct timeval timer)
+static TIMEVAL vrrp_timer_delta(TIMEVAL timer)
 {
-  struct timeval timer_now;
+  TIMEVAL timer_now;
 
   /* init timer */
   memset(&timer_now, 0, sizeof(struct timeval));
@@ -117,7 +118,7 @@ static struct timeval vrrp_timer_delta(struct timeval timer)
 
 static long vrrp_timer_fd(const int fd, vrrp_instance *instance)
 {
-  struct timeval timer;
+  TIMEVAL timer;
   long vrrp_timer = 0;
 
   timer = vrrp_compute_timer(fd, instance);
@@ -130,7 +131,7 @@ static long vrrp_timer_fd(const int fd, vrrp_instance *instance)
 static int vrrp_timer_vrid_timeout(const int fd, vrrp_instance *vrrp)
 {
   vrrp_instance *ptr = vrrp;
-  struct timeval vrrp_timer;
+  TIMEVAL vrrp_timer;
   int vrid = 0;
 
   /* clean the memory */
@@ -152,8 +153,8 @@ static int vrrp_timer_vrid_timeout(const int fd, vrrp_instance *vrrp)
 static void vrrp_timer_dump(vrrp_instance *vrrp)
 {
   vrrp_instance *ptr = vrrp;
-  struct timeval timer_now;
-  struct timeval timer;
+  TIMEVAL timer_now;
+  TIMEVAL timer;
   long vrrp_timer = 0;
 
   memset(&timer, 0, sizeof(struct timeval));
@@ -172,12 +173,12 @@ static void vrrp_timer_dump(vrrp_instance *vrrp)
 */
 
 /* Thread functions */
-static void vrrp_register_workers(struct thread_master *master,
-                                  vrrp_instance *instance,
-                                  sockpool *pool)
+static void vrrp_register_workers(thread_master *master
+                                  , vrrp_instance *instance
+                                  , sockpool *pool)
 {
   sockpool *poolptr = pool;
-  struct timeval timer;
+  TIMEVAL timer;
   long vrrp_timer = 0;
 
   /* init compute timer */
@@ -235,7 +236,7 @@ static sockpool *remove_sock(sockpool *pool)
   sockpool *t;
 
   t = (sockpool *)pool->next;
-  free(pool);
+  FREE(pool);
   return t;
 }
 
@@ -261,8 +262,7 @@ static sockpool *vrrp_create_sockpool(vrrp_instance *instance, sockpool *pool)
 
     if (!already_exist_sock(pool, ifindex, proto)) {
       /* allocate & clean the new struct */
-      sock = (sockpool *)malloc(sizeof(sockpool));
-      memset(sock, 0, sizeof(sockpool));
+      sock = (sockpool *)MALLOC(sizeof(sockpool));
 
       /* fill in the new sock structure */
       sock->ifindex = ifindex;
@@ -330,7 +330,7 @@ static void vrrp_set_fds(vrrp_instance *instance, sockpool *pool)
  * are multiplexed through this fds. So our design can handle 2*n
  * multiplexing points.
  */
-int vrrp_dispatcher_init_thread(struct thread *thread)
+int vrrp_dispatcher_init_thread(thread *thread)
 {
   vrrp_instance *instance = THREAD_ARG(thread);
   sockpool *pool;
@@ -378,16 +378,16 @@ static vrrp_instance *vrrp_search_instance(const int vrid, vrrp_instance *instan
   return NULL;
 }
 
-static void vrrp_handle_backup(vrrp_instance *instance,
-                               char *vrrp_buffer,
-                               int len)
+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)
+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;
@@ -404,9 +404,9 @@ static void vrrp_handle_become_master(vrrp_instance *instance,
   }
 }
 
-static void vrrp_handle_leave_master(vrrp_instance *instance,
-                                     char *vrrp_buffer,
-                                     int len)
+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"
@@ -415,9 +415,9 @@ static void vrrp_handle_leave_master(vrrp_instance *instance,
   }
 }
 
-static int vrrp_handle_state(vrrp_instance *instance,
-                             char *vrrp_buffer,
-                             int len)
+static int vrrp_handle_state(vrrp_instance *instance
+                             , char *vrrp_buffer
+                             , int len)
 {
   int previous_state;
 
@@ -500,7 +500,7 @@ static int vrrp_handle_state_timeout(vrrp_instance *instance)
 }
 
 /* Our read packet dispatcher */
-int vrrp_read_dispatcher_thread(struct thread *thread)
+int vrrp_read_dispatcher_thread(thread *thread)
 {
   vrrp_instance *instance = THREAD_ARG(thread);
   vrrp_instance *ptr = instance;
@@ -559,21 +559,16 @@ int vrrp_read_dispatcher_thread(struct thread *thread)
   } else {
 
     /* allocate & clean the read buffer */
-    vrrp_buffer = (char *)malloc(VRRP_PACKET_TEMP_LEN);
-    memset(vrrp_buffer, 0, VRRP_PACKET_TEMP_LEN);
+    vrrp_buffer = (char *)MALLOC(VRRP_PACKET_TEMP_LEN);
 
     /* read & affect received buffer */
     len = read(thread->u.fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
     iph = (struct iphdr *)vrrp_buffer;
 
-    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;
-    }
+    if (iph->protocol == IPPROTO_IPSEC_AH)
+      hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2) + vrrp_ipsecah_len());
+    else
+      hd = (vrrp_pkt *)((char *)iph + (iph->ihl<<2));
 
     /* Searching for matching instance */
     vrrp_instance = vrrp_search_instance(hd->vrid, instance);
@@ -619,7 +614,7 @@ int vrrp_read_dispatcher_thread(struct thread *thread)
     }
 
     /* cleanup the room */
-    free(vrrp_buffer);
+    FREE(vrrp_buffer);
 
   }
 
index d25a8ec..a8e3e38 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        vrrp_scheduler.c include file.
  * 
- * Version:     $Id: vrrp_scheduler.h,v 0.4.8 2001/11/20 15:26:11 acassen Exp $
+ * Version:     $Id: vrrp_scheduler.h,v 0.4.9 2001/12/10 10:52:33 acassen Exp $
  * 
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
  *              
@@ -50,7 +50,7 @@ typedef struct {
 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_read_dispatcher_thread(thread *thread);
 extern int vrrp_state_master_rx(vrrp_instance *instance, char *buf, int buflen);
 extern void vrrp_state_master_tx(vrrp_instance *instance, const int prio);
 extern void vrrp_state_backup(vrrp_instance *instance, char *buf, int buflen);