keepalived-0.2.6 v0.2.6
authorAlexandre Cassen <acassen@freebox.fr>
Tue, 6 Mar 2001 16:47:44 +0000 (17:47 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:53 +0000 (10:58 +0200)
52 files changed:
Makefile [new file with mode: 0644]
cfreader.c [new file with mode: 0644]
cfreader.h [new file with mode: 0644]
confread/Makefile [moved from keepalived/Makefile with 53% similarity]
confread/cfreader.c [new file with mode: 0644]
confread/cfreader.h [new file with mode: 0644]
confread/keepalived.conf [new file with mode: 0644]
confread/main.c [new file with mode: 0644]
confread/main.h [new file with mode: 0644]
confread/utils.c [new file with mode: 0644]
etc/keepalived/keepalived.conf [new file with mode: 0644]
etc/keepalived/log/keepalived.log [moved from keepalived/etc/keepalived/log/keepalived.log with 100% similarity]
etc/lvs.conf [new file with mode: 0644]
etc/rc.d/init.d/keepalived.init [new file with mode: 0755]
genhash/Makefile
genhash/genhash.c
genhash/genhash.h
genhash/md5.c [new file with mode: 0644]
genhash/md5.h [new file with mode: 0644]
httpget.c [new file with mode: 0644]
httpget.h [moved from keepalived/httpget.h with 82% similarity]
icmpcheck.c [moved from keepalived/icmpcheck.c with 95% similarity]
icmpcheck.h [moved from keepalived/icmpcheck.h with 97% similarity]
iputils.c [moved from keepalived/iputils.c with 100% similarity]
iputils.h [moved from keepalived/iputils.h with 89% similarity]
ipvswrapper.c [moved from keepalived/ipvswrapper.c with 81% similarity]
ipvswrapper.h [moved from keepalived/ipvswrapper.h with 95% similarity]
keepalived.c [moved from keepalived/keepalived.c with 50% similarity]
keepalived.h [moved from keepalived/keepalived.h with 88% similarity]
keepalived/cfreader.c [deleted file]
keepalived/cfreader.h [deleted file]
keepalived/etc/keepalived/keepalived.conf [deleted file]
keepalived/etc/lvs.conf [deleted file]
keepalived/httpget.c [deleted file]
keepalived/tcpcheck.c [deleted file]
libmd-0.3 [deleted file]
md5.c [new file with mode: 0644]
md5.h [new file with mode: 0644]
pidfile.c [new file with mode: 0644]
pidfile.h [moved from keepalived/utils.h with 83% similarity]
smtpwrapper.c [new file with mode: 0644]
smtpwrapper.h [new file with mode: 0644]
smtpwrapper/Makefile [new file with mode: 0644]
smtpwrapper/main.c [new file with mode: 0644]
smtpwrapper/main.h [new file with mode: 0644]
smtpwrapper/smtpwrapper.c [new file with mode: 0644]
smtpwrapper/smtpwrapper.h [new file with mode: 0644]
smtpwrapper/utils.c [new file with mode: 0644]
tcpcheck.c [new file with mode: 0644]
tcpcheck.h [moved from keepalived/tcpcheck.h with 75% similarity]
utils.c [moved from keepalived/utils.c with 83% similarity]
utils.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..88a627c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
+
+EXEC= keepalived
+CC= gcc
+#CFLAGS= -Wall -Wunused
+CFLAGS= 
+DEFS= md5.h iputils.h utils.h pidfile.h cfreader.h icmpcheck.h tcpcheck.h httpget.h smtpwrapper.h ipvswrapper.h keepalived.h
+OBJECTS= md5.o iputils.o utils.o pidfile.o cfreader.o icmpcheck.o tcpcheck.o httpget.o smtpwrapper.o ipvswrapper.o keepalived.o
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:  
+#      $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+       $(CC) -o $@ $(INCLUDE) -DDEBUG -c $*.c
+
+all:   $(EXEC)
+       strip $(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+$(EXEC):       $(OBJECTS) $(DEFS)
+       $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+
+clean:
+       rm -f core *.o $(EXEC) /etc/lvs.conf /etc/keepalived/keepalived.conf /usr/sbin/keepalived /usr/bin/genhash
+       rm -rf /etc/keepalived
+
+install:       
+       install -m 700 keepalived /usr/sbin/
+       install -m 755 etc/rc.d/init.d/keepalived.init /etc/rc.d/init.d/
+       mkdir /etc/keepalived
+       mkdir /etc/keepalived/log
+       touch /etc/keepalived/log/keepalived.log
+       install -m 644 etc/lvs.conf /etc/
+       install -m 644 etc/keepalived/keepalived.conf /etc/keepalived/
diff --git a/cfreader.c b/cfreader.c
new file mode 100644 (file)
index 0000000..a6066c6
--- /dev/null
@@ -0,0 +1,456 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        Configuration file parser/reader. Place into the dynamic
+ *              data structure representation the conf file representing
+ *              the loadbalanced server pool.
+ *  
+ * Version:     $Id: cfreader.c,v 0.2.6 2001/03/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Change the dynamic data structure. Move to a tree data
+ *                   structure.
+ *               <+> Revisited the pointer handling for the dynamic data
+ *                   structure.
+ *               <+> Adding keywords support for the configuration file.
+ *               <+> Adding support for email notification.
+ *
+ *              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 "cfreader.h"
+
+int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
+{
+  virtualserver *pointerptr=lstptr;
+
+  while(lstptr != NULL) {
+    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+      lstptr=pointerptr;
+      return 1;
+    }
+    lstptr=(virtualserver *)lstptr->next;
+  }
+  lstptr=pointerptr;
+  return 0;
+}
+
+int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
+{
+  realserver *pointerptr=lstptr;
+
+  while(lstptr != NULL) {
+    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+      lstptr=pointerptr;
+      return 1;
+    }
+    lstptr=(realserver *)lstptr->next;
+  }
+  lstptr=pointerptr;
+  return 0;
+}
+
+notification_email * AddItem_Email(notification_email *lstemail,notification_email *email)
+{
+  notification_email *pointerlst=lstemail;
+
+  if (lstemail != NULL) {
+    while(lstemail->next != NULL) lstemail=(notification_email *)lstemail->next;
+    lstemail->next=(struct notification_email *)email;
+    return pointerlst;
+  } else {
+    lstemail=email;
+    return lstemail;
+  }
+}
+
+virtualserver * AddItem_VS(virtualserver *lstvs,virtualserver *vs)
+{
+  virtualserver *pointerlst=lstvs;
+
+  if(AlreadyExist_VS(lstvs,vs->addr_ip,vs->addr_port)) return lstvs;
+
+  if (lstvs != NULL) {
+    while(lstvs->next != NULL) lstvs=(virtualserver *)lstvs->next;
+    lstvs->next=(struct virtualserver *)vs;
+    return pointerlst;
+  } else {
+    lstvs=vs;
+    return lstvs;
+  }
+}
+
+realserver * AddItem_SVR(realserver *lstsvr,realserver *svr)
+{
+  realserver *pointerlst=lstsvr;
+
+  if(AlreadyExist_SVR(lstsvr,svr->addr_ip,svr->addr_port)) return lstsvr;
+
+  if (lstsvr != NULL) {
+    while(lstsvr->next != NULL) lstsvr=(realserver *)lstsvr->next;
+    lstsvr->next=(struct realserver *)svr;
+    return pointerlst;
+  } else {
+    lstsvr=svr;
+    return lstsvr;
+  }
+}
+
+urls * AddItem_Url(urls *lsturls,urls *url)
+{
+  urls *pointerlst=lsturls;
+
+  if (lsturls != NULL) {
+    while(lsturls->next != NULL) lsturls=(urls *)lsturls->next;
+    lsturls->next=(struct urls *)url;
+    return pointerlst;
+  } else {
+    lsturls=url;
+    return lsturls;
+  }
+}
+
+urls * RemoveUrl(urls * lstptr)
+{
+  urls *t;
+
+  t=(urls *)lstptr->next;
+  free(lstptr);
+  return t;
+}
+
+realserver * RemoveSVR(realserver * lstptr)
+{
+  realserver *t;
+
+  t=(realserver *)lstptr->next;
+
+  if(lstptr->method->http_get != NULL) {
+    while(lstptr->method->http_get->check_urls != NULL)
+      lstptr->method->http_get->check_urls=RemoveUrl(lstptr->method->http_get->check_urls);
+    free(lstptr->method->http_get);
+  }
+
+  if(lstptr->method->tcp_vanilla != NULL)
+    free(lstptr->method->tcp_vanilla);
+
+  free(lstptr->method);
+  free(lstptr);
+  return t;
+}
+
+virtualserver * RemoveVS(virtualserver * lstptr)
+{
+  virtualserver *t;
+
+  t=(virtualserver *)lstptr->next;
+  while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
+  free(lstptr);
+  return t;
+}
+
+notification_email * RemoveEmail(notification_email *lstptr)
+{
+  notification_email *t;
+
+  t=(notification_email *)lstptr->next;
+  free(lstptr);
+  return t;
+}
+
+void ClearConf(configuration_data * lstptr)
+{
+  while(lstptr->email != NULL)
+    lstptr->email=RemoveEmail(lstptr->email);
+
+  while(lstptr->lvstopology != NULL)
+    lstptr->lvstopology=RemoveVS(lstptr->lvstopology);
+}
+
+void PrintConf(configuration_data *lstconf)
+{
+  notification_email *pointeremail;
+  virtualserver *pointervs;
+  realserver *pointersvr;
+  urls *pointerurls;
+  char *tempbuffer;
+
+  tempbuffer=(char *)malloc(TEMPBUFFERLENGTH);
+  memset(tempbuffer,0,TEMPBUFFERLENGTH);
+
+  if(lstconf == NULL) {
+    logmessage("Empty data configuration !!!\n");
+  } else {
+    logmessage("------< Global definitions >------\n");
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," LVS ID = %s\n",lstconf->lvs_id);
+    logmessage(tempbuffer);
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," Delay loop = %s, Smtp server = %s\n",
+                     lstconf->delay_loop,lstconf->smtp_server);
+    logmessage(tempbuffer);
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," Email notification from = %s\n",lstconf->email_from);
+    logmessage(tempbuffer);
+
+    pointeremail=lstconf->email;
+    while(lstconf->email != NULL) {
+      memset(tempbuffer,0,TEMPBUFFERLENGTH);
+      sprintf(tempbuffer," Email notification = %s\n",lstconf->email->addr);
+      logmessage(tempbuffer);
+
+      lstconf->email=(notification_email *)lstconf->email->next;
+    }
+    lstconf->email=pointeremail;
+
+    logmessage("------< LVS Topology >------\n");
+    pointervs=lstconf->lvstopology;
+    while(lstconf->lvstopology != NULL) {
+      memset(tempbuffer,0,TEMPBUFFERLENGTH);
+      sprintf(tempbuffer," VS IP = %s, PORT = %s\n",lstconf->lvstopology->addr_ip,
+                                                    lstconf->lvstopology->addr_port);
+      logmessage(tempbuffer);
+
+      sprintf(tempbuffer," -> lb_algo = %s, lb_kind = %s, persistence = %s, protocol = %s\n",
+                         lstconf->lvstopology->sched,lstconf->lvstopology->loadbalancing_kind,
+                         lstconf->lvstopology->timeout_persistence,lstconf->lvstopology->service_type);
+      logmessage(tempbuffer);
+
+      pointersvr=lstconf->lvstopology->svr;
+      while(lstconf->lvstopology->svr != NULL) {
+        sprintf(tempbuffer,"    -> SVR IP = %s, PORT = %s, WEIGHT = %s\n",
+                           lstconf->lvstopology->svr->addr_ip,lstconf->lvstopology->svr->addr_port,
+                           lstconf->lvstopology->svr->weight);
+        logmessage(tempbuffer);
+
+        /* Displaying ICMP_CHECK resume */
+        if (lstconf->lvstopology->svr->method->flag_type == ICMP_CHECK_ID)
+          logmessage("       -> Keepalive method = ICMP_CHECK\n");
+
+        /* Displaying TCP_CHECK resume */
+        if (lstconf->lvstopology->svr->method->flag_type == TCP_CHECK_ID) {
+          logmessage("       -> Keepalive method = TCP_CHECK\n");
+          sprintf(tempbuffer,"       -> Connection timeout = %s\n",
+                             lstconf->lvstopology->svr->method->tcp_vanilla->connection_to);
+          logmessage(tempbuffer);
+        }
+
+        /* Displaying HTTP_GET resume */
+        if (lstconf->lvstopology->svr->method->flag_type == HTTP_GET_ID) {
+          pointerurls=lstconf->lvstopology->svr->method->http_get->check_urls;
+          logmessage("       -> Keepalive method = HTTP_GET\n");
+          while (lstconf->lvstopology->svr->method->http_get->check_urls  != NULL) {
+            sprintf(tempbuffer,"       -> Url = %s, Digest = %s\n",
+                               lstconf->lvstopology->svr->method->http_get->check_urls->url,
+                               lstconf->lvstopology->svr->method->http_get->check_urls->digest);
+            logmessage(tempbuffer);
+            lstconf->lvstopology->svr->method->http_get->check_urls=(urls *)lstconf->lvstopology->svr->method->http_get->check_urls->next;
+          }
+          lstconf->lvstopology->svr->method->http_get->check_urls=pointerurls;
+
+          sprintf(tempbuffer,"       -> Connection timeout = %s, Nb get retry = %s\n",
+                             lstconf->lvstopology->svr->method->http_get->connection_to,
+                             lstconf->lvstopology->svr->method->http_get->nb_get_retry);
+          logmessage(tempbuffer);
+          sprintf(tempbuffer,"       -> Delay before retry = %s\n",
+                             lstconf->lvstopology->svr->method->http_get->delay_before_retry);
+          logmessage(tempbuffer);
+        }
+
+        lstconf->lvstopology->svr=(realserver *)lstconf->lvstopology->svr->next;
+      }
+      lstconf->lvstopology->svr=pointersvr;
+
+      lstconf->lvstopology=(virtualserver *)lstconf->lvstopology->next;
+    }
+    lstconf->lvstopology=pointervs;
+
+  }
+  free(tempbuffer);
+}
+
+configuration_data * ConfReader(configuration_data *conf_data)
+{
+  FILE *stream;
+  char *string="";
+  virtualserver *pointervs;
+  virtualserver *vsfill;
+  realserver *svrfill;
+  notification_email *emailfill;
+  keepalive_check *methodfill;
+  http_get_check *httpgetfill;
+  urls *urlsfill;
+  tcp_vanilla_check *tcpcheckfill;
+
+  stream=fopen(CONFFILE,"r");
+  if(stream==NULL) {
+    logmessage("ConfReader : Can not read the config file\n");
+    return(NULL);
+  }
+
+  string=(char *)malloc(TEMPBUFFERLENGTH);
+  memset(string,0,TEMPBUFFERLENGTH);
+  conf_data=(configuration_data *)malloc(sizeof(configuration_data));
+  memset(conf_data,0,sizeof(configuration_data));
+
+  /* Initialise the dynamic data structure */
+  conf_data->email=NULL;
+  conf_data->lvstopology=NULL;
+
+  while(!feof(stream)) {
+    fscanf(stream,"%s",string);
+
+    /* Fill in the global defs structure */
+    if(strcmp(string,GLOBALDEFS) == 0)
+      do {
+        if(strcmp(string,DELAY) == 0)
+          fscanf(stream,"%s",conf_data->delay_loop);
+        if(strcmp(string,SMTP) == 0)
+          fscanf(stream,"%s",conf_data->smtp_server);
+        if(strcmp(string,EMAILFROM) == 0)
+          fscanf(stream,"%s",conf_data->email_from);
+        if(strcmp(string,LVSID) == 0)
+          fscanf(stream,"%s",conf_data->lvs_id);
+        if(strcmp(string,EMAIL) == 0)
+          do {
+            fscanf(stream,"%s",string);
+            if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+              emailfill=(notification_email *)malloc(sizeof(notification_email));
+              memset(emailfill,0,sizeof(notification_email));
+              strncat(emailfill->addr,string,sizeof(emailfill->addr));
+              emailfill->next=NULL;
+              conf_data->email = AddItem_Email(conf_data->email,emailfill);
+            }
+          } while(strcmp(string,ENDFLAG) != 0);
+        fscanf(stream,"%s",string);
+      } while(strcmp(string,ENDFLAG) != 0);
+
+    /* Fill in virtual server structure */
+    if(strcmp(string,VS) == 0) {
+      vsfill=(virtualserver *)malloc(sizeof(virtualserver));
+      vsfill->next=NULL;
+      conf_data->lvstopology = AddItem_VS(conf_data->lvstopology,vsfill);
+
+      pointervs=conf_data->lvstopology;
+      while(conf_data->lvstopology->next != NULL)
+        conf_data->lvstopology=(virtualserver *)conf_data->lvstopology->next;
+
+      fscanf(stream,"%s",vsfill->addr_ip);
+      fscanf(stream,"%s",vsfill->addr_port);
+      do {
+        if(strcmp(string,LBSCHED) == 0)
+          fscanf(stream,"%s",vsfill->sched);
+        if(strcmp(string,LBKIND) == 0)
+          fscanf(stream,"%s",vsfill->loadbalancing_kind);
+        if(strcmp(string,PTIMEOUT) == 0)
+          fscanf(stream,"%s",vsfill->timeout_persistence);
+        if(strcmp(string,PROTOCOL) == 0)
+          fscanf(stream,"%s",vsfill->service_type);
+
+        /* Fill in real server structure */
+        if(strcmp(string,SVR) == 0) {
+          svrfill=(realserver *)malloc(sizeof(realserver));
+          memset(svrfill,0,sizeof(realserver));
+          fscanf(stream,"%s",svrfill->addr_ip);
+          fscanf(stream,"%s",svrfill->addr_port);
+          svrfill->alive=1;
+          do {
+            if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+              if(strcmp(string,WEIGHT) == 0)
+                fscanf(stream,"%s",svrfill->weight);
+
+              if(strcmp(string,ICMPCHECK) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=ICMP_CHECK_ID;
+                methodfill->http_get=NULL;
+                methodfill->tcp_vanilla=NULL;
+              }
+
+              if(strcmp(string,TCPCHECK) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=TCP_CHECK_ID;
+                tcpcheckfill=(tcp_vanilla_check *)malloc(sizeof(tcp_vanilla_check));
+                memset(tcpcheckfill,0,sizeof(tcp_vanilla_check));
+                do {
+                  fscanf(stream,"%s",string);
+                  if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+                    if(strcmp(string,CTIMEOUT) == 0)
+                      fscanf(stream,"%s",tcpcheckfill->connection_to);
+                  }
+                } while (strcmp(string,ENDFLAG) != 0);
+                methodfill->http_get=NULL;
+                methodfill->tcp_vanilla=tcpcheckfill;
+              }
+
+              if(strcmp(string,HTTPGET) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=HTTP_GET_ID;
+                httpgetfill=(http_get_check *)malloc(sizeof(http_get_check));
+                memset(httpgetfill,0,sizeof(http_get_check));
+                httpgetfill->check_urls=NULL;
+                do {
+                  if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+                    if(strcmp(string,CTIMEOUT) == 0)
+                      fscanf(stream,"%s",httpgetfill->connection_to);
+                    if(strcmp(string,NBGETRETRY) == 0)
+                      fscanf(stream,"%s",httpgetfill->nb_get_retry);
+                    if(strcmp(string,DELAYRETRY) == 0)
+                      fscanf(stream,"%s",httpgetfill->delay_before_retry);
+
+                    if(strcmp(string,URL) == 0) {
+                      urlsfill=(urls *)malloc(sizeof(urls));
+                      memset(urlsfill,0,sizeof(urls));
+                      urlsfill->next=NULL;
+                      do {
+                        fscanf(stream,"%s",string);
+                        if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+                          if(strcmp(string,URLPATH) == 0)
+                            fscanf(stream,"%s",urlsfill->url);
+                          if(strcmp(string,DIGEST) == 0)
+                            fscanf(stream,"%s",urlsfill->digest);
+                        
+                        }
+                      } while (strcmp(string,ENDFLAG) != 0);
+                      httpgetfill->check_urls=AddItem_Url(httpgetfill->check_urls,urlsfill);
+                    }
+
+                  }
+                  fscanf(stream,"%s",string);
+                } while (strcmp(string,ENDFLAG) != 0);
+                methodfill->http_get=httpgetfill;
+                methodfill->tcp_vanilla=NULL;
+              }
+            }
+            fscanf(stream,"%s",string);
+          } while(strcmp(string,ENDFLAG) != 0);
+          svrfill->method=methodfill;
+          svrfill->next=NULL;
+          conf_data->lvstopology->svr = AddItem_SVR(conf_data->lvstopology->svr,svrfill);
+        }
+
+        fscanf(stream,"%s",string);
+      } while(strcmp(string,ENDFLAG) != 0);
+      conf_data->lvstopology=pointervs;
+    }
+  }
+
+  free(string);
+  fclose(stream);
+
+  return(conf_data);
+}
diff --git a/cfreader.h b/cfreader.h
new file mode 100644 (file)
index 0000000..d1b0003
--- /dev/null
@@ -0,0 +1,134 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        cfreader.c include file.
+ *  
+ * Version:     $Id: cfreader.h,v 0.2.6 2001/03/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Adding keywords.
+ *               <+> Change change the whole data structure.
+ *               <+> Adding LVS ID & notification email for alertes.
+ *
+ *              Alexandre Cassen : Initial release : 2000/12/09
+ *              
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */
+
+#ifndef CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONFFILE "keepalived.conf"
+
+#define TEMPBUFFERLENGTH 100
+
+/* Keywords definition */
+#define GLOBALDEFS   "global_defs"
+#define VS           "virtual_server"
+#define SVR          "real_server"
+#define BEGINFLAG    "{"
+#define ENDFLAG      "}"
+#define DELAY        "delay_loop"
+#define EMAIL        "notification_email"
+#define EMAILFROM    "notification_email_from"
+#define LVSID        "lvs_id"
+#define SMTP         "smtp_server"
+#define LBSCHED      "lb_algo"
+#define LBKIND       "lb_kind"
+#define PTIMEOUT     "persistence_timeout"
+#define PROTOCOL     "protocol"
+#define WEIGHT       "weight"
+#define URL          "url"
+#define URLPATH      "path"
+#define DIGEST       "digest"
+#define CTIMEOUT     "connect_timeout"
+#define NBGETRETRY   "nb_get_retry"
+#define DELAYRETRY   "delay_before_retry"
+
+#define ICMPCHECK    "ICMP_CHECK"
+#define TCPCHECK     "TCP_CHECK"
+#define HTTPGET      "HTTP_GET"
+#define SSLGET       "SSL_GET"
+
+/* Check method id */
+#define ICMP_CHECK_ID  0x001
+#define TCP_CHECK_ID   0x002
+#define HTTP_GET_ID    0x003
+#define SSL_GET_ID     0x004
+
+/* Structure definition  */
+typedef struct _tcp_vanilla_check {
+  char connection_to[4+1];
+} tcp_vanilla_check;
+
+typedef struct _urls {
+  char url[100+1];
+  char digest[32+1];
+
+  struct urls *next;
+} urls;
+
+typedef struct _http_get_check {
+  char connection_to[4+1];
+  char nb_get_retry[1+1];
+  char delay_before_retry[4+1];
+  urls *check_urls;
+} http_get_check;
+
+typedef struct _keepalive_check {
+  int flag_type;
+  http_get_check *http_get;
+  tcp_vanilla_check *tcp_vanilla;
+} keepalive_check;
+
+typedef struct _real_server {
+  char addr_ip[15+1];
+  char addr_port[5+1];
+  char weight[3+1];
+  keepalive_check *method;
+  int alive;
+
+  struct realserver *next;
+} realserver;
+
+typedef struct _virtual_server {
+  char addr_ip[15+1];
+  char addr_port[5+1];
+  char sched[5+1];
+  char loadbalancing_kind[5+1];
+  char timeout_persistence[4];
+  char service_type[3+1];
+  realserver *svr;
+
+  struct virtualserver *next;
+} virtualserver;
+
+typedef struct _notification_email {
+  char addr[40+1];
+
+  struct notification_email *next;
+} notification_email;
+
+typedef struct _configuration_data {
+  char delay_loop[4+1];
+  char email_from[40+1];
+  char smtp_server[15+1];
+  char lvs_id[20+1];
+  notification_email *email;
+
+  virtualserver *lvstopology;
+} configuration_data;
+
+#endif
similarity index 53%
rename from keepalived/Makefile
rename to confread/Makefile
index 9ca1c82..81fe8bd 100644 (file)
@@ -1,12 +1,12 @@
 # Makefile
 # Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
 
-EXEC= keepalived
+EXEC= confreader
 CC= gcc
-#CFLAGS= -Wall -Wunused -lmd
-CFLAGS= -lmd
-DEFS= iputils.h utils.h cfreader.h icmpcheck.h tcpcheck.h httpget.h ipvswrapper.h keepalived.h
-OBJECTS= iputils.o utils.o cfreader.o icmpcheck.o tcpcheck.o httpget.o ipvswrapper.o keepalived.o
+#CFLAGS= -Wall -Wunused
+CFLAGS= 
+DEFS= main.h cfreader.h
+OBJECTS= main.o cfreader.o utils.o
 INCLUDE= -I/usr/src/linux/include
 
 .c.o:  
@@ -23,7 +23,3 @@ $(EXEC):      $(OBJECTS) $(DEFS)
 
 clean:
        rm -f core *.o $(EXEC) 
-
-install:
-       cp -av keepalived /usr/sbin/
-       cp -av etc/* /etc/
diff --git a/confread/cfreader.c b/confread/cfreader.c
new file mode 100644 (file)
index 0000000..c464188
--- /dev/null
@@ -0,0 +1,448 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        Configuration file parser/reader. Place into the dynamic
+ *              data structure representation the conf file representing
+ *              the loadbalanced server pool.
+ *  
+ * Version:     $Id: cfreader.c,v 0.2.1 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.
+ */
+
+#include "cfreader.h"
+
+int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
+{
+  virtualserver *pointerptr=lstptr;
+
+  while(lstptr != NULL) {
+    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+      lstptr=pointerptr;
+      return 1;
+    }
+    lstptr=(virtualserver *)lstptr->next;
+  }
+  lstptr=pointerptr;
+  return 0;
+}
+
+int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
+{
+  realserver *pointerptr=lstptr;
+
+  while(lstptr != NULL) {
+    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+      lstptr=pointerptr;
+      return 1;
+    }
+    lstptr=(realserver *)lstptr->next;
+  }
+  lstptr=pointerptr;
+  return 0;
+}
+
+notification_email * AddItem_Email(notification_email *lstemail,notification_email *email)
+{
+  notification_email *pointerlst=lstemail;
+
+  if (lstemail != NULL) {
+    while(lstemail->next != NULL) lstemail=(notification_email *)lstemail->next;
+    lstemail->next=(struct notification_email *)email;
+    return pointerlst;
+  } else {
+    lstemail=email;
+    return lstemail;
+  }
+}
+
+virtualserver * AddItem_VS(virtualserver *lstvs,virtualserver *vs)
+{
+  virtualserver *pointerlst=lstvs;
+
+  if(AlreadyExist_VS(lstvs,vs->addr_ip,vs->addr_port)) return lstvs;
+
+  if (lstvs != NULL) {
+    while(lstvs->next != NULL) lstvs=(virtualserver *)lstvs->next;
+    lstvs->next=(struct virtualserver *)vs;
+    return pointerlst;
+  } else {
+    lstvs=vs;
+    return lstvs;
+  }
+}
+
+realserver * AddItem_SVR(realserver *lstsvr,realserver *svr)
+{
+  realserver *pointerlst=lstsvr;
+
+  if(AlreadyExist_SVR(lstsvr,svr->addr_ip,svr->addr_port)) return lstsvr;
+
+  if (lstsvr != NULL) {
+    while(lstsvr->next != NULL) lstsvr=(realserver *)lstsvr->next;
+    lstsvr->next=(struct realserver *)svr;
+    return pointerlst;
+  } else {
+    lstsvr=svr;
+    return lstsvr;
+  }
+}
+
+urls * AddItem_Url(urls *lsturls,urls *url)
+{
+  urls *pointerlst=lsturls;
+
+  if (lsturls != NULL) {
+    while(lsturls->next != NULL) lsturls=(urls *)lsturls->next;
+    lsturls->next=(struct urls *)url;
+    return pointerlst;
+  } else {
+    lsturls=url;
+    return lsturls;
+  }
+}
+
+urls * RemoveUrl(urls * lstptr)
+{
+  urls *t;
+
+  t=(urls *)lstptr->next;
+  free(lstptr);
+  return t;
+}
+
+realserver * RemoveSVR(realserver * lstptr)
+{
+  realserver *t;
+
+  t=(realserver *)lstptr->next;
+
+  if(lstptr->method->http_get != NULL) {
+    while(lstptr->method->http_get->check_urls != NULL)
+      lstptr->method->http_get->check_urls=RemoveUrl(lstptr->method->http_get->check_urls);
+    free(lstptr->method->http_get);
+  }
+
+  if(lstptr->method->tcp_vanilla != NULL)
+    free(lstptr->method->tcp_vanilla);
+
+  free(lstptr->method);
+  free(lstptr);
+  return t;
+}
+
+virtualserver * RemoveVS(virtualserver * lstptr)
+{
+  virtualserver *t;
+
+  t=(virtualserver *)lstptr->next;
+  while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
+  free(lstptr);
+  return t;
+}
+
+notification_email * RemoveEmail(notification_email *lstptr)
+{
+  notification_email *t;
+
+  t=(notification_email *)lstptr->next;
+  free(lstptr);
+  return t;
+}
+
+void ClearConf(configuration_data * lstptr)
+{
+  while(lstptr->email != NULL)
+    lstptr->email=RemoveEmail(lstptr->email);
+
+  while(lstptr->lvstopology != NULL)
+    lstptr->lvstopology=RemoveVS(lstptr->lvstopology);
+}
+
+void PrintConf(configuration_data *lstconf)
+{
+  notification_email *pointeremail;
+  virtualserver *pointervs;
+  realserver *pointersvr;
+  urls *pointerurls;
+  char *tempbuffer;
+
+  tempbuffer=(char *)malloc(TEMPBUFFERLENGTH);
+  memset(tempbuffer,0,TEMPBUFFERLENGTH);
+
+  if(lstconf == NULL) {
+    logmessage("Empty data configuration !!!\n",getpid());
+  } else {
+    logmessage("------< Global definitions >------\n",getpid());
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," LVS ID = %s\n",lstconf->lvs_id);
+    logmessage(tempbuffer,getpid());
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," Delay loop = %s, Smtp server = %s\n",
+                     lstconf->delay_loop,lstconf->smtp_server);
+    logmessage(tempbuffer,getpid());
+    memset(tempbuffer,0,TEMPBUFFERLENGTH);
+    sprintf(tempbuffer," Email notification from = %s\n",lstconf->email_from);
+    logmessage(tempbuffer,getpid());
+
+    pointeremail=lstconf->email;
+    while(lstconf->email != NULL) {
+      memset(tempbuffer,0,TEMPBUFFERLENGTH);
+      sprintf(tempbuffer," Email notification = %s\n",lstconf->email->addr);
+      logmessage(tempbuffer,getpid());
+
+      lstconf->email=(notification_email *)lstconf->email->next;
+    }
+    lstconf->email=pointeremail;
+
+    logmessage("------< LVS Topology >------\n",getpid());
+    pointervs=lstconf->lvstopology;
+    while(lstconf->lvstopology != NULL) {
+      memset(tempbuffer,0,TEMPBUFFERLENGTH);
+      sprintf(tempbuffer," VS IP = %s, PORT = %s\n",lstconf->lvstopology->addr_ip,
+                                                    lstconf->lvstopology->addr_port);
+      logmessage(tempbuffer,getpid());
+
+      sprintf(tempbuffer," -> lb_algo = %s, lb_kind = %s, persistence = %s, protocol = %s\n",
+                         lstconf->lvstopology->sched,lstconf->lvstopology->loadbalancing_kind,
+                         lstconf->lvstopology->timeout_persistence,lstconf->lvstopology->service_type);
+      logmessage(tempbuffer,getpid());
+
+      pointersvr=lstconf->lvstopology->svr;
+      while(lstconf->lvstopology->svr != NULL) {
+        sprintf(tempbuffer,"    -> SVR IP = %s, PORT = %s, WEIGHT = %s\n",
+                           lstconf->lvstopology->svr->addr_ip,lstconf->lvstopology->svr->addr_port,
+                           lstconf->lvstopology->svr->weight);
+        logmessage(tempbuffer,getpid());
+
+        /* Displaying ICMP_CHECK resume */
+        if (lstconf->lvstopology->svr->method->flag_type == ICMP_CHECK_ID)
+          logmessage("       -> Keepalive method = ICMP_CHECK\n",getpid());
+
+        /* Displaying TCP_CHECK resume */
+        if (lstconf->lvstopology->svr->method->flag_type == TCP_CHECK_ID) {
+          logmessage("       -> Keepalive method = TCP_CHECK\n",getpid());
+          sprintf(tempbuffer,"       -> Connection timeout = %s\n",
+                             lstconf->lvstopology->svr->method->tcp_vanilla->connection_to);
+          logmessage(tempbuffer,getpid());
+        }
+
+        /* Displaying HTTP_GET resume */
+        if (lstconf->lvstopology->svr->method->flag_type == HTTP_GET_ID) {
+          pointerurls=lstconf->lvstopology->svr->method->http_get->check_urls;
+          logmessage("       -> Keepalive method = HTTP_GET\n",getpid());
+          while (lstconf->lvstopology->svr->method->http_get->check_urls  != NULL) {
+            sprintf(tempbuffer,"       -> Url = %s, Digest = %s\n",
+                               lstconf->lvstopology->svr->method->http_get->check_urls->url,
+                               lstconf->lvstopology->svr->method->http_get->check_urls->digest);
+            logmessage(tempbuffer,getpid());
+            lstconf->lvstopology->svr->method->http_get->check_urls=(urls *)lstconf->lvstopology->svr->method->http_get->check_urls->next;
+          }
+          lstconf->lvstopology->svr->method->http_get->check_urls=pointerurls;
+
+          sprintf(tempbuffer,"       -> Connection timeout = %s, Nb get retry = %s\n",
+                             lstconf->lvstopology->svr->method->http_get->connection_to,
+                             lstconf->lvstopology->svr->method->http_get->nb_get_retry);
+          logmessage(tempbuffer,getpid());
+          sprintf(tempbuffer,"       -> Delay before retry = %s\n",
+                             lstconf->lvstopology->svr->method->http_get->delay_before_retry);
+          logmessage(tempbuffer,getpid());
+        }
+
+        lstconf->lvstopology->svr=(realserver *)lstconf->lvstopology->svr->next;
+      }
+      lstconf->lvstopology->svr=pointersvr;
+
+      lstconf->lvstopology=(virtualserver *)lstconf->lvstopology->next;
+    }
+    lstconf->lvstopology=pointervs;
+
+  }
+  free(tempbuffer);
+}
+
+configuration_data * ConfReader(configuration_data *conf_data)
+{
+  FILE *stream;
+  char *string="";
+  virtualserver *pointervs;
+  virtualserver *vsfill;
+  realserver *svrfill;
+  notification_email *emailfill;
+  keepalive_check *methodfill;
+  http_get_check *httpgetfill;
+  urls *urlsfill;
+  tcp_vanilla_check *tcpcheckfill;
+
+  stream=fopen(CONFFILE,"r");
+  if(stream==NULL) {
+    logmessage("ConfReader : Can not read the config file\n",getpid());
+    return(NULL);
+  }
+
+  string=(char *)malloc(TEMPBUFFERLENGTH);
+  memset(string,0,TEMPBUFFERLENGTH);
+  conf_data=(configuration_data *)malloc(sizeof(configuration_data));
+  memset(conf_data,0,sizeof(configuration_data));
+
+  /* Initialise the dynamic data structure */
+  conf_data->email=NULL;
+  conf_data->lvstopology=NULL;
+
+  while(!feof(stream)) {
+    fscanf(stream,"%s",string);
+
+    /* Fill in the global defs structure */
+    if(strcmp(string,GLOBALDEFS) == 0)
+      do {
+        if(strcmp(string,DELAY) == 0)
+          fscanf(stream,"%s",conf_data->delay_loop);
+        if(strcmp(string,SMTP) == 0)
+          fscanf(stream,"%s",conf_data->smtp_server);
+        if(strcmp(string,EMAILFROM) == 0)
+          fscanf(stream,"%s",conf_data->email_from);
+        if(strcmp(string,LVSID) == 0)
+          fscanf(stream,"%s",conf_data->lvs_id);
+        if(strcmp(string,EMAIL) == 0)
+          do {
+            fscanf(stream,"%s",string);
+            if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+              emailfill=(notification_email *)malloc(sizeof(notification_email));
+              memset(emailfill,0,sizeof(notification_email));
+              strncat(emailfill->addr,string,sizeof(emailfill->addr));
+              emailfill->next=NULL;
+              conf_data->email = AddItem_Email(conf_data->email,emailfill);
+            }
+          } while(strcmp(string,ENDFLAG) != 0);
+        fscanf(stream,"%s",string);
+      } while(strcmp(string,ENDFLAG) != 0);
+
+    /* Fill in virtual server structure */
+    if(strcmp(string,VS) == 0) {
+      vsfill=(virtualserver *)malloc(sizeof(virtualserver));
+      vsfill->next=NULL;
+      conf_data->lvstopology = AddItem_VS(conf_data->lvstopology,vsfill);
+
+      pointervs=conf_data->lvstopology;
+      while(conf_data->lvstopology->next != NULL)
+        conf_data->lvstopology=(virtualserver *)conf_data->lvstopology->next;
+
+      fscanf(stream,"%s",vsfill->addr_ip);
+      fscanf(stream,"%s",vsfill->addr_port);
+      do {
+        if(strcmp(string,LBSCHED) == 0)
+          fscanf(stream,"%s",vsfill->sched);
+        if(strcmp(string,LBKIND) == 0)
+          fscanf(stream,"%s",vsfill->loadbalancing_kind);
+        if(strcmp(string,PTIMEOUT) == 0)
+          fscanf(stream,"%s",vsfill->timeout_persistence);
+        if(strcmp(string,PROTOCOL) == 0)
+          fscanf(stream,"%s",vsfill->service_type);
+
+        /* Fill in real server structure */
+        if(strcmp(string,SVR) == 0) {
+          svrfill=(realserver *)malloc(sizeof(realserver));
+          memset(svrfill,0,sizeof(realserver));
+          fscanf(stream,"%s",svrfill->addr_ip);
+          fscanf(stream,"%s",svrfill->addr_port);
+          svrfill->alive=1;
+          do {
+            if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+              if(strcmp(string,WEIGHT) == 0)
+                fscanf(stream,"%s",svrfill->weight);
+
+              if(strcmp(string,ICMPCHECK) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=ICMP_CHECK_ID;
+                methodfill->http_get=NULL;
+                methodfill->tcp_vanilla=NULL;
+              }
+
+              if(strcmp(string,TCPCHECK) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=TCP_CHECK_ID;
+                tcpcheckfill=(tcp_vanilla_check *)malloc(sizeof(tcp_vanilla_check));
+                memset(tcpcheckfill,0,sizeof(tcp_vanilla_check));
+                do {
+                  fscanf(stream,"%s",string);
+                  if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+                    if(strcmp(string,CTIMEOUT) == 0)
+                      fscanf(stream,"%s",tcpcheckfill->connection_to);
+                  }
+                } while (strcmp(string,ENDFLAG) != 0);
+                methodfill->http_get=NULL;
+                methodfill->tcp_vanilla=tcpcheckfill;
+              }
+
+              if(strcmp(string,HTTPGET) == 0) {
+                methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+                memset(methodfill,0,sizeof(keepalive_check));
+                methodfill->flag_type=HTTP_GET_ID;
+                httpgetfill=(http_get_check *)malloc(sizeof(http_get_check));
+                memset(httpgetfill,0,sizeof(http_get_check));
+                httpgetfill->check_urls=NULL;
+                do {
+                  if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+                    if(strcmp(string,CTIMEOUT) == 0)
+                      fscanf(stream,"%s",httpgetfill->connection_to);
+                    if(strcmp(string,NBGETRETRY) == 0)
+                      fscanf(stream,"%s",httpgetfill->nb_get_retry);
+                    if(strcmp(string,DELAYRETRY) == 0)
+                      fscanf(stream,"%s",httpgetfill->delay_before_retry);
+
+                    if(strcmp(string,URL) == 0) {
+                      urlsfill=(urls *)malloc(sizeof(urls));
+                      memset(urlsfill,0,sizeof(urls));
+                      urlsfill->next=NULL;
+                      do {
+                        fscanf(stream,"%s",string);
+                        if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+                          if(strcmp(string,URLPATH) == 0)
+                            fscanf(stream,"%s",urlsfill->url);
+                          if(strcmp(string,DIGEST) == 0)
+                            fscanf(stream,"%s",urlsfill->digest);
+                        
+                        }
+                      } while (strcmp(string,ENDFLAG) != 0);
+                      httpgetfill->check_urls=AddItem_Url(httpgetfill->check_urls,urlsfill);
+                    }
+
+                  }
+                  fscanf(stream,"%s",string);
+                } while (strcmp(string,ENDFLAG) != 0);
+                methodfill->http_get=httpgetfill;
+                methodfill->tcp_vanilla=NULL;
+              }
+            }
+            fscanf(stream,"%s",string);
+          } while(strcmp(string,ENDFLAG) != 0);
+          svrfill->method=methodfill;
+          svrfill->next=NULL;
+          conf_data->lvstopology->svr = AddItem_SVR(conf_data->lvstopology->svr,svrfill);
+        }
+
+        fscanf(stream,"%s",string);
+      } while(strcmp(string,ENDFLAG) != 0);
+      conf_data->lvstopology=pointervs;
+    }
+  }
+
+  free(string);
+  fclose(stream);
+
+  return(conf_data);
+}
diff --git a/confread/cfreader.h b/confread/cfreader.h
new file mode 100644 (file)
index 0000000..220c559
--- /dev/null
@@ -0,0 +1,134 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        cfreader.c include file.
+ *  
+ * Version:     $Id: cfreader.h,v 0.2.1 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 CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONFFILE "keepalived.conf"
+
+#define TEMPBUFFERLENGTH 100
+
+/* Keywords definition */
+#define GLOBALDEFS   "global_defs"
+#define VS           "virtual_server"
+#define SVR          "real_server"
+#define BEGINFLAG    "{"
+#define ENDFLAG      "}"
+#define DELAY        "delay_loop"
+#define EMAIL        "notification_email"
+#define EMAILFROM    "notification_email_from"
+#define LVSID        "lvs_id"
+#define SMTP         "smtp_server"
+#define LBSCHED      "lb_algo"
+#define LBKIND       "lb_kind"
+#define PTIMEOUT     "persistence_timeout"
+#define PROTOCOL     "protocol"
+#define WEIGHT       "weight"
+#define URL          "url"
+#define URLPATH      "path"
+#define DIGEST       "digest"
+#define CTIMEOUT     "connect_timeout"
+#define NBGETRETRY   "nb_get_retry"
+#define DELAYRETRY   "delay_before_retry"
+
+#define ICMPCHECK    "ICMP_CHECK"
+#define TCPCHECK     "TCP_CHECK"
+#define HTTPGET      "HTTP_GET"
+#define SSLGET       "SSL_GET"
+
+/* Check method id */
+#define ICMP_CHECK_ID  0x001
+#define TCP_CHECK_ID   0x002
+#define HTTP_GET_ID    0x003
+#define SSL_GET_ID     0x004
+
+/* Structure definition  */
+typedef struct _tcp_vanilla_check {
+  char connection_to[4+1];
+} tcp_vanilla_check;
+
+typedef struct _urls {
+  char url[100+1];
+  char digest[32+1];
+
+  struct urls *next;
+} urls;
+
+typedef struct _http_get_check {
+  char connection_to[4+1];
+  char nb_get_retry[1+1];
+  char delay_before_retry[4+1];
+  urls *check_urls;
+} http_get_check;
+
+typedef struct _keepalive_check {
+  int flag_type;
+  http_get_check *http_get;
+  tcp_vanilla_check *tcp_vanilla;
+} keepalive_check;
+
+typedef struct _real_server {
+  char addr_ip[15+1];
+  char addr_port[5+1];
+  char weight[3+1];
+  keepalive_check *method;
+  int alive;
+
+  struct realserver *next;
+} realserver;
+
+typedef struct _virtual_server {
+  char addr_ip[15+1];
+  char addr_port[5+1];
+  char sched[5+1];
+  char loadbalancing_kind[5+1];
+  char timeout_persistence[4];
+  char service_type[3+1];
+  realserver *svr;
+
+  struct virtualserver *next;
+} virtualserver;
+
+typedef struct _notification_email {
+  char addr[40+1];
+
+  struct notification_email *next;
+} notification_email;
+
+typedef struct _configuration_data {
+  char delay_loop[4+1];
+  char email_from[40+1];
+  char smtp_server[15+1];
+  char lvs_id[20+1];
+  notification_email *email;
+
+  virtualserver *lvstopology;
+} configuration_data;
+
+/* prototypes */
+//configuration_data * ConfReader(configuration_data *conf_data);
+//void ClearConf(configuration_data * lstptr);
+//void PrintConf(configuration_data * lstptr);
+
+#endif
diff --git a/confread/keepalived.conf b/confread/keepalived.conf
new file mode 100644 (file)
index 0000000..c69c9f7
--- /dev/null
@@ -0,0 +1,74 @@
+# Configuration File for keepalived
+
+
+global_defs {
+   delay_loop 60
+   notification_email {
+     acassen@domain.com
+     0633225522@domain.com
+   }
+   notification_email_from keepalived@domain.com
+   smtp_server 192.168.3.62
+   lvs_id LVS_MAIN
+}
+
+virtual_server 10.10.10.2 1358 {
+    lb_algo rr 
+    lb_kind NAT
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.200.2 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest ec90a42b99ea9a2f5ecbe213ac9eba03
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 2
+        }
+    }
+    real_server 192.168.200.3 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 2
+        }
+    }
+}
+
+virtual_server 10.10.10.2 8080 {
+    lb_algo rr
+    lb_kind NAT
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.200.4 8080 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+    real_server 192.168.200.5 8080 {
+        weight 1
+        ICMP_CHECK
+    }
+    real_server 192.168.200.6 8080 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+}
+
diff --git a/confread/main.c b/confread/main.c
new file mode 100644 (file)
index 0000000..15f5368
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project 
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        Main program structure.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.3 2001/01/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:       
+ *         Alexandre Cassen : 2001/01/01 :
+ *          <+> Change the signalhandling.
+ *
+ *          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 "main.h"
+
+int main(int argc, char **argv)
+{
+  int delay_loop=60;
+  printf(PROG" v"VERSION"\n");
+
+  if (chdir(CONF_HOME_DIR)) {
+    fprintf(stderr,"%s: ",CONF_HOME_DIR);
+    perror(NULL);
+    exit(1);
+  }
+
+  if ((confDATA=(configuration_data *)ConfReader(confDATA)) == NULL) {
+    exit(0);
+  }
+
+  PrintConf(confDATA);
+  ClearConf(confDATA);
+
+  return 0;
+}
diff --git a/confread/main.h b/confread/main.h
new file mode 100644 (file)
index 0000000..36e0644
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+ * 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:        keepalived.c include file.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.1 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 KEEPALIVED_H
+#define KEEPALIVED_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "cfreader.h"
+
+#define LOGBUFFER_LENGTH 100
+
+/* Configuration file home directory */
+#define CONF_HOME_DIR "./"
+
+/* Global variables */
+configuration_data *confDATA;
+
+/* Build version */
+#define PROG    "confreader"
+#define VERSION "0.2.6 (02/20, 2001), Alexandre Cassen"
+
+#endif
diff --git a/confread/utils.c b/confread/utils.c
new file mode 100644 (file)
index 0000000..ec11393
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        General program utils.
+ *
+ * Version:     $Id: utils.c,v 0.2.1 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.
+ */
+
+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;
+      }
+    }
+  }
+}
+
+void logmessage(char *msg,int idevent)
+{
+  printf("%s",msg);
+}
diff --git a/etc/keepalived/keepalived.conf b/etc/keepalived/keepalived.conf
new file mode 100644 (file)
index 0000000..c69c9f7
--- /dev/null
@@ -0,0 +1,74 @@
+# Configuration File for keepalived
+
+
+global_defs {
+   delay_loop 60
+   notification_email {
+     acassen@domain.com
+     0633225522@domain.com
+   }
+   notification_email_from keepalived@domain.com
+   smtp_server 192.168.3.62
+   lvs_id LVS_MAIN
+}
+
+virtual_server 10.10.10.2 1358 {
+    lb_algo rr 
+    lb_kind NAT
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.200.2 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest ec90a42b99ea9a2f5ecbe213ac9eba03
+            }
+            url { 
+              path /testurl2/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 2
+        }
+    }
+    real_server 192.168.200.3 1358 {
+        weight 1
+        HTTP_GET {
+            url { 
+              path /testurl/test.jsp
+              digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            nb_get_retry 3
+            delay_before_retry 2
+        }
+    }
+}
+
+virtual_server 10.10.10.2 8080 {
+    lb_algo rr
+    lb_kind NAT
+    persistence_timeout 50
+    protocol TCP
+
+    real_server 192.168.200.4 8080 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+    real_server 192.168.200.5 8080 {
+        weight 1
+        ICMP_CHECK
+    }
+    real_server 192.168.200.6 8080 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+}
+
diff --git a/etc/lvs.conf b/etc/lvs.conf
new file mode 100644 (file)
index 0000000..59a34c3
--- /dev/null
@@ -0,0 +1,5 @@
+ipchains -A forward -j MASQ -p tcp -s 192.168.200.0/24 1358 -d 0.0.0.0/0
+ipchains -A forward -j MASQ -p tcp -s 192.168.200.0/24 8080 -d 0.0.0.0/0
+
+ipvsadm -A -t 10.10.10.2:1358 -s rr -p 50
+ipvsadm -A -t 10.10.10.2:8080 -s rr -p 50
diff --git a/etc/rc.d/init.d/keepalived.init b/etc/rc.d/init.d/keepalived.init
new file mode 100755 (executable)
index 0000000..e8181ab
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Startup script for the Keepalived daemon
+#
+# processname: keepalived
+# pidfile: /var/run/keepalived.pid
+# config: /etc/lvs.conf
+# config: /etc/keepalived/keepalived.conf
+
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# See how we were called.
+case "$1" in
+  start)
+       echo -n "Starting Keepalived for LVS: "
+        sh /etc/lvs.conf
+       daemon keepalived
+       echo
+       ;;
+  stop)
+       echo -n "Shutting down Keepalived for LVS: "
+       killproc keepalived
+       echo
+       ;;
+  *)
+       echo "Usage: $0 {start|stop}"
+       exit 1
+esac
+
+exit 0
index a560f0d..ec82653 100644 (file)
@@ -3,9 +3,9 @@
 
 EXEC= genhash
 CC= gcc
-CFLAGS= -Wall -lmd
-DEFS= genhash.h
-OBJECTS= genhash.o
+CFLAGS= -Wall
+DEFS= genhash.h md5.h
+OBJECTS= md5.o genhash.o
 .c.o:  
        $(CC) -o $@ $(CFLAGS) -c $*.c
 
@@ -18,7 +18,7 @@ $(EXEC):      $(OBJECTS) $(DEFS)
        $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
 
 clean:
-       rm -f core *.o $(EXEC) 
+       rm -f core *.o $(EXEC)
 
-install:
-       cp -av genhash /usr/bin
+install:       
+       install -m 755 genhash /usr/bin/
index c1b6a9e..8964dcc 100644 (file)
@@ -4,12 +4,12 @@
  *              into the /etc/keepalived/keepalived.conf for the 
  *              HTTP_GET_CHECK.
  *  
- * Version:     $Id: keepalived.c,v 0.2.0 2000/12/09 $
+ * Version:     $Id: keepalived.c,v 0.3.0 2001/02/10 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *
  * Changes:
- *              Alexandre Cassen      :       Initial release
+ *              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
@@ -57,6 +57,17 @@ void print_buffer(int count, char *buff)
   }
 }
 
+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;
@@ -78,24 +89,36 @@ 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);
-  strcpy(str_request,"GET ");
-  strcat(str_request,URL);
-  strcat(str_request,"\n");
+  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");
+    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");
+    printf("-[ Can not resolve remote host ]-\n");
+    free(str_request);
+    free(buffertmp);
+    close(sdesc);
     return(ERROR_SOCKET);
   }
 
@@ -104,58 +127,164 @@ int HTTP_GET(char *IP_DST, unsigned short int PORT_DST, char *URL, char *buffer)
   bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
   adr_serv.sin_port=htons(PORT_DST);
 
-  if ( connect(sdesc, (struct sockaddr *)&adr_serv, long_inet) == -1) {
-    printf("Can not connect remote host\n");
+  /* 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");
+    printf("-[ Can not send data to remote host ]-\n");
+    free(str_request);
+    free(buffertmp);
+    close(sdesc);
     return(ERROR_SOCKET);
   }
 
-  rcv_buffer_size=recv(sdesc,buffer,RCV_BUFFER_LENGTH,0);
-  if ( rcv_buffer_size == -1 ) {
-    printf("Can not recieve data from remote host\n");
+  /* 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);
-  return(rcv_buffer_size);
+  free(buffertmp);
+  return(total_length);
 }
 
+
 int main(int argc, char **argv)
 {
   char *buffer_http;
-  int retcode=0;
-  char MDResult[0x40];
+  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;
+      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 *));
 
-  retcode=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
+  buffer_http_size=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
+  buffer_html=extract_html(buffer_http,buffer_http_size);
 
-  if(retcode > 0) {
-    printf("\n----[ Buffer Text representation ]----\n");
+  if(buffer_http_size > 0) {
+    printf("---------------------------[ Received Buffer ]----------------------------\n");
     printf("%s\n",buffer_http);
 
-    printf("\n----[ Buffer Hexa representation ]----\n");
-    printf("Buffer length : %d\n",retcode);
-    if(retcode!=0) print_buffer(retcode,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("\n----[ MD5 resulting ]----\n");
-    MD5Data(buffer_http,retcode,MDResult);
-    printf("MD5 256 bits Digest : %s\n",MDResult);
+    printf("MD5 Digest : %s\n",MDResult);
   } else {
     printf("No buffer returned...\n");
   }
 
+  free(MDResult);
   free(buffer_http);
-  return 1;
+  return(1);
 }
index 666abea..3c1bd29 100644 (file)
 #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 <md5.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   80
+#define GET_BUFFER_LENGTH   180
 #define RCV_BUFFER_LENGTH   1024
 
 /* Build version */
diff --git a/genhash/md5.c b/genhash/md5.c
new file mode 100644 (file)
index 0000000..9a3b957
--- /dev/null
@@ -0,0 +1,327 @@
+/*\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
new file mode 100644 (file)
index 0000000..72ddcb8
--- /dev/null
@@ -0,0 +1,94 @@
+/*\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/httpget.c b/httpget.c
new file mode 100644 (file)
index 0000000..aee4df0
--- /dev/null
+++ b/httpget.c
@@ -0,0 +1,325 @@
+/* 
+ * 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:        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.
+ *  
+ * Version:     $Id: httpget.c,v 0.2.6 2001/03/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Use a non blocking timeouted tcp connection.
+ *               <+> Adding support for multi-url. Can perform a HTTP GET
+ *                   over multiple url on the same tcp service (usefull for
+ *                   HTTP server owning multiple applications servers).
+ *               <+> Adding HTTP GET retry.
+ *               <+> Remove the libmd call, use the L. Peter Deutsch
+ *                   independant md5 implementation.
+ *               <+> Parse the whole HTTP get reply, computing a md5sum
+ *                   over the html response part.
+ *               <+> Adding delay support between HTTP get retry.
+ *
+ *              Alexandre Cassen : Initial release : 2000/12/09
+ *              
+ *              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 "httpget.h"
+
+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 GET(char *IP_DST, char *PORT_DST, char *URL, char *buffer,int ctimeout)
+{
+  register int sdesc;
+  int long_inet;
+  int rcv_buffer_size=0;
+  long total_length=0;
+  char *str_request;
+  struct hostent *ip_serv;
+  struct sockaddr_in adr_serv;
+  struct linger li = { 0 };
+  char *debugmsg;
+  char *buffertmp;
+  struct timeval tv;
+  fd_set rfds, wfds;
+  int rc, flags;
+  int arglen;
+
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  buffertmp=(char *)malloc(GET_BUFFER_LENGTH);
+  str_request=(char *)malloc(GET_REQUEST_BUFFER_LENGTH);
+  memset(buffertmp,0,GET_BUFFER_LENGTH);
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+  memset(str_request,0,GET_REQUEST_BUFFER_LENGTH);
+
+  sprintf(str_request,GETCMD,URL);
+
+  if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    return(SOCKET_ERROR);
+  }
+
+  /* free the tcp port after closing the socket descriptor */
+  li.l_onoff=1;
+  li.l_linger=0;
+  setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+  long_inet = sizeof(struct sockaddr_in);
+
+  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Can not resolve remote host %s\n",IP_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  memset(&adr_serv,0,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(atoi(PORT_DST));
+
+  /* Set read/write socket timeout */
+  flags=fcntl(sdesc, F_GETFL);
+  fcntl(sdesc, F_SETFL, flags | 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:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"HTTP_GET : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ECONNREFUSED:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"HTTP_GET : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ENETUNREACH:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"HTTP_GET : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case EINPROGRESS: // NONBLOCK socket connection in progress
+        goto next;
+      default:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"HTTP_GET : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+    }
+
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+next:
+  /* Timeout settings */
+  tv.tv_sec=ctimeout;
+  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)) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Timeout writing data to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  if (rc < 0) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  rc = 0;
+  arglen=sizeof(int);
+  if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+    rc = errno;
+
+  if (rc) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending the http get request */
+  if (send(sdesc,str_request,strlen(str_request),0) == -1) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Can not send data to remote host %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(debugmsg);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Proceed the HTTP server reply */
+  select(sdesc+1,&rfds,NULL,NULL,&tv);
+  if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"HTTP_GET : Timeout reading data from %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(str_request);
+    free(buffertmp);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  while((rcv_buffer_size = read(sdesc,buffertmp,GET_BUFFER_LENGTH)) != 0) {
+    if ( rcv_buffer_size == -1 ) {
+      if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"HTTP_GET : Can not recieve data from remote host %s:%s\n",IP_DST,PORT_DST);
+      logmessage(debugmsg);
+#endif
+      free(str_request);
+      free(debugmsg);
+      free(buffertmp);
+      close(sdesc);
+      return(SOCKET_ERROR);
+    }
+    memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+    memset(buffertmp,0,GET_BUFFER_LENGTH);
+    total_length += rcv_buffer_size;
+  }
+
+end:
+  close(sdesc);
+  free(str_request);
+  free(debugmsg);
+  free(buffertmp);
+  return(total_length);
+}
+
+int HTTP_GET(char *IP_DST,char *PORT_DST,char *URL,char *MDResult,int ctimeout,int getretry,int rdelay)
+{
+  char *buffer_http;
+  char *buffer_html;
+  char *debugmsg;
+  md5_state_t state;
+  md5_byte_t digest[16];
+  int buffer_http_size=0;
+  int split_offset=0;
+  int nb_retry=0;
+  int di;
+
+
+  buffer_http=(char *)malloc(GET_BUFFER_LENGTH);
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+
+  while (nb_retry < getretry) {
+    sleep(rdelay);
+    memset(buffer_http,0,GET_BUFFER_LENGTH);
+
+    buffer_http_size=GET(IP_DST,PORT_DST,URL,buffer_http,ctimeout);
+    buffer_html=extract_html(buffer_http,buffer_http_size);
+
+    if (buffer_http_size > 0) {
+      if ((buffer_http_size-(buffer_html-buffer_http)) == 0) {
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"HTTP_GET : No html buffer received from %s:%s. Retry\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        nb_retry++;
+      } else {
+        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]);
+        free(debugmsg);
+        free(buffer_http);
+        return(1);
+      }
+    } else {
+      free(debugmsg);
+      free(buffer_http);
+      return(0);
+    }
+  }
+
+#ifdef DEBUG
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+  sprintf(debugmsg,"HTTP_GET : No html buffer received from %s:%s after %d retry\n",IP_DST,PORT_DST,getretry);
+  logmessage(debugmsg);
+#endif
+
+  free(debugmsg);
+  free(buffer_http);
+  return(0);
+}
similarity index 82%
rename from keepalived/httpget.h
rename to httpget.h
index 8105f05..11ae866 100644 (file)
+++ b/httpget.h
@@ -5,12 +5,15 @@
  * 
  * Part:        httpget.c include file.
  *  
- * Version:     $Id: httpget.h,v 0.2.1 2000/12/09 $
+ * Version:     $Id: httpget.h,v 0.2.6 2001/03/01 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:     
- *              Alexandre Cassen      :       Initial release
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Change the GET method.
+ *
+ *              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
 #include <string.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
-#include <md5.h>
+#include <errno.h>
+#include "md5.h"
 
 #define SOCKET_ERROR   0
 #define SOCKET_SUCCESS 1
 
+#define GETCMD "GET %s HTTP/1.0\r\n\r\n"
+
 #define MD5_BUFFER_LENGTH 32
 #define GET_REQUEST_BUFFER_LENGTH 128
 #define GET_BUFFER_LENGTH 2048
 #define LOGBUFFER_LENGTH 100
 
-/* prototypes */
-int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x40]);
-
 #endif
similarity index 95%
rename from keepalived/icmpcheck.c
rename to icmpcheck.c
index 66ab6d2..ddd3f90 100644 (file)
@@ -14,8 +14,8 @@
  *         Alexandre Cassen : 2001/01/01 :
  *          <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
  *              Call this function in ICMP_RCV_ECHOREPLY with 1s timeout.
- *          <+> Added a timer (2s timeouted) in ICMP_RCV_ECHOREPLY to check
- *              ECHO_REPLY. Check perform on icmp type flag, remote ip address.
+ *          <+> Added a timer (2s timeouted) in ICMP_RCV_ECHOREPLY to check.
+ *              Check perform on icmp type flag, remote ip address.
  *          <+> Added a 3 time ECHO_REQUEST send retry.
  *
  *         Alexandre Cassen : 2000/12/09 : Initial release
@@ -179,7 +179,7 @@ int ICMP_RCV_ECHOREPLY(char *IP_DST)
     if (result<0) { 
       memset(debugmsg,0,LOGBUFFER_LENGTH);
       sprintf(debugmsg,"ICMP_CHECK : icmp timeout to [%s]...\n",IP_DST);
-      logmessage(debugmsg,getpid());
+      logmessage(debugmsg);
     }
 #endif
 
@@ -190,7 +190,7 @@ int ICMP_RCV_ECHOREPLY(char *IP_DST)
 #ifdef DEBUG
       memset(debugmsg,0,LOGBUFFER_LENGTH);
       sprintf(debugmsg,"ICMP_CHECK : Received packet too short according to ICMP protocol from [%s]...\n",IP_DST);
-      logmessage(debugmsg,getpid());
+      logmessage(debugmsg);
 #endif
     }
 
@@ -207,7 +207,7 @@ int ICMP_RCV_ECHOREPLY(char *IP_DST)
 #ifdef DEBUG
       memset(debugmsg,0,LOGBUFFER_LENGTH);
       sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] retry\n",IP_DST);
-      logmessage(debugmsg,getpid());
+      logmessage(debugmsg);
 #endif
 
     /* timer to evaluate packet loosed */
@@ -221,7 +221,7 @@ int ICMP_RCV_ECHOREPLY(char *IP_DST)
 #ifdef DEBUG
   memset(debugmsg,0,LOGBUFFER_LENGTH);
   sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] packet losed\n",IP_DST);
-  logmessage(debugmsg,getpid());
+  logmessage(debugmsg);
 #endif
 
   close(sockfd);
@@ -245,7 +245,7 @@ int ICMP_CHECK(char *IP_DST)
 #ifdef DEBUG
       memset(debugmsg,0,LOGBUFFER_LENGTH);
       sprintf(debugmsg,"ICMP_CHECK : Can't send ECHO_REQUEST to [%s]\n",IP_DST);
-      logmessage(debugmsg,getpid());
+      logmessage(debugmsg);
 #endif
       free(debugmsg);
       return(SOCKET_ERROR);
@@ -257,7 +257,7 @@ int ICMP_CHECK(char *IP_DST)
 #ifdef DEBUG
       memset(debugmsg,0,LOGBUFFER_LENGTH);
       sprintf(debugmsg,"ICMP_CHECK : Reexpedite ECHO_REQUEST to [%s]\n",IP_DST);
-      logmessage(debugmsg,getpid());
+      logmessage(debugmsg);
 #endif
       loop=(retry==NB_RETRY)?0:1;
     }
@@ -267,7 +267,7 @@ int ICMP_CHECK(char *IP_DST)
 #ifdef DEBUG
     memset(debugmsg,0,LOGBUFFER_LENGTH);
     sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] after 3 try\n",IP_DST);
-    logmessage(debugmsg,getpid());
+    logmessage(debugmsg);
 #endif
     free(debugmsg);
     return(SOCKET_ERROR);
similarity index 97%
rename from keepalived/icmpcheck.h
rename to icmpcheck.h
index ae41786..e23bfab 100644 (file)
@@ -50,6 +50,6 @@
 #define select_time (DEFAULT_SELECT_TIME * 100)
 
 /* prototypes  */
-int ICMP_CHECK(char *IP_DST);
+//int ICMP_CHECK(char *IP_DST);
 
 #endif
similarity index 100%
rename from keepalived/iputils.c
rename to iputils.c
similarity index 89%
rename from keepalived/iputils.h
rename to iputils.h
index f36fc54..f4bc5fe 100644 (file)
+++ b/iputils.h
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
 
-
-/* prototypes */
-int in_cksum(register unsigned short *ptr , int nbytes);
-int hostToaddr(char *host, u_long *val);
-
-
 #endif
similarity index 81%
rename from keepalived/ipvswrapper.c
rename to ipvswrapper.c
index 0fcf24d..9627729 100644 (file)
@@ -6,12 +6,12 @@
  * Part:        IPVS Kernel wrapper. Use setsockopt call to add/remove
  *              server to/from the loadbalanced server pool.
  *  
- * Version:     $Id: ipvswrapper.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: ipvswrapper.c,v 0.2.1 2001/03/01 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:     
- *              Alexandre Cassen      :       Initial release
+ *              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
@@ -38,29 +38,29 @@ int ipvs_pool_cmd(int cmd, virtualserver *vserver)
 
   ctl.u.vs_user.weight = atoi(vserver->svr->weight);
   
-  if (strcmp(vserver->svr->loadbalancing_kind,"NAT")==0)
+  if (strcmp(vserver->loadbalancing_kind,"NAT")==0)
     ctl.u.vs_user.masq_flags = 0;
   else
-    if (strcmp(vserver->svr->loadbalancing_kind,"DR")==0)
+    if (strcmp(vserver->loadbalancing_kind,"DR")==0)
       ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_DROUTE;
     else
-      if (strcmp(vserver->svr->loadbalancing_kind,"TUN")==0)
+      if (strcmp(vserver->loadbalancing_kind,"TUN")==0)
         ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_TUNNEL;
       else {
         memset(debugmsg,0,LOGBUFFER_LENGTH);
         sprintf(debugmsg,"ipvs_pool_cmd : service [%s:%s] [%s] unknown routing method...\n",
                          vserver->svr->addr_ip, vserver->svr->addr_port,
-                         vserver->svr->loadbalancing_kind);
-        logmessage(debugmsg,getpid());
-        logmessage("ipvs_pool_cmd : Check your configuration file...\n",getpid());
+                         vserver->loadbalancing_kind);
+        logmessage(debugmsg);
+        logmessage("ipvs_pool_cmd : Check your configuration file...\n");
         free(debugmsg);
         return(IPVS_ERROR);
       }
 
   ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff); /* f:f:f:f for default netmask */
 
-  ctl.u.vs_user.protocol = (strcmp(vserver->svr->service_type,"UDP")==0)?IPPROTO_UDP:IPPROTO_TCP;
-  ctl.u.vs_user.timeout  = (strcmp(vserver->timeout_persistence,"NULL")==0)?0:atoi(vserver->timeout_persistence);
+  ctl.u.vs_user.protocol = (strcmp(vserver->service_type,"UDP")==0)?IPPROTO_UDP:IPPROTO_TCP;
+  ctl.u.vs_user.timeout  = (atoi(vserver->timeout_persistence)==0)?0:atoi(vserver->timeout_persistence);
 
   ctl.u.vs_user.vfwmark  = 0;
   ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
@@ -75,7 +75,7 @@ int ipvs_pool_cmd(int cmd, virtualserver *vserver)
   sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
   if (sockfd == -1) {
 #ifdef DEBUG
-    logmessage("ipvs__pool_cmd : Can not initialize SOCK_RAW descriptor\n",getpid());
+    logmessage("ipvs__pool_cmd : Can not initialize SOCK_RAW descriptor\n");
 #endif
     free(debugmsg);
     return IPVS_ERROR;
@@ -88,7 +88,7 @@ int ipvs_pool_cmd(int cmd, virtualserver *vserver)
     memset(debugmsg,0,LOGBUFFER_LENGTH);
     sprintf(debugmsg,"ipvs_pool_cmd : Virtual service [%s:%s] not defined.\n",
                      vserver->addr_ip, vserver->addr_port);
-    logmessage(debugmsg,getpid());
+    logmessage(debugmsg);
 #endif
     close(sockfd);
     free(debugmsg);
@@ -97,7 +97,7 @@ int ipvs_pool_cmd(int cmd, virtualserver *vserver)
 #ifdef DEBUG
     memset(debugmsg,0,LOGBUFFER_LENGTH);
     sprintf(debugmsg,"ipvs_pool_cmd : No such destination %s\n",vserver->svr->addr_ip);
-    logmessage(debugmsg,getpid());
+    logmessage(debugmsg);
 #endif
     close(sockfd);
     free(debugmsg);
similarity index 95%
rename from keepalived/ipvswrapper.h
rename to ipvswrapper.h
index 355bd55..f6de4db 100644 (file)
@@ -55,7 +55,4 @@
 
 #define LOGBUFFER_LENGTH 100
 
-/* prototypes */
-int ipvs_pool_cmd(int cmd, virtualserver *vserver);
-
 #endif
similarity index 50%
rename from keepalived/keepalived.c
rename to keepalived.c
index d2dc4a7..bb9be57 100644 (file)
@@ -5,13 +5,17 @@
  *
  * Part:        Main program structure.
  *  
- * Version:     $Id: keepalived.c,v 0.2.3 2001/01/01 $
+ * Version:     $Id: keepalived.c,v 0.2.6 2001/03/01 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:       
- *         Alexandre Cassen : 2001/01/01 :
+ *         Alexandre Cassen : 2001/03/01 :
+ *          <+> Adding support for multi-url md5sum check.
+ *          <+> Adding pidfile lock.
  *          <+> Change the signalhandling.
+ *          <+> Change the dynamic data structure.
+ *          <+> Use a global var to stock the daemon pid.
  *
  *          Alexandre Cassen : 2000/12/09 : Initial release
  *              
@@ -25,6 +29,8 @@
 
 int main(int argc, char **argv)
 {
+  struct sigaction nact, oact;
+
   printf(PROG" v"VERSION"\n");
 
   if (chdir(CONF_HOME_DIR)) {
@@ -33,7 +39,8 @@ int main(int argc, char **argv)
     exit(1);
   }
 
-  logmessage("Starting keepalived daemon\n",getpid());
+  initdaemonpid(getpid());
+  logmessage("Starting keepalived daemon\n");
 
   switch (fork()) {
     case -1:
@@ -49,38 +56,51 @@ int main(int argc, char **argv)
       return 0;
   }
 
-  if (signal(SIGTERM,sig_handler) == SIG_IGN)
-    signal(SIGTERM,SIG_IGN);
-  signal(SIGINT,SIG_IGN);
-  signal(SIGHUP,SIG_IGN);
+  initdaemonpid(getpid());
+  if(keepalived_running()) {
+    logmessage("Keepalived is already running.\n");
+    return(0);
+  } else
+    if(!pidfile_write(getpid()))
+      logmessage("Can not write keepalived pidfile.\n");
+
+  /* init signal handling */
+  sigemptyset(&nact.sa_mask);
+  nact.sa_handler = sig_handler;
+  nact.sa_flags = SA_RESTART;
+  sigaction(SIGALRM,&nact,&oact);
+  sigaction(SIGTERM,&nact,&oact);
+  sigaction(SIGKILL,&nact,&oact);
+  sigaction(SIGSEGV,&nact,&oact);
+  sigaction(SIGHUP,&nact,&oact);
+  sigaction(SIGINT,&nact,&oact);
 
-  if ((lstVS=(virtualserver *)ConfReader(lstVS,delay_loop))==NULL) {
-    logmessage("Config file contain no data\n",getpid());
+  if ((lstCONF=(configuration_data *)ConfReader(lstCONF))==NULL) {
+    logmessage("Config file contain no data\n");
     exit(0);
   }
 
-  if (!init_services(lstVS)) {
-    logmessage("Ending keepalived daemon\n",getpid());
+  logmessage("Using LVS dynamic data representation :\n");
+  PrintConf(lstCONF);
+
+  if (!init_services(lstCONF->lvstopology)) {
+    logmessage("Ending keepalived daemon\n");
     return 0;
   }
 
-  logmessage("Using LVS dynamic data representation :\n",getpid());
-  PrintLst(lstVS);
-
   while (keep_going) {
-    perform_checks(lstVS);
-    sleep(delay_loop);
+    perform_checks(lstCONF);
+    sleep(atoi(lstCONF->delay_loop));
   }
-
-  return 0;
 }
 
-void sig_handler(int signum)
+static void sig_handler(int signum)
 {
   keep_going=0;
-  ClearLst(lstVS);
-  logmessage("Ending keepalived daemon\n",getpid());
-  signal(signum,sig_handler);
+  ClearConf(lstCONF);
+  logmessage("Ending keepalived daemon\n");
+  pidfile_rm();
+  exit(1);
 }
 
 void perform_ipvs(int alive, virtualserver *lstptr)
@@ -94,7 +114,7 @@ void perform_ipvs(int alive, virtualserver *lstptr)
     sprintf(logbuffer,"Adding service [%s:%s] to VS [%s:%s]\n",
             lstptr->svr->addr_ip,lstptr->svr->addr_port,
             lstptr->addr_ip,lstptr->addr_port);
-    logmessage(logbuffer,getpid());
+    logmessage(logbuffer);
     ipvs_pool_cmd(IPVS_CMD_ADD,lstptr);
   } else {
     lstptr->svr->alive=alive;
@@ -102,7 +122,7 @@ void perform_ipvs(int alive, virtualserver *lstptr)
     sprintf(logbuffer,"Removing service [%s:%s] from VS [%s:%s]\n",
             lstptr->svr->addr_ip,lstptr->svr->addr_port,
             lstptr->addr_ip,lstptr->addr_port);
-    logmessage(logbuffer,getpid());
+    logmessage(logbuffer);
     ipvs_pool_cmd(IPVS_CMD_DEL,lstptr);
   }
   free(logbuffer);
@@ -125,99 +145,125 @@ int init_services(virtualserver *lstptr)
   return 1;
 }
 
-void perform_checks(virtualserver * lstptr)
+void perform_checks(configuration_data *lstconf)
 {
-  char MD5Result[0x40];
+  char *MD5Result;
+  virtualserver *lstptr;
   realserver *pointersvr;
+  urls *pointerurls;
   char *logbuffer;
+  int connectionerror;
+  int digesterror;
+
+  lstptr=lstconf->lvstopology;
 
   logbuffer=(char *)malloc(LOGBUFFER_LENGTH);
+  MD5Result=(char *)malloc(16*2*sizeof(char *));
 
   while(lstptr != NULL) {
     pointersvr=lstptr->svr;
     while(lstptr->svr != NULL) {
 
-      if (strcmp(lstptr->svr->keepalive_method,"ICMP_CHECK") == 0) {
+      if (lstptr->svr->method->flag_type == ICMP_CHECK_ID) {
         if (ICMP_CHECK(lstptr->svr->addr_ip)) {
-#ifdef DEBUG
-          logmessage("ICMP check succeed\n",getpid());
-#endif
+
           if (!lstptr->svr->alive) {
             memset(logbuffer,0,LOGBUFFER_LENGTH);
             sprintf(logbuffer,"ICMP check succeed to %s.\n",lstptr->svr->addr_ip);
-            logmessage(logbuffer,getpid());
+            logmessage(logbuffer);
             perform_ipvs(1,lstptr);
+            SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> ICMP CHECK succeed on service <=\n\n"
+                                                    "The service has been added to the server pool\n");
           }
         } else {
-#ifdef DEBUG
-          logmessage("ICMP check failed\n",getpid());
-#endif
           if (lstptr->svr->alive) {
             memset(logbuffer,0,LOGBUFFER_LENGTH);
             sprintf(logbuffer,"ICMP check failed to %s.\n",lstptr->svr->addr_ip);
-            logmessage(logbuffer,getpid());
+            logmessage(logbuffer);
             perform_ipvs(0,lstptr);
+            SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> ICMP CHECK failed on service <=\n\n"
+                                                    "The service has been removed from the server pool\n");
           }
         }
       }
 
-      if (strcmp(lstptr->svr->keepalive_method,"TCP_CHECK") == 0) {
-        if (TCP_CHECK(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port)) {
-#ifdef DEBUG
-          logmessage("TCP check succeed\n",getpid());
-#endif
+      if (lstptr->svr->method->flag_type == TCP_CHECK_ID) {
+        if (TCP_CHECK(lstptr->svr->addr_ip,lstptr->svr->addr_port)) {
           if (!lstptr->svr->alive) {
             memset(logbuffer,0,LOGBUFFER_LENGTH);
             sprintf(logbuffer,"TCP check succeed to %s:%s.\n",lstptr->svr->addr_ip,
                                                               lstptr->svr->addr_port);
-            logmessage(logbuffer,getpid());
+            logmessage(logbuffer);
             perform_ipvs(1,lstptr);
+            SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> TCP CHECK succeed on service <=\n\n"
+                                                    "The service has been added to the server pool\n");
           }
         } else {
-#ifdef DEBUG
-          logmessage("TCP check failed\n",getpid());
-#endif
           if (lstptr->svr->alive) {
             memset(logbuffer,0,LOGBUFFER_LENGTH);
             sprintf(logbuffer,"TCP check failed to %s:%s.\n",lstptr->svr->addr_ip,
                                                              lstptr->svr->addr_port);
-            logmessage(logbuffer,getpid());
+            logmessage(logbuffer);
             perform_ipvs(0,lstptr);
+            SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> TCP CHECK failed on service <=\n\n"
+                                                    "The service has been removed from the server pool\n");
           }
         }
       }
 
-      if (strcmp(lstptr->svr->keepalive_method,"HTTP_GET") == 0) {
+      if (lstptr->svr->method->flag_type == HTTP_GET_ID) {
+        connectionerror=0;
+        digesterror=0;
+
+        /* perform the multi urls md5 check */
+        pointerurls=lstptr->svr->method->http_get->check_urls;
+        while((lstptr->svr->method->http_get->check_urls != NULL) && 
+              !connectionerror && !digesterror) {
+          memset(MD5Result,0,16*2*sizeof(char *));
+
+          if(!HTTP_GET(lstptr->svr->addr_ip,lstptr->svr->addr_port,
+                      lstptr->svr->method->http_get->check_urls->url,MD5Result,
+                      atoi(lstptr->svr->method->http_get->connection_to),
+                      atoi(lstptr->svr->method->http_get->nb_get_retry),
+                      atoi(lstptr->svr->method->http_get->delay_before_retry)))
+            connectionerror=1;
+
+          if (strcmp(lstptr->svr->method->http_get->check_urls->digest,MD5Result) != 0)
+            digesterror=1;
+
+          lstptr->svr->method->http_get->check_urls=(urls *)lstptr->svr->method->http_get->check_urls->next;
+        }
+        lstptr->svr->method->http_get->check_urls=pointerurls;
+
+        if(!connectionerror) {
 
-        if(HTTP_GET(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port,
-                 lstptr->svr->keepalive_url,MD5Result)) {
+          if (!digesterror) {
 
-          if (strcmp(lstptr->svr->keepalive_result,MD5Result) == 0) {
-#ifdef DEBUG
-            logmessage("HTTP GET check succeed\n",getpid());
-#endif
             if (!lstptr->svr->alive) {
               memset(logbuffer,0,LOGBUFFER_LENGTH);
               sprintf(logbuffer,"HTTP GET check succeed to %s:%s.\n",lstptr->svr->addr_ip,
                                                                      lstptr->svr->addr_port);
-              logmessage(logbuffer,getpid());
+              logmessage(logbuffer);
               perform_ipvs(1,lstptr);
+              SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> HTTP GET check succeed on service <=\n\n"
+                                                    "The service has been added to the server pool\n");
             }
           } else {
-#ifdef DEBUG
-            logmessage("HTTP GET check failed\n",getpid());
-#endif
             if (lstptr->svr->alive) {
               memset(logbuffer,0,LOGBUFFER_LENGTH);
               sprintf(logbuffer,"HTTP GET check failed to %s:%s.\n",lstptr->svr->addr_ip,
                                                                   lstptr->svr->addr_port);
-              logmessage(logbuffer,getpid());
+              logmessage(logbuffer);
               perform_ipvs(0,lstptr);
+              SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> HTTP GET check failed on service <=\n\n"
+                                                      "The service has been removed from the server pool\n");
             }
           }
         } else {
           if(lstptr->svr->alive) {
             perform_ipvs(0,lstptr);
+            SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> HTTP GET check failed on service <=\n\n"
+                                                    "The service has been removed from the server pool\n");
           }
         }
 
@@ -227,5 +273,6 @@ void perform_checks(virtualserver * lstptr)
     lstptr->svr=pointersvr;
     lstptr=(virtualserver *)lstptr->next;
   }
+  free(MD5Result);
   free(logbuffer);
 }
similarity index 88%
rename from keepalived/keepalived.h
rename to keepalived.h
index d11b930..97a5b08 100644 (file)
@@ -31,6 +31,7 @@
 #include <fcntl.h>
 
 #include "cfreader.h"
+#include "smtpwrapper.h"
 #include "icmpcheck.h"
 #include "tcpcheck.h"
 #include "httpget.h"
 
 /* Global variables */
 volatile sig_atomic_t keep_going = 1;
-virtualserver *lstVS;
-int delay_loop = 60;
+configuration_data *lstCONF;
 
 /* Build version */
 #define PROG    "keepalived"
-#define VERSION "0.2.3 (01/01, 2001), Alexandre Cassen"
+#define VERSION "0.2.6 (03/01, 2001), Alexandre Cassen"
 
 /* prototypes */
-void sig_handler(int signum);
-void perform_checks(virtualserver * lstptr);
+static void sig_handler(int signum);
+void perform_checks(configuration_data * lstconf);
 int init_services(virtualserver *lstptr);
 
 #endif
diff --git a/keepalived/cfreader.c b/keepalived/cfreader.c
deleted file mode 100644 (file)
index a6318b0..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* 
- * Soft:        Keepalived is a failover program for the LVS project
- *              <www.linuxvirtualserver.org>. It monitor & manipulate
- *              a loadbalanced server pool using multi-layer checks.
- * 
- * Part:        Configuration file parser/reader. Place into the dynamic
- *              data structure representation the conf file representing
- *              the loadbalanced server pool.
- *  
- * Version:     $Id: cfreader.c,v 0.2.1 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.
- */
-
-#include "cfreader.h"
-
-int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
-{
-  virtualserver *pointerptr=lstptr;
-
-  while(lstptr != NULL) {
-    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
-      lstptr=pointerptr;
-      return 1;
-    }
-    lstptr=(virtualserver *)lstptr->next;
-  }
-  lstptr=pointerptr;
-  return 0;
-}
-
-int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
-{
-  realserver *pointerptr=lstptr;
-
-  while(lstptr != NULL) {
-    if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
-      lstptr=pointerptr;
-      return 1;
-    }
-    lstptr=(realserver *)lstptr->next;
-  }
-  lstptr=pointerptr;
-  return 0;
-}
-
-virtualserver * AddItem_VS(virtualserver *lstptr, char ip[16], char port[6], char sched[6], char tpersistence[4])
-{
-  virtualserver *pointerlst=lstptr;
-
-  if(AlreadyExist_VS(lstptr,ip,port)) return lstptr;
-
-  if (lstptr != NULL) {
-    while(lstptr->next != NULL) lstptr=(virtualserver *)lstptr->next;
-    lstptr->next=(struct virtualserver *)malloc(sizeof(virtualserver));
-    lstptr=(virtualserver *)lstptr->next;
-    lstptr->svr=NULL;
-    lstptr->next=NULL;
-    
-    /* Fill in the data structure */
-    strncat(lstptr->addr_ip,ip,sizeof(lstptr->addr_ip));
-    strncat(lstptr->addr_port,port,sizeof(lstptr->addr_port));
-    strncat(lstptr->sched,sched,sizeof(lstptr->sched));
-    strncat(lstptr->timeout_persistence,tpersistence,sizeof(lstptr->timeout_persistence));
-    
-    return pointerlst;
-  } else {
-    lstptr=(virtualserver *)malloc(sizeof(virtualserver));
-    lstptr->svr=NULL;
-    lstptr->next=NULL;
-    
-    /* Fill in the data structure */
-    strncat(lstptr->addr_ip,ip,sizeof(lstptr->addr_ip));
-    strncat(lstptr->addr_port,port,sizeof(lstptr->addr_port));
-    strncat(lstptr->sched,sched,sizeof(lstptr->sched));
-    strncat(lstptr->timeout_persistence,tpersistence,sizeof(lstptr->timeout_persistence));
-
-    return lstptr;
-  }
-}
-
-virtualserver * AddItem_SVR(virtualserver *lstvs, 
-                            char ip_vs[16], char port_vs[6],
-                            realserver *server)
-{
-  virtualserver *pointerlst=lstvs;
-  realserver *pointersvr;
-
-
-  while( (lstvs->next != NULL) && 
-         !((strcmp(lstvs->addr_ip,ip_vs)==0)  &&
-           (strcmp(lstvs->addr_port,port_vs)==0)) )
-    lstvs=(virtualserver *)lstvs->next;
-  
-  if( (strcmp(lstvs->addr_ip,ip_vs)==0) && 
-      (strcmp(lstvs->addr_port,port_vs)==0) ) {
-
-    if(AlreadyExist_SVR(lstvs->svr,server->addr_ip,server->addr_port)) return pointerlst;
-
-    if (lstvs->svr != NULL) {
-      pointersvr=lstvs->svr;
-
-      while(lstvs->svr->next != NULL) lstvs->svr=(realserver *)lstvs->svr->next;
-
-      lstvs->svr->next=(struct realserver *)server;
-
-      lstvs->svr=pointersvr;
-    } else {
-      lstvs->svr=(realserver *)server;
-    }
-  }
-  return pointerlst;
-}
-
-void PrintLst(virtualserver * lstptr)
-{
-  realserver *pointersvr;
-  char *tempbuff;
-
-  tempbuff=(char *)malloc(TEMPBUFFERLENGTH);
-  
-  if(lstptr == NULL) 
-    printf("Queue empty !!!\n");
-  else
-    while(lstptr != NULL) {
-      memset(tempbuff,0,TEMPBUFFERLENGTH);
-      sprintf(tempbuff,"VS IP = %s, Port = %s, SCHED = %s, PERSISTENCE TIMEOUT = %s\n",
-                       lstptr->addr_ip, lstptr->addr_port,
-                       lstptr->sched, lstptr->timeout_persistence);
-      logmessage(tempbuff,getpid());
-      pointersvr=lstptr->svr;
-      while(lstptr->svr != NULL) {
-        memset(tempbuff,0,TEMPBUFFERLENGTH);
-        sprintf(tempbuff," -> SVR IP = %s, Port = %s\n",lstptr->svr->addr_ip,lstptr->svr->addr_port);
-        logmessage(tempbuff,getpid());
-
-        memset(tempbuff,0,TEMPBUFFERLENGTH);
-        sprintf(tempbuff,"    -> KM = %s, KA = %s, KU = %s, KR = %s\n",
-                         lstptr->svr->keepalive_method, lstptr->svr->keepalive_url,
-                         lstptr->svr->keepalive_algo, lstptr->svr->keepalive_result);
-        logmessage(tempbuff,getpid());
-
-        memset(tempbuff,0,TEMPBUFFERLENGTH);
-        sprintf(tempbuff,"    -> LB = %s, Weight = %s, ST = %s, Alive = %d\n",
-                         lstptr->svr->loadbalancing_kind, lstptr->svr->weight,
-                         lstptr->svr->service_type, lstptr->svr->alive);
-        logmessage(tempbuff,getpid());
-
-        lstptr->svr=(realserver *)lstptr->svr->next;
-      }
-      lstptr->svr=pointersvr;
-      lstptr=(virtualserver *)lstptr->next;
-    }
-  free(tempbuff);
-}
-
-realserver * RemoveSVR(realserver * lstptr)
-{
-  realserver *t;
-
-//  printf("  Removing SVR : (%s,%s)\n",lstptr->addr_ip,lstptr->addr_port);
-  t=(realserver *)lstptr->next;
-  free(lstptr);
-  return t;
-}
-
-virtualserver * RemoveVS(virtualserver * lstptr)
-{
-  virtualserver *t;
-
-//  printf("Removing VS : (%s,%s)\n",lstptr->addr_ip,lstptr->addr_port);
-  t=(virtualserver *)lstptr->next;
-  while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
-  free(lstptr);
-  return t;
-}
-
-void ClearLst(virtualserver * lstptr)
-{
-  while(lstptr != NULL) {
-    lstptr=RemoveVS(lstptr);
-  }
-}
-
-virtualserver * AddItem(virtualserver *lstvs, char ip_vs[16], char port_vs[6],
-                            char ip_svr[16], char port_svr[16], char kmethod[12],
-                            char kurl[101],char kalgo[11], char kresult[33], char lbkind[6],
-                            char weight[4], char stype[4])
-{
-  realserver *server;
-  server=(realserver *)malloc(sizeof(realserver));
-
-  strncat(server->addr_ip,ip_svr,sizeof(server->addr_ip));
-  strncat(server->addr_port,port_svr,sizeof(server->addr_port));
-  strncat(server->keepalive_method,kmethod,sizeof(server->keepalive_method));
-  strncat(server->keepalive_url,kurl,sizeof(server->keepalive_url));
-  strncat(server->keepalive_algo,kalgo,sizeof(server->keepalive_algo));
-  strncat(server->keepalive_result,kresult,sizeof(server->keepalive_result));
-  strncat(server->loadbalancing_kind,lbkind,sizeof(server->loadbalancing_kind));
-  strncat(server->weight,weight,sizeof(server->weight));
-  strncat(server->service_type,stype,sizeof(server->service_type));
-
-  server->alive=1;
-  server->next=NULL;
-
-  lstvs=AddItem_SVR(lstvs,ip_vs,port_vs,server);
-
-  return lstvs;
-}
-
-virtualserver * ConfReader(virtualserver *lst_vs, int delay_loop)
-{
-  FILE *stream;
-  char *string="";
-  virtualserver *vsfill;
-  realserver *svrfill;
-
-  lst_vs=NULL; /* Initialise the dynamic data structure */
-
-  string=(char *)malloc(TEMPBUFFERLENGTH);
-  vsfill=(virtualserver *)malloc(sizeof(virtualserver));
-  svrfill=(realserver *)malloc(sizeof(realserver));
-  svrfill->alive=1;
-  svrfill->next=NULL;
-  stream=fopen(CONFFILE,"r");
-  if(stream==NULL) {
-    logmessage("ConfReader : Can not read the config file\n",getpid());
-    return(NULL);
-  }
-
-  while(!feof(stream)) {
-    fscanf(stream,"%s",string);
-    if(strcmp(string,DELAYWORD) == 0) {
-      fscanf(stream,"%s",string);
-      delay_loop=atoi(string);
-    }
-    if(strcmp(string,VSWORD) == 0) {
-      fscanf(stream,"%s",vsfill->addr_ip);
-      fscanf(stream,"%s",vsfill->addr_port);
-      fscanf(stream,"%s",vsfill->sched);
-      fscanf(stream,"%s",vsfill->timeout_persistence);
-      lst_vs = AddItem_VS(lst_vs,vsfill->addr_ip,vsfill->addr_port,vsfill->sched,
-                          vsfill->timeout_persistence);
-      fscanf(stream,"%s",string);
-      fscanf(stream,"%s",string);
-      do {
-        if(strcmp(string,SVRWORD) == 0) {
-          fscanf(stream,"%s",svrfill->addr_ip);
-          fscanf(stream,"%s",svrfill->addr_port);
-          fscanf(stream,"%s",string);
-          fscanf(stream,"%s",svrfill->keepalive_method);
-          fscanf(stream,"%s",svrfill->keepalive_url);
-          fscanf(stream,"%s",svrfill->keepalive_algo);
-          fscanf(stream,"%s",svrfill->keepalive_result);
-          fscanf(stream,"%s",svrfill->loadbalancing_kind);
-          fscanf(stream,"%s",svrfill->weight);
-          fscanf(stream,"%s",svrfill->service_type);
-          fscanf(stream,"%s",string);
-
-          lst_vs = AddItem(lst_vs,vsfill->addr_ip,vsfill->addr_port,
-                                  svrfill->addr_ip,svrfill->addr_port,svrfill->keepalive_method,
-                                  svrfill->keepalive_url,svrfill->keepalive_algo,
-                                  svrfill->keepalive_result,svrfill->loadbalancing_kind,
-                                  svrfill->weight,
-                                  svrfill->service_type); 
-        }
-        fscanf(stream,"%s",string);
-      } while(strcmp(string,ENDFLAG) != 0);
-    }
-  }
-
-  free(string);
-  free(vsfill);
-  free(svrfill);
-  fclose(stream);
-
-  return lst_vs;
-}
diff --git a/keepalived/cfreader.h b/keepalived/cfreader.h
deleted file mode 100644 (file)
index 5d3fd63..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 
- * Soft:        Keepalived is a failover program for the LVS project
- *              <www.linuxvirtualserver.org>. It monitor & manipulate
- *              a loadbalanced server pool using multi-layer checks.
- * 
- * Part:        cfreader.c include file.
- *  
- * Version:     $Id: cfreader.h,v 0.2.1 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 CFREADER_H
-#define CFREADER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define CONFFILE "keepalived.conf"
-
-#define TEMPBUFFERLENGTH 100
-
-#define DELAYWORD    "delay_loop"
-#define VSWORD       "virtual_server"
-#define SVRWORD      "real_server"
-#define BEGINFLAG    "{"
-#define ENDFLAG      "}"
-
-/* Structure definition  */
-typedef struct _real_server {
-  char addr_ip[15+1];
-  char addr_port[5+1];
-  char keepalive_method[11+1];
-  char keepalive_url[100+1];
-  char keepalive_algo[10+1];
-  char keepalive_result[32+1];
-  char loadbalancing_kind[5+1];
-  char weight[3+1];
-  char service_type[3+1];
-  int alive;
-
-  struct realserver *next;
-} realserver;
-
-typedef struct _virtual_server {
-  char addr_ip[15+1];
-  char addr_port[5+1];
-  char sched[5+1];
-  char timeout_persistence[4];
-  realserver *svr;
-
-  struct virtualserver *next;
-} virtualserver;
-
-
-/* prototypes */
-virtualserver * ConfReader(virtualserver *lst_vs, int delay_loop);
-void ClearLst(virtualserver * lstptr);
-void PrintLst(virtualserver * lstptr);
-
-#endif
diff --git a/keepalived/etc/keepalived/keepalived.conf b/keepalived/etc/keepalived/keepalived.conf
deleted file mode 100644 (file)
index 6a7375b..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-# Configuration File for keepalived
-
-virtual_server 10.10.10.1 1358 rr 50 {
-    real_server 192.168.200.2 1358 {
-        HTTP_GET
-        /url/test.jsp
-        MD5_SUM
-        ec90a42b99ea9a2f5ecbe213ac9eba03
-        NAT
-        1
-        TCP
-    }
-    real_server 192.168.200.3 1358 {
-        TCP_CHECK
-        NULL
-        NULL
-        NULL
-        NAT
-        1
-        TCP
-    }
-    real_server 192.168.200.4 1358 {
-        ICMP_CHECK
-        NULL
-        NULL
-        NULL
-        NAT
-        1
-        TCP
-    }
-}
-
-virtual_server 10.10.10.2 1359 rr 50 {
-    real_server 192.168.200.2 1359 {
-        HTTP_GET
-        /url/test.jsp
-        MD5_SUM
-        ec90a42b99ea9a2f5ecbe213ac9eba03
-        NAT
-        1
-        TCP
-    }
-    real_server 192.168.200.3 80 {
-        TCP_CHECK
-        NULL
-        NULL
-        NULL
-        NAT
-        1
-        TCP
-    }
-    real_server 192.168.200.4 1234 {
-        ICMP_CHECK
-        NULL
-        NULL
-        NULL
-        NAT
-        1
-        TCP
-    }
-}
-
diff --git a/keepalived/etc/lvs.conf b/keepalived/etc/lvs.conf
deleted file mode 100644 (file)
index e4609fe..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Configuration file for PortFW & NAT
-# /etc/lvs.conf
-
-# Port forwarding configuration
-ipvsadm -A -t 10.10.10.1:1358 -s rr -p 50
-ipvsadm -A -t 10.10.10.2:1359 -s rr -p 50
-
-# NAT configuration
-ipchains -A forward -j MASQ -p tcp 192.168.200.0/24 1358 -d 0.0.0.0/0
-ipchains -A forward -j MASQ -p tcp 192.168.200.0/24 1359 -d 0.0.0.0/0
-ipchains -A forward -j MASQ -p tcp 192.168.200.0/24 80 -d 0.0.0.0/0
-ipchains -A forward -j MASQ -p tcp 192.168.200.0/24 1234 -d 0.0.0.0/0
diff --git a/keepalived/httpget.c b/keepalived/httpget.c
deleted file mode 100644 (file)
index bf82c9b..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/* 
- * Soft:        Keepalived is a failover program for the LVS project
- *              <www.linuxvirtualserver.org>. It monitor & manipulate
- *              a loadbalanced server pool using multi-layer checks.
- * 
- * Part:        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.
- *  
- * Version:     $Id: httpget.c,v 0.2.1 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.
- */
-
-#include "httpget.h"
-
-int GET(char *IP_SRC,char *IP_DST, char *PORT_DST, char *URL, char *buffer)
-{
-  register int sdesc;
-  int long_inet;
-  int rcv_buffer_size=0;
-  char *str_request;
-  struct hostent *ip_serv;
-  struct sockaddr_in adr_serv;
-  struct linger li = { 0 };
-  char *debugmsg;
-
-  if (!TCP_CHECK(IP_SRC,IP_DST,PORT_DST)) {
-#ifdef DEBUG
-    logmessage("HTTP_GET : TCP check failed...\n",getpid());
-#endif
-    return 0;
-  }
-
-  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
-  str_request=(char *)malloc(GET_REQUEST_BUFFER_LENGTH);
-  strcpy(str_request,"GET ");
-  strcat(str_request,URL);
-  strcat(str_request,"\n");
-
-  if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"HTTP_GET : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(str_request);
-    free(debugmsg);
-    return(SOCKET_ERROR);
-  }
-
-  /* free the tcp port after closing the socket descriptor */
-  li.l_onoff=1;
-  li.l_linger=0;
-  setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
-  long_inet = sizeof(struct sockaddr_in);
-
-  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"HTTP_GET : Can not resolve remote host %s\n",IP_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(str_request);
-    free(debugmsg);
-    close(sdesc);
-    return(SOCKET_ERROR);
-  }
-
-  memset(&adr_serv,0,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(atoi(PORT_DST));
-
-  if ( connect(sdesc, (struct sockaddr *)&adr_serv, long_inet) == -1) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"HTTP_GET : Can not connect remote host %s:%s\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(str_request);
-    free(debugmsg);
-    close(sdesc);
-    return(SOCKET_ERROR);
-  }
-
-  if (send(sdesc,str_request,strlen(str_request),0) == -1) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"HTTP_GET : Can not send data to remote host %s:%s\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(str_request);
-    free(debugmsg);
-    close(sdesc);
-    return(SOCKET_ERROR);
-  }
-
-  rcv_buffer_size=recv(sdesc,buffer,GET_BUFFER_LENGTH,0);
-  if ( rcv_buffer_size == -1 ) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"HTTP_GET : Can not recieve data from remote host %s:%s\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(str_request);
-    free(debugmsg);
-    close(sdesc);
-    return(SOCKET_ERROR);
-  }
-
-  close(sdesc);
-  free(str_request);
-  free(debugmsg);
-  return(rcv_buffer_size);
-}
-
-int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x40])
-{
-  char *bufferget;
-  int retcode=0;
-
-  bufferget=(char *)malloc(GET_BUFFER_LENGTH);
-  memset(bufferget,0,GET_BUFFER_LENGTH);
-
-  if ((retcode=GET(IP_SRC,IP_DST,PORT_DST,URL,bufferget))!=0) {
-    MD5Data(bufferget,retcode,MDResult);
-    free(bufferget);
-    return(1);
-  } else {
-    free(bufferget);
-    return(0);
-  }
-  free(bufferget);
-}
diff --git a/keepalived/tcpcheck.c b/keepalived/tcpcheck.c
deleted file mode 100644 (file)
index a884eb6..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/* 
- * Soft:        Keepalived is a failover program for the LVS project
- *              <www.linuxvirtualserver.org>. It monitor & manipulate
- *              a loadbalanced server pool using multi-layer checks.
- * 
- * Part:        TCP CHECK. Build a TCP/IP packet and send it to a remote
- *              server. This check implement the tcp half open connection
- *              check.
- *  
- * Version:     $Id: tcpcheck.c,v 0.2.3 2000/12/29 $
- * 
- * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *              
- * Changes:     
- *         Alexandre Cassen : 2000/12/29 :
- *          <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
- *              Call this function in TCP_RCV_SYNACK_PACKET with 1s timeout.
- *          <+> Added a timer (2s timeouted) in TCP_RCV_SYNACK_PACKET to check
- *              SYN|ACK packet. Check perform on tcp sequence, remote tcp port number,
- *              tcp SYN|ACK flag, remote ip address.
- *          <+> Added a 3 time SYN packet send retry.
- *
- *         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 "tcpcheck.h"
-
-int recvfrom_to(int s, char *buf, int len, struct sockaddr *saddr, int timo)
-{
-  int nfound,slen,n;
-  struct timeval to;
-  fd_set readset,writeset;
-
-  to.tv_sec  = timo/1000;
-  to.tv_usec = 0;
-
-  FD_ZERO(&readset);
-  FD_ZERO(&writeset);
-  FD_SET(s,&readset);
-  nfound = select(s+1,&readset,&writeset,NULL,&to);
-  if (nfound<0) {
-#ifdef DEBUG
-    logmessage("TCP_CHECK : Select socket descriptor error...\n",getpid());
-#endif
-    return(-1);
-  }
-  if (nfound==0) {
-#ifdef DEBUG
-    logmessage("TCP_CHECK : Timeout receiving SYN response...\n",getpid());
-#endif
-    return -1;
-  }
-  slen=sizeof(struct sockaddr_in);
-  n=recvfrom(s,buf,len,0,saddr,&slen);
-  if (n<0) {
-#ifdef DEBUG
-    logmessage("TCP_CHECK : recvfrom error...\n",getpid());
-#endif
-    return -1;
-  }
-  return n;
-}
-
-int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG,unsigned long int SEQ)
-{
-  register int rawsock;
-  struct linger li = { 0 };
-
-  /* Packet Data representation */
-  struct iphdr *packet_ip;
-  struct tcphdr *packet_tcp;
-  struct tcphdr_pseudo packet_tcppseudo;
-  struct sockaddr_in dest;
-  char *packet;
-
-  /* Packet pointer affectation */
-  packet=(char *)malloc(SYNPACKET_LENGTH);
-  memset(packet,0,SYNPACKET_LENGTH);
-  memset(&dest,0,sizeof(struct sockaddr_in));
-  packet_ip=(struct iphdr *)packet;
-  packet_tcp=(struct tcphdr *)(packet_ip+1);
-
-  if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1 ) {
-    free(packet);
-    return (SOCKET_ERROR);
-  }
-
-  /* free the tcp port after closing the socket descriptor */
-  li.l_onoff=1;
-  li.l_linger=0;
-  setsockopt(rawsock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
-  /* Fill in the IP header structure */
-  packet_ip->version  = 4;
-  packet_ip->ihl      = 5;
-  packet_ip->tos      = 0 ;
-  packet_ip->tot_len  = sizeof(struct iphdr) + sizeof(struct tcphdr);
-  packet_ip->id       = htons(random());
-  packet_ip->frag_off = 0;
-  packet_ip->ttl      = 30;              /* 30 Hops Max */
-  packet_ip->protocol = IPPROTO_TCP;
-  packet_ip->saddr    = inet_addr(IP_SRC);
-  packet_ip->daddr    = inet_addr(IP_DST);
-  packet_ip->check    = in_cksum((unsigned short *)packet_ip, sizeof(struct iphdr));
-
-  /* Fill in the TCP header structure */
-  packet_tcp->source  = htons(STCP);
-  packet_tcp->dest    = htons(atoi(PORT_DST));
-  packet_tcp->seq     = SEQ;
-  packet_tcp->doff    = sizeof(struct tcphdr)/4;
-  packet_tcp->ack_seq = 0;
-  packet_tcp->res1    = 0;
-  packet_tcp->fin     = (strstr(FLAG,"FIN"))?1:0;
-  packet_tcp->syn     = (strstr(FLAG,"SYN"))?1:0;
-  packet_tcp->rst     = (strstr(FLAG,"RST"))?1:0;
-  packet_tcp->psh     = (strstr(FLAG,"PSH"))?1:0;
-  packet_tcp->ack     = (strstr(FLAG,"ACK"))?1:0;
-  packet_tcp->urg     = (strstr(FLAG,"URG"))?1:0;
-  packet_tcp->res2    = 0;
-  packet_tcp->window  = htons(65535);
-  packet_tcp->check   = 0;
-  packet_tcp->urg_ptr = 0;
-
-  /* Fill in the TCP pseudo structure */
-  packet_tcppseudo.saddr = packet_ip->saddr;
-  packet_tcppseudo.daddr = packet_ip->daddr;
-  packet_tcppseudo.zero = 0;
-  packet_tcppseudo.proto = packet_ip->protocol;
-  packet_tcppseudo.tcplen = htons(sizeof(struct tcphdr));
-  bcopy((char *)packet_tcp, (char *)&packet_tcppseudo.tcp, sizeof(struct tcphdr));
-
-  packet_tcp->check = in_cksum((unsigned short *)&packet_tcppseudo, 
-                             sizeof(struct tcphdr_pseudo));
-
-  /* Fill in the Sockaddr structure */
-  /* A little fake, IP & PORT are in IP & TCP headers */
-  dest.sin_family = AF_INET;
-  dest.sin_port  = packet_tcp->dest;
-  dest.sin_addr.s_addr = packet_ip->daddr;
-
-  if (sendto(rawsock,packet,sizeof(struct iphdr) + sizeof(struct tcphdr),
-             0,&dest,sizeof(dest)) < 0) {
-    close(rawsock);
-    free(packet);
-    return(SOCKET_ERROR);
-  }
-
-  close(rawsock);
-  free(packet);
-  return(SOCKET_SUCCESS);
-}
-
-int TCP_RCV_SYNACK_PACKET(char *IP_DST, char *PORT_DST, unsigned long int SEQ)
-{
-  register int rawsock;
-  struct linger li = { 0 };
-  time_t hint;
-  struct tm *date;
-  int timer_before, timer_after;
-  int loop = 1;
-  char *debugmsg;
-
-  /* Packet Data representation */
-  struct iphdr *packet_ip;
-  struct tcphdr *packet_tcp;
-  struct tcphdr_pseudo packet_tcppseudo;
-  struct sockaddr_in dest;
-  char *packet;
-
-  /* Packet pointer affectation */
-  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
-  packet=(char *)malloc(SYNPACKET_LENGTH);
-  memset(packet,0,SYNPACKET_LENGTH);
-  memset(debugmsg,0,LOGBUFFER_LENGTH);
-  memset(&dest,0,sizeof(struct sockaddr_in));
-  packet_ip=(struct iphdr *)packet;
-  packet_tcp=(struct tcphdr *)(packet_ip+1);
-
-  if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1 ) {
-    free(debugmsg);
-    free(packet);
-    return (SOCKET_ERROR);
-  }
-
-  /* free the tcp port after closing the socket descriptor */
-  li.l_onoff=1;
-  li.l_linger=0;
-  setsockopt(rawsock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
-  /* Fill in the Sockaddr structure */
-  memset(&dest,0,sizeof(struct sockaddr_in));
-  dest.sin_family = AF_INET;
-  dest.sin_port = htons(atoi(PORT_DST));
-  dest.sin_addr.s_addr = inet_addr(IP_DST);
-
-  /* Timer initialization */
-  /* We can also use a signal SIGALRM and catch this signal with handler to break the loop */
-  hint = time((long*)0);
-  date = localtime(&hint);
-  timer_before = date->tm_sec;
-
-  while(loop) {
-    if (recvfrom_to(rawsock,packet,SYNPACKET_LENGTH,(struct sockaddr *)&dest,1000) < 0) {
-      close(rawsock);
-      free(debugmsg);
-      free(packet);
-      return(SOCKET_ERROR);
-    }
-
-    if ( packet_tcp->syn && packet_tcp->ack && 
-        (packet_tcp->ack_seq == SEQ) &&
-        (packet_ip->saddr == dest.sin_addr.s_addr) &&
-        (packet_tcp->source == htons(atoi(PORT_DST))) ) {
-      close(rawsock);
-      free(debugmsg);
-      free(packet);
-      return(SOCKET_SUCCESS);
-    }
-
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"TCP_CHECK : SYN|ACK packet not recieved from [%s:%s]. Retry\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-
-    /* timer to evaluate packet loosed */
-    hint = time((long*)0);
-    date = localtime(&hint);
-    timer_after = date->tm_sec;
-
-    if(abs(timer_after-timer_before)>1) loop=0;
-  }
-
-#ifdef DEBUG
-  memset(debugmsg,0,LOGBUFFER_LENGTH);
-  sprintf(debugmsg,"TCP_CHECK : SYN|ACK packet loosed from [%s:%s]\n",IP_DST,PORT_DST);
-  logmessage(debugmsg,getpid());
-#endif
-
-  close(rawsock);
-  free(debugmsg);
-  free(packet);
-  return(SOCKET_ERROR);
-}
-
-int TCP_CHECK(char *IP_SRC, char *IP_DST, char *PORT_DST)
-{
-  register int tcpsock;
-  char *debugmsg;
-  int loop=1;
-  int retry=0;
-  unsigned long int SEQTCP=0;
-
-  /* Memory allocation for the data structures */
-  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
-
-  while(loop) {
-    SEQTCP = random() & 0xffff;
-
-    if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"SYN",htonl(SEQTCP-1))) {
-#ifdef DEBUG
-      memset(debugmsg,0,LOGBUFFER_LENGTH);
-      sprintf(debugmsg,"TCP_CHECK : Can't send SYN request to [%s:%s]\n",IP_DST,PORT_DST);
-      logmessage(debugmsg,getpid());
-#endif
-      free(debugmsg);
-      return(SOCKET_ERROR);
-    }
-    if(TCP_RCV_SYNACK_PACKET(IP_DST,PORT_DST,htonl(SEQTCP))) {
-      loop=0;
-    } else {
-      retry++;
-#ifdef DEBUG
-      memset(debugmsg,0,LOGBUFFER_LENGTH);
-      sprintf(debugmsg,"TCP_CHECK : Reexpedite SYN request to [%s:%s]\n",IP_DST,PORT_DST);
-      logmessage(debugmsg,getpid());
-#endif
-      loop=(retry==NB_RETRY)?0:1;
-    }
-  }
-
-  if (retry==NB_RETRY) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"TCP_CHECK : SYN|ACK response not recieved from [%s:%s] after 3 try\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(debugmsg);
-    return(SOCKET_ERROR);
-  }
-
-  /* The we send a RST TCP packet to be sure that the remote host */
-  /* close the communication channel.                             */
-  /* Needed some time by MS Windows .... damned...                */
-
-  if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"RST ACK",SEQTCP)) {
-#ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"TCP_CHECK : Can't send RST to [%s:%s]\n",IP_DST,PORT_DST);
-    logmessage(debugmsg,getpid());
-#endif
-    free(debugmsg);
-    return(SOCKET_ERROR);
-  }
-
-  free(debugmsg);
-  return(SOCKET_SUCCESS);
-}
diff --git a/libmd-0.3 b/libmd-0.3
deleted file mode 100644 (file)
index fcd15ac..0000000
--- a/libmd-0.3
+++ /dev/null
@@ -1 +0,0 @@
-ff
diff --git a/md5.c b/md5.c
new file mode 100644 (file)
index 0000000..9a3b957
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,327 @@
+/*\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/md5.h b/md5.h
new file mode 100644 (file)
index 0000000..72ddcb8
--- /dev/null
+++ b/md5.h
@@ -0,0 +1,94 @@
+/*\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/pidfile.c b/pidfile.c
new file mode 100644 (file)
index 0000000..fd21e07
--- /dev/null
+++ b/pidfile.c
@@ -0,0 +1,50 @@
+/*
+ * 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:        Pid file lock utils.
+ *
+ * Version:     $Id: pidfile.c,v 0.2.6 2001/03/05 $
+ *
+ * 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.
+ */
+
+#include "pidfile.h"
+
+int pidfile_write(int pid)
+{
+  FILE *pidfile = fopen(PIDFILENAME,"w");
+
+  if(!pidfile) {
+    logmessage("pidfile_write : Can not open pidfile\n");
+    return(0);
+  }
+  fprintf(pidfile,"%d\n",pid);
+  fclose(pidfile);
+  return(1);
+}
+
+void pidfile_rm()
+{
+  unlink(PIDFILENAME);
+}
+
+int keepalived_running()
+{
+  FILE *pidfile;
+
+  if ((pidfile=fopen(PIDFILENAME,"r")) == NULL)
+    return 0;
+
+  fclose(pidfile);
+  return 1;
+}
similarity index 83%
rename from keepalived/utils.h
rename to pidfile.h
index 231c8e8..e4ef5d3 100644 (file)
+++ b/pidfile.h
@@ -3,9 +3,9 @@
  *              <www.linuxvirtualserver.org>. It monitor & manipulate
  *              a loadbalanced server pool using multi-layer checks.
  *
- * Part:        utils.c include file.
+ * Part:        pidfile.c include file.
  *
- * Version:     $Id: utils.h,v 0.2.1 2000/12/09 $
+ * Version:     $Id: pidfile.h,v 0.2.6 2001/03/05 $
  *
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *
@@ -18,8 +18,8 @@
  *              2 of the License, or (at your option) any later version.
  */
 
-#ifndef UTILS_H
-#define UTILS_H
+#ifndef PIDFILE_H
+#define PIDFILE_H
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -31,6 +31,6 @@
 #include <netdb.h>
 #include <string.h>
 
-#define LOGFILE       "log/keepalived.log"
+#define PIDFILENAME "/var/run/keepalived.pid"
 
 #endif
diff --git a/smtpwrapper.c b/smtpwrapper.c
new file mode 100644 (file)
index 0000000..93c3450
--- /dev/null
@@ -0,0 +1,452 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        SMTP WRAPPER connect to a specified smtp server and send mail
+ *              using the smtp protocol according to the RFC 822. A non blocking 
+ *              timeouted connection is used to handle smtp protocol.
+ *  
+ * Version:     $Id: smtpwrapper.c,v 0.2.6 2001/03/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *         Alexandre Cassen : 2001/03/01 : 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 "smtpwrapper.h"
+
+int send_to(register int sdesc, fd_set wfds, struct timeval tv, char *buffer)
+{
+  select(sdesc+1,NULL,&wfds,NULL,&tv);
+  if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Timeout writing data to smtp server\n");
+#endif
+    return(SOCKET_ERROR);
+  }
+
+  if (send(sdesc,buffer,strlen(buffer),0) == -1) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Can not send data to remote smtp server\n");
+#endif
+    return(SOCKET_ERROR);
+  }
+
+  return(SOCKET_SUCCESS);
+}
+
+int read_to(register int sdesc, fd_set rfds, struct timeval tv, char *buffer)
+{
+  int rcv_buffer_size=0;
+  long total_length=0;
+  char *buffertmp;
+
+  buffertmp=(char *)malloc(BUFFER_LENGTH);
+  memset(buffertmp,0,BUFFER_LENGTH);
+
+  select(sdesc+1,&rfds,NULL,NULL,&tv);
+  if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Timeout receiving data from smtp server\n");
+#endif
+    free(buffertmp);
+    return(SOCKET_ERROR);
+  }
+
+  while((rcv_buffer_size = read(sdesc,buffertmp,BUFFER_LENGTH)) != 0) {
+    if ( rcv_buffer_size == -1 ) {
+      if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+      logmessage("SMTP_SENDMAIL : Can not recieve data from remote smtp server\n");
+#endif
+      free(buffertmp);
+      return(SOCKET_ERROR);
+    }
+    memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+    memset(buffertmp,0,BUFFER_LENGTH);
+    total_length += rcv_buffer_size;
+  }
+
+end:
+  free(buffertmp);
+  return(SOCKET_SUCCESS);
+}
+
+int smtp_cmd(register int sdesc,fd_set rfds,fd_set wfds,struct timeval tv,char *smtpcmd,char *retcode)
+{
+  char *buffer;
+  char *smtpcode;
+
+  buffer=(char *)malloc(BUFFER_LENGTH);
+  smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+
+  /* Sending SMTP command to remote smtp server */
+  if (!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+
+  /* Processing SMTP server reply */
+  memset(buffer,0,BUFFER_LENGTH);
+  if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+  /* Look for response code */
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+  if(strcmp(smtpcode,retcode) != 0) {
+#ifdef DEBUG
+    logmessage(buffer);
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+
+  free(buffer);
+  free(smtpcode);
+  return(SOCKET_SUCCESS);
+}
+
+int SMTP_SENDMAIL(char *IP_DST, char *PORT_DST, char *from, char *to,char *subject,char *body,int ctimeout)
+{
+  register int sdesc;
+  int long_inet;
+  struct hostent *ip_serv;
+  struct sockaddr_in adr_serv;
+  struct linger li = { 0 };
+  char *debugmsg;
+  char *buffer;
+  char *smtpcode;
+  char *smtpcmd;
+  struct timeval tv;
+  fd_set rfds, wfds;
+  int rc, flags;
+  int arglen;
+
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  buffer=(char *)malloc(BUFFER_LENGTH);
+  smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+  smtpcmd=(char *)malloc(SMTP_CMD_LENGTH);
+  memset(buffer,0,BUFFER_LENGTH);
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+
+  if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    return(SOCKET_ERROR);
+  }
+
+  /* free the tcp port after closing the socket descriptor */
+  li.l_onoff=1;
+  li.l_linger=0;
+  setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+  long_inet = sizeof(struct sockaddr_in);
+
+  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Can not resolve remote host %s\n",IP_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  memset(&adr_serv,0,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(atoi(PORT_DST));
+
+  /* Set read/write socket timeout */
+  flags=fcntl(sdesc, F_GETFL);
+  fcntl(sdesc, F_SETFL, flags | 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:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ECONNREFUSED:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ENETUNREACH:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case EINPROGRESS: // NONBLOCK socket connection in progress
+        goto next;
+      default:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+    }
+
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+next:
+  /* Timeout settings */
+  tv.tv_sec=ctimeout;
+  tv.tv_usec=0;
+  FD_ZERO(&rfds);
+  FD_ZERO(&wfds);
+  FD_SET(sdesc,&rfds);
+  FD_SET(sdesc,&wfds);
+
+  rc = select(sdesc+1,&rfds,NULL,NULL,&tv);
+  if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Timeout reading data to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  if (rc < 0) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  rc = 0;
+  arglen=sizeof(int);
+  if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+    rc = errno;
+
+  if (rc) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Proceed the SMTP server reply */
+  if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Look for connect code */
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+  if(strcmp(smtpcode,SMTP_CONNECT) != 0) {
+#ifdef DEBUG
+    logmessage("Can not connect remote smtp server.\n");
+#endif
+  }
+
+  /* Sending host identification */
+  memset(buffer,0,BUFFER_LENGTH);
+  if(gethostname(buffer,500)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error resolving local hostname\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending EHLO command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"EHLO %s\n",buffer);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_EHLO)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending MAIL FROM command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"MAIL FROM:%s\n",from);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_MAIL_FROM)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending MAIL FROM.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending RCPT TO command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"RCPT TO:%s\n",to);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_RCPT_TO)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending RCPT TO.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending DATA command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"DATA\n");
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DATA)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending DATA.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending smtp header to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"Subject: %s\nX-Mailer: Keepalived SmtpWrapper\n\n",subject);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp header.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending smtp body to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"\n\n%s\n\n",body);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp body.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending DATA command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"\n.\n");
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DOT)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending trailing DOT.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending quit to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"QUIT\n",body);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp quit.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  close(sdesc);
+  free(debugmsg);
+  free(buffer);
+  return(SOCKET_SUCCESS);
+}
+
+void SMTP_SEND_ALERTES(configuration_data *lstconf,virtualserver *lstvs,char *subject,char *body)
+{
+  char *tmpbuff;
+  char *debugmsg;
+  notification_email *pointeremail;
+
+  tmpbuff=(char *)malloc(500);  
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  memset(tmpbuff,0,500);
+
+  sprintf(tmpbuff,"[%s] %s:%s - %s",lstconf->lvs_id,lstvs->svr->addr_ip,lstvs->svr->addr_port,subject);
+
+  pointeremail=lstconf->email;
+  while(lstconf->email != NULL) {
+    if(!SMTP_SENDMAIL(lstconf->smtp_server,SMTP_PORT,lstconf->email_from,lstconf->email->addr,tmpbuff,body,6)) {
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"SMTP_SEND_ALERTES : Can not send alerte to %s.\n",lstconf->email->addr);
+      logmessage(debugmsg);
+    }
+    lstconf->email=(notification_email *)lstconf->email->next;
+  }
+  lstconf->email=pointeremail;
+
+  free(tmpbuff);
+  free(debugmsg);
+}
diff --git a/smtpwrapper.h b/smtpwrapper.h
new file mode 100644 (file)
index 0000000..b205bdd
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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:        smtpwrapper.c include file.
+ *
+ * Version:     $Id: smtpwrapper.h,v 0.2.6 2001/03/01 $
+ *
+ * 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 SMTPWRAPPER_H
+#define SMTPWRAPPER_H
+
+#include <signal.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "cfreader.h"
+
+#define SOCKET_ERROR   0
+#define SOCKET_SUCCESS 1
+#define SOCKET_TIMEOUT 3
+
+#define SMTP_PORT      "25"
+
+#define SMTP_CONNECT   "220"
+#define SMTP_EHLO      "250"
+#define SMTP_MAIL_FROM "250"
+#define SMTP_RCPT_TO   "250"
+#define SMTP_DATA      "354"
+#define SMTP_DOT       "250"
+
+
+#define LOGBUFFER_LENGTH 100
+#define BUFFER_LENGTH 1024
+#define SMTP_ERROR_CODE_LENGTH 4
+#define SMTP_CMD_LENGTH  500
+
+#endif
diff --git a/smtpwrapper/Makefile b/smtpwrapper/Makefile
new file mode 100644 (file)
index 0000000..304199b
--- /dev/null
@@ -0,0 +1,25 @@
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
+
+EXEC= smtpsend
+CC= gcc
+#CFLAGS= -Wall -Wunused
+CFLAGS= 
+DEFS= main.h smtpwrapper.h
+OBJECTS= main.o smtpwrapper.o utils.o
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:  
+#      $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+       $(CC) -o $@ $(INCLUDE) -DDEBUG -c $*.c
+
+all:   $(EXEC)
+       strip $(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+$(EXEC):       $(OBJECTS) $(DEFS)
+       $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+
+clean:
+       rm -f core *.o $(EXEC) 
diff --git a/smtpwrapper/main.c b/smtpwrapper/main.c
new file mode 100644 (file)
index 0000000..47d2dfc
--- /dev/null
@@ -0,0 +1,33 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project 
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        Main program structure.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.3 2001/01/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:       
+ *         Alexandre Cassen : 2001/01/01 :
+ *          <+> Change the signalhandling.
+ *
+ *          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 "main.h"
+
+int main(int argc, char **argv)
+{
+  printf(PROG" v"VERSION"\n");
+
+  SMTP_SENDMAIL("172.31.47.40","25","keepalived@smsgw.cplusfrn.com","acassen@smsgw.cplusfrn.com","le sujet","Test de body",6);
+
+  return 0;
+}
diff --git a/smtpwrapper/main.h b/smtpwrapper/main.h
new file mode 100644 (file)
index 0000000..1e82a54
--- /dev/null
@@ -0,0 +1,39 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        keepalived.c include file.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.1 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 KEEPALIVED_H
+#define KEEPALIVED_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+
+#include "smtpwrapper.h"
+
+/* Build version */
+#define PROG    "smtpwrapper"
+#define VERSION "0.2.6 (03/01, 2001), Alexandre Cassen"
+
+#endif
diff --git a/smtpwrapper/smtpwrapper.c b/smtpwrapper/smtpwrapper.c
new file mode 100644 (file)
index 0000000..35204e9
--- /dev/null
@@ -0,0 +1,425 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        SMTP WRAPPER connect to a specified smtp server and send mail
+ *              using the smtp protocol according to the RFC 822. A non blocking 
+ *              timeouted connection is used to handle smtp protocol.
+ *  
+ * Version:     $Id: smtpwrapper.c,v 0.2.6 2001/03/01 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *         Alexandre Cassen : 2001/03/01 : 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 "smtpwrapper.h"
+
+int send_to(register int sdesc, fd_set wfds, struct timeval tv, char *buffer)
+{
+  select(sdesc+1,NULL,&wfds,NULL,&tv);
+  if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Timeout writing data to smtp server\n");
+#endif
+    return(SOCKET_ERROR);
+  }
+
+  if (send(sdesc,buffer,strlen(buffer),0) == -1) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Can not send data to remote smtp server\n");
+#endif
+    return(SOCKET_ERROR);
+  }
+
+  return(SOCKET_SUCCESS);
+}
+
+int read_to(register int sdesc, fd_set rfds, struct timeval tv, char *buffer)
+{
+  int rcv_buffer_size=0;
+  long total_length=0;
+  char *buffertmp;
+
+  buffertmp=(char *)malloc(BUFFER_LENGTH);
+  memset(buffertmp,0,BUFFER_LENGTH);
+
+  select(sdesc+1,&rfds,NULL,NULL,&tv);
+  if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Timeout receiving data from smtp server\n");
+#endif
+    free(buffertmp);
+    return(SOCKET_ERROR);
+  }
+
+  while((rcv_buffer_size = read(sdesc,buffertmp,BUFFER_LENGTH)) != 0) {
+    if ( rcv_buffer_size == -1 ) {
+      if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+      logmessage("SMTP_SENDMAIL : Can not recieve data from remote smtp server\n");
+#endif
+      free(buffertmp);
+      return(SOCKET_ERROR);
+    }
+    memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+    memset(buffertmp,0,BUFFER_LENGTH);
+    total_length += rcv_buffer_size;
+  }
+
+end:
+  free(buffertmp);
+  return(SOCKET_SUCCESS);
+}
+
+int smtp_cmd(register int sdesc,fd_set rfds,fd_set wfds,struct timeval tv,char *smtpcmd,char *retcode)
+{
+  char *buffer;
+  char *smtpcode;
+
+  buffer=(char *)malloc(BUFFER_LENGTH);
+  smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+
+  /* Sending SMTP command to remote smtp server */
+  if (!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+
+  /* Processing SMTP server reply */
+  memset(buffer,0,BUFFER_LENGTH);
+  if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+  /* Look for response code */
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+  if(strcmp(smtpcode,retcode) != 0) {
+#ifdef DEBUG
+    logmessage(buffer);
+#endif
+    free(buffer);
+    free(smtpcode);
+    return(SOCKET_ERROR);
+  }
+
+  free(buffer);
+  free(smtpcode);
+  return(SOCKET_SUCCESS);
+}
+
+int SMTP_SENDMAIL(char *IP_DST, char *PORT_DST, char *from, char *to,char *subject,char *body,int ctimeout)
+{
+  register int sdesc;
+  int long_inet;
+  struct hostent *ip_serv;
+  struct sockaddr_in adr_serv;
+  struct linger li = { 0 };
+  char *debugmsg;
+  char *buffer;
+  char *smtpcode;
+  char *smtpcmd;
+  struct timeval tv;
+  fd_set rfds, wfds;
+  int rc, flags;
+  int arglen;
+
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  buffer=(char *)malloc(BUFFER_LENGTH);
+  smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+  smtpcmd=(char *)malloc(SMTP_CMD_LENGTH);
+  memset(buffer,0,BUFFER_LENGTH);
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+
+  if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    return(SOCKET_ERROR);
+  }
+
+  /* free the tcp port after closing the socket descriptor */
+  li.l_onoff=1;
+  li.l_linger=0;
+  setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+  long_inet = sizeof(struct sockaddr_in);
+
+  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Can not resolve remote host %s\n",IP_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  memset(&adr_serv,0,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(atoi(PORT_DST));
+
+  /* Set read/write socket timeout */
+  flags=fcntl(sdesc, F_GETFL);
+  fcntl(sdesc, F_SETFL, flags | 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:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ECONNREFUSED:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ENETUNREACH:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case EINPROGRESS: // NONBLOCK socket connection in progress
+        goto next;
+      default:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"SMTP_SENDMAIL : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+    }
+
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+next:
+  /* Timeout settings */
+  tv.tv_sec=ctimeout;
+  tv.tv_usec=0;
+  FD_ZERO(&rfds);
+  FD_ZERO(&wfds);
+  FD_SET(sdesc,&rfds);
+  FD_SET(sdesc,&wfds);
+
+  rc = select(sdesc+1,&rfds,NULL,NULL,&tv);
+  if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Timeout reading data to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  if (rc < 0) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  rc = 0;
+  arglen=sizeof(int);
+  if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+    rc = errno;
+
+  if (rc) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"SMTP_SENDMAIL : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Proceed the SMTP server reply */
+  if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Look for connect code */
+  memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+  memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+  if(strcmp(smtpcode,SMTP_CONNECT) != 0) {
+#ifdef DEBUG
+    logmessage("Can not connect remote smtp server.\n");
+#endif
+  }
+
+  /* Sending host identification */
+  memset(buffer,0,BUFFER_LENGTH);
+  if(gethostname(buffer,500)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error resolving local hostname\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending EHLO command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"EHLO %s\n",buffer);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_EHLO)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending MAIL FROM command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"MAIL FROM:%s\n",from);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_MAIL_FROM)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending MAIL FROM.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending RCPT TO command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"RCPT TO:%s\n",to);
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_RCPT_TO)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending RCPT TO.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending DATA command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"DATA\n");
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DATA)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending DATA.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending smtp header to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"Subject: %s\nX-Mailer: Keepalived SmtpWrapper\n\n",subject);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp header.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending smtp body to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"\n\n%s\n\n",body);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp body.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending DATA command to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"\n.\n");
+  if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DOT)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending trailing DOT.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  /* Sending quit to remote smtp server */
+  memset(smtpcmd,0,SMTP_CMD_LENGTH);
+  sprintf(smtpcmd,"QUIT\n",body);
+  if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+    logmessage("SMTP_SENDMAIL : Error sending smtp quit.\n");
+#endif
+    free(debugmsg);
+    free(buffer);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  close(sdesc);
+  free(debugmsg);
+  free(buffer);
+  return(SOCKET_SUCCESS);
+}
diff --git a/smtpwrapper/smtpwrapper.h b/smtpwrapper/smtpwrapper.h
new file mode 100644 (file)
index 0000000..c7f24fb
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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:        smtpwrapper.c include file.
+ *
+ * Version:     $Id: smtpwrapper.h,v 0.2.6 2001/03/01 $
+ *
+ * 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 CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define SOCKET_ERROR   0
+#define SOCKET_SUCCESS 1
+#define SOCKET_TIMEOUT 3
+
+#define SMTP_CONNECT   "220"
+#define SMTP_EHLO      "250"
+#define SMTP_MAIL_FROM "250"
+#define SMTP_RCPT_TO   "250"
+#define SMTP_DATA      "354"
+#define SMTP_DOT       "250"
+
+
+#define LOGBUFFER_LENGTH 100
+#define BUFFER_LENGTH 1024
+#define SMTP_ERROR_CODE_LENGTH 4
+#define SMTP_CMD_LENGTH  500
+
+#endif
diff --git a/smtpwrapper/utils.c b/smtpwrapper/utils.c
new file mode 100644 (file)
index 0000000..c0478da
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ *
+ * Part:        General program utils.
+ *
+ * Version:     $Id: utils.c,v 0.2.1 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.
+ */
+
+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;
+      }
+    }
+  }
+}
+
+void logmessage(char *msg)
+{
+  printf("%s",msg);
+}
diff --git a/tcpcheck.c b/tcpcheck.c
new file mode 100644 (file)
index 0000000..7308cff
--- /dev/null
@@ -0,0 +1,183 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        TCP CHECK. Build a TCP/IP packet and send it to a remote
+ *              server. This check implement the tcp half open connection
+ *              check.
+ *  
+ * Version:     $Id: tcpcheck.c,v 0.2.5 2001/02/16 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *              
+ * Changes:     
+ *         Alexandre Cassen : 2001/02/16 :
+ *          <-> Suppress the whole RAW_SOCKET tcpcheck level initial implementation.
+ *          <+> Replace the RAW_SOCKET initial implementation by a vanilla tcpcheck.
+ *              Using non blocking & no_linger socket. Use a timeval to set socket
+ *              descriptor timeout.
+ *
+ *         Alexandre Cassen : 2000/12/29 :
+ *          <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
+ *              Call this function in TCP_RCV_SYNACK_PACKET with 1s timeout.
+ *          <+> Added a timer (2s timeouted) in TCP_RCV_SYNACK_PACKET to check
+ *              SYN|ACK packet. Check perform on tcp sequence, remote tcp port number,
+ *              tcp SYN|ACK flag, remote ip address.
+ *          <+> Added a 3 time SYN packet send retry.
+ *
+ *         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 "tcpcheck.h"
+
+int TCP_CHECK(const char *IP_DST, const char *PORT_DST)
+{
+  register int sdesc;
+  int long_inet;
+  char *debugmsg;
+  struct hostent *ip_serv;
+  struct sockaddr_in adr_serv;
+  struct linger li = { 0 };
+  struct timeval tv;
+  fd_set wfds;
+  int rc, val;
+  int arglen;
+
+  /* Memory allocation for the data structures */
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+
+  if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    return(SOCKET_ERROR);
+  }
+
+  /* free the tcp port after closing the socket descriptor */
+  li.l_onoff=1;
+  li.l_linger=0;
+  setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+  long_inet = sizeof(struct sockaddr_in);
+
+  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Can not resolve remote host %s\n",IP_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  memset(&adr_serv,0,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(atoi(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:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"TCP_CHECK : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ECONNREFUSED:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"TCP_CHECK : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case ENETUNREACH:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"TCP_CHECK : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+        break;
+      case EINPROGRESS: // NONBLOCK socket connection in progress
+        goto next;
+      default:
+#ifdef DEBUG
+        memset(debugmsg,0,LOGBUFFER_LENGTH);
+        sprintf(debugmsg,"TCP_CHECK : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+        logmessage(debugmsg);
+#endif
+    }
+
+    free(debugmsg);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+next:
+  /* Timeout settings */
+  tv.tv_sec=SOCKET_TIMEOUT;
+  tv.tv_usec=0;
+  FD_ZERO(&wfds);
+  FD_SET(sdesc,&wfds);
+
+  rc = select(sdesc+1,NULL,&wfds,NULL,&tv);
+  if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Timeout writing data to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  if (rc < 0) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  rc = 0;
+  arglen=sizeof(int);
+  if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+    rc = errno;
+
+  if (rc) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+    logmessage(debugmsg);
+#endif
+    free(debugmsg);
+    close(sdesc);
+    return(SOCKET_ERROR);
+  }
+
+  free(debugmsg);
+  return(SOCKET_SUCCESS);
+}
similarity index 75%
rename from keepalived/tcpcheck.h
rename to tcpcheck.h
index 8c3384e..0ca936c 100644 (file)
 #include <sys/time.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <fcntl.h>
+#include <errno.h>
 
 #define SOCKET_ERROR   0
 #define SOCKET_SUCCESS 1
-#define STCP           1111
+#define SOCKET_TIMEOUT 3
 
 #define LOGBUFFER_LENGTH 100
-#define SYNPACKET_LENGTH 1024
-#define HOSTNAME_LENGTH  30
-
-#define NB_RETRY 3
-
-/* Structures used */
-struct tcphdr_pseudo {
-  unsigned int saddr;
-  unsigned int daddr;
-  unsigned char zero;
-  unsigned char proto;
-  unsigned short tcplen;
-  struct tcphdr tcp;
-};
-
-/* prototypes */
-int TCP_CHECK(char *IP_SRC, char *IP_DST, char *PORT_DST);
 
 #endif
similarity index 83%
rename from keepalived/utils.c
rename to utils.c
index 719670c..967eea8 100644 (file)
+++ b/utils.c
@@ -5,12 +5,15 @@
  *
  * Part:        General program utils.
  *
- * Version:     $Id: utils.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: utils.c,v 0.2.6 2001/03/01 $
  *
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *
  * Changes:
- *              Alexandre Cassen      :       Initial release
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Adding daemonpid var to stock running keepalived daemon pid.
+ *
+ *              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
@@ -58,7 +61,12 @@ void print_buffer(int count, char *buff)
   }
 }
 
-void logmessage(char *msg,int idevent)
+void initdaemonpid(int pid)
+{
+  daemonpid=pid;
+}
+
+void logmessage(char *msg)
 {
   FILE *logfile;
   time_t hint;
@@ -75,6 +83,6 @@ void logmessage(char *msg,int idevent)
                   date->tm_hour,
                   date->tm_min,
                   date->tm_sec,
-                  idevent,msg);
+                  daemonpid,msg);
   fclose(logfile);
 }
diff --git a/utils.h b/utils.h
new file mode 100644 (file)
index 0000000..d5d1ad8
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,42 @@
+/*
+ * 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.c include file.
+ *
+ * Version:     $Id: utils.h,v 0.2.6 2001/03/09 $
+ *
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ *              Alexandre Cassen : 2001/03/01 :
+ *               <+> Adding global daemon pid var.
+ *
+ *              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.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <string.h>
+
+#define LOGFILE       "log/keepalived.log"
+
+/* Globals defs */
+int daemonpid;
+
+#endif