keepalived-0.2.1 v0.2.1
authorAlexandre Cassen <acassen@freebox.fr>
Sat, 23 Dec 2000 00:09:48 +0000 (01:09 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:52 +0000 (10:58 +0200)
24 files changed:
genhash/Makefile [new file with mode: 0644]
genhash/genhash.c [new file with mode: 0644]
genhash/genhash.h [new file with mode: 0644]
keepalived/Makefile [new file with mode: 0644]
keepalived/cfreader.c [new file with mode: 0644]
keepalived/cfreader.h [new file with mode: 0644]
keepalived/etc/keepalived/keepalived.conf [new file with mode: 0644]
keepalived/etc/keepalived/log/keepalived.log [new file with mode: 0644]
keepalived/etc/lvs.conf [new file with mode: 0644]
keepalived/httpget.c [new file with mode: 0644]
keepalived/httpget.h [new file with mode: 0644]
keepalived/icmpcheck.c [new file with mode: 0644]
keepalived/icmpcheck.h [new file with mode: 0644]
keepalived/iputils.c [new file with mode: 0644]
keepalived/iputils.h [new file with mode: 0644]
keepalived/ipvswrapper.c [new file with mode: 0644]
keepalived/ipvswrapper.h [new file with mode: 0644]
keepalived/keepalived.c [new file with mode: 0644]
keepalived/keepalived.h [new file with mode: 0644]
keepalived/tcpcheck.c [new file with mode: 0644]
keepalived/tcpcheck.h [new file with mode: 0644]
keepalived/utils.c [new file with mode: 0644]
keepalived/utils.h [new file with mode: 0644]
libmd-0.3 [new file with mode: 0644]

diff --git a/genhash/Makefile b/genhash/Makefile
new file mode 100644 (file)
index 0000000..000c444
--- /dev/null
@@ -0,0 +1,24 @@
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@canal-plus.com>
+
+EXEC= genhash
+CC= gcc
+CFLAGS= -Wall -lmd
+DEFS= genhash.h
+OBJECTS= genhash.o
+.c.o:  
+       $(CC) -o $@ $(CFLAGS) -c $*.c
+
+all:   $(EXEC)
+       strip $(EXEC)
+       @echo ""
+       @echo "Make complete"
+
+$(EXEC):       $(OBJECTS) $(DEFS)
+       $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+
+clean:
+       rm -f core *.o $(EXEC) 
+
+install:
+       cp -av genhash /usr/bin/
diff --git a/genhash/genhash.c b/genhash/genhash.c
new file mode 100644 (file)
index 0000000..c1b6a9e
--- /dev/null
@@ -0,0 +1,161 @@
+/* 
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for the 
+ *              HTTP_GET_CHECK.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.0 2000/12/09 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ *              Alexandre Cassen      :       Initial release
+ *               
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */     
+
+#include "genhash.h"
+
+void print_buffer(int count, char *buff)
+{
+  int i,j,c;
+  int printnext=1;
+
+  if(count) {
+    if(count%16)
+      c=count+(16-count%16);
+    else c=count;
+  } else
+    c=count;
+
+  for(i=0;i<c;i++) {
+    if(printnext) { 
+      printnext--;
+      printf("%.4x ",i&0xffff);
+    }
+    if(i<count)
+      printf("%3.2x",buff[i]&0xff);
+    else
+      printf("   ");
+    if(!((i+1)%8)) {
+      if((i+1)%16)
+        printf(" -");
+      else {
+        printf("   ");
+        for(j=i-15;j<=i;j++)
+          if(j<count) {
+            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
+              printf("%c",buff[j]&0xff);
+            else printf(".");
+          } else printf(" ");
+        printf("\n"); printnext=1;
+      }
+    }
+  }
+}
+
+int new_sock(int type)
+{
+  int sd;
+  struct sockaddr_in adr_local;
+  if ( (sd = socket(AF_INET, type, 0)) == -1 ) return (-1);
+
+  bzero(&adr_local, sizeof(struct sockaddr_in));
+  adr_local.sin_family = AF_INET;
+  adr_local.sin_port = htons(0);
+  adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
+
+  if ( bind(sd, (struct sockaddr *)&adr_local, sizeof(struct sockaddr_in)) ) return (-1);
+
+  return (sd);
+}
+
+int HTTP_GET(char *IP_DST, unsigned short int PORT_DST, char *URL, char *buffer)
+{
+  register int sdesc;
+  int long_inet;
+  int rcv_buffer_size=0;
+  char *str_request;
+  struct hostent *ip_serv;
+  struct sockaddr_in adr_serv;
+  str_request=(char *)malloc(GET_BUFFER_LENGTH);
+  strcpy(str_request,"GET ");
+  strcat(str_request,URL);
+  strcat(str_request,"\n");
+
+  if ( (sdesc=new_sock(SOCK_STREAM)) == -1 ) {
+    printf("Can not bind remote address\n");
+    return(ERROR_SOCKET);
+  }
+
+  long_inet = sizeof(struct sockaddr_in);
+
+  if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+    printf("Can not resolve remote host\n");
+    return(ERROR_SOCKET);
+  }
+
+  bzero(&adr_serv,long_inet);
+  adr_serv.sin_family=ip_serv->h_addrtype;
+  bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+  adr_serv.sin_port=htons(PORT_DST);
+
+  if ( connect(sdesc, (struct sockaddr *)&adr_serv, long_inet) == -1) {
+    printf("Can not connect remote host\n");
+    return(ERROR_SOCKET);
+  }
+
+  if (send(sdesc,str_request,strlen(str_request),0) == -1) {
+    printf("Can not send data to remote host\n");
+    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");
+    return(ERROR_SOCKET);
+  }
+
+  close(sdesc);
+  free(str_request);
+  return(rcv_buffer_size);
+}
+
+int main(int argc, char **argv)
+{
+  char *buffer_http;
+  int retcode=0;
+  char MDResult[0x40];
+
+  printf(PROG" v"VERSION"\n");
+  if (argc < 4) {
+      printf("Usage: %s <IP address> <TCP port> <url path>\n", argv[0]);
+      return 0;
+  }
+
+  buffer_http=(char *)malloc(RCV_BUFFER_LENGTH);
+
+  retcode=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
+
+  if(retcode > 0) {
+    printf("\n----[ Buffer Text representation ]----\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("\n----[ MD5 resulting ]----\n");
+    MD5Data(buffer_http,retcode,MDResult);
+    printf("MD5 256 bits Digest : %s\n",MDResult);
+  } else {
+    printf("No buffer returned...\n");
+  }
+
+  free(buffer_http);
+  return 1;
+}
diff --git a/genhash/genhash.h b/genhash/genhash.h
new file mode 100644 (file)
index 0000000..666abea
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Soft:        Genhash compute MD5 digest from a HTTP get result. This
+ *              program is use to compute hash value that you will add
+ *              into the /etc/keepalived/keepalived.conf for the 
+ *              HTTP_GET_CHECK.
+ *
+ * Part:        genhash.c include file.
+ *  
+ * Version:     $Id: keepalived.c,v 0.2.0 2000/12/09 $
+ * 
+ * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ *              Alexandre Cassen      :       Initial release
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ */     
+
+#ifndef GENHASH_H
+#define GENHASH_H
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <linux/if_ether.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <md5.h>
+
+/* Sockets connection errors codes */
+#define ERROR_SOCKET        0
+
+/* Data buffer length description */
+#define GET_BUFFER_LENGTH   80
+#define RCV_BUFFER_LENGTH   1024
+
+/* Build version */
+#define PROG    "genhash"
+#define VERSION "0.2.0 (12/09, 2000), Alexandre Cassen"
+
+#endif
diff --git a/keepalived/Makefile b/keepalived/Makefile
new file mode 100644 (file)
index 0000000..20d0125
--- /dev/null
@@ -0,0 +1,29 @@
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@canal-plus.com>
+
+EXEC= keepalived
+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
+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) 
+
+install:
+       cp -av keepalived /usr/sbin/
+       cp -av etc/* /etc/
diff --git a/keepalived/cfreader.c b/keepalived/cfreader.c
new file mode 100644 (file)
index 0000000..c81f8ce
--- /dev/null
@@ -0,0 +1,287 @@
+/* 
+ * 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: 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.
+ */
+
+#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) {
+      bzero(tempbuff,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) {
+        bzero(tempbuff,TEMPBUFFERLENGTH);
+        sprintf(tempbuff," -> SVR IP = %s, Port = %s\n",lstptr->svr->addr_ip,lstptr->svr->addr_port);
+        logmessage(tempbuff,getpid());
+
+        bzero(tempbuff,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());
+
+        bzero(tempbuff,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
new file mode 100644 (file)
index 0000000..ab4c3cd
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+ * 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: 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 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
new file mode 100644 (file)
index 0000000..6a7375b
--- /dev/null
@@ -0,0 +1,62 @@
+# 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/keepalived/log/keepalived.log b/keepalived/etc/keepalived/log/keepalived.log
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/keepalived/etc/lvs.conf b/keepalived/etc/lvs.conf
new file mode 100644 (file)
index 0000000..e4609fe
--- /dev/null
@@ -0,0 +1,12 @@
+# 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
new file mode 100644 (file)
index 0000000..cc36fdc
--- /dev/null
@@ -0,0 +1,144 @@
+/* 
+ * 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: 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.
+ */
+
+#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);
+  }
+
+  bzero(&adr_serv,long_inet);
+  adr_serv.sin_family=ip_serv->h_addrtype;
+  bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+  adr_serv.sin_port=htons(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);
+  bzero(bufferget,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/httpget.h b/keepalived/httpget.h
new file mode 100644 (file)
index 0000000..e6e316a
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        httpget.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 HTTPGET_H
+#define HTTPGET_H
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/ip_icmp.h>
+#include <linux/if_ether.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <md5.h>
+
+#define SOCKET_ERROR   0
+#define SOCKET_SUCCESS 1
+
+#define MD5_BUFFER_LENGTH 32
+#define GET_REQUEST_BUFFER_LENGTH 128
+#define GET_BUFFER_LENGTH 2048
+#define LOGBUFFER_LENGTH 100
+
+/* prototypes */
+int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x40]);
+
+#endif
diff --git a/keepalived/icmpcheck.c b/keepalived/icmpcheck.c
new file mode 100644 (file)
index 0000000..64da749
--- /dev/null
@@ -0,0 +1,186 @@
+/* 
+ * 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:        ICMP CHECK. Build an ICMP packet and send it to a remote
+ *              server.
+ *  
+ * 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.
+ */
+
+#include "icmpcheck.h"
+
+int recvfrom_wto(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/100000;
+  to.tv_usec = (timo - (to.tv_sec*100000))*10;
+
+  FD_ZERO(&readset);
+  FD_ZERO(&writeset);
+  FD_SET(s,&readset);
+  nfound = select(s+1,&readset,&writeset,NULL,&to);
+  if (nfound<0) { 
+    //printf("select failed !!!\n"); 
+    return(-1);
+  }
+  if (nfound==0) return -1;  /* timeout */
+  slen=sizeof(struct sockaddr);
+  n=recvfrom(s,buf,len,0,saddr,&slen);
+  if (n<0) return -1; // printf("Error recvfrom");
+  return n;
+}
+
+int ICMP_CHECK(char dst_ip[16])
+{
+  struct iphdr *ipHdr;
+  struct icmphdr *icmpHdr;
+  struct sockaddr_in addr ;
+  struct sockaddr_in response_addr ;
+  struct ip *ip;
+  struct icmp *icp;
+  unsigned char *sendbuff;
+  unsigned char *recvbuff;
+  char *debugmsg;
+  char on = 1;
+  int hlen;
+  int result;
+  int sockfd;
+       
+  unsigned long tmp;
+
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);   
+  sendbuff = (unsigned char *)malloc(BUFFSIZE);
+
+  bzero(sendbuff,BUFFSIZE);
+       
+  if( (sockfd = socket( AF_INET , SOCK_RAW , IPPROTO_ICMP )) < 0 ) {
+    free(debugmsg);
+    free(sendbuff);
+    return(0);
+  }
+       
+  if( setsockopt(sockfd , IPPROTO_IP , IP_HDRINCL , &on , sizeof(on)) < 0 ) {
+    free(debugmsg);
+    free(sendbuff);
+    close(sockfd);
+    return(0);
+  }
+
+  ipHdr = (struct iphdr *)sendbuff;
+
+  ipHdr->ihl = 5;                       /* No options Feild */
+  ipHdr->version = 0x4;
+  ipHdr->tos =  0 ;                    /* Low Delay */
+  ipHdr->tot_len = sizeof(struct iphdr) + sizeof( struct icmphdr );
+  ipHdr->id = htons( getpid() );
+  ipHdr->frag_off = 0;
+  ipHdr->ttl = 30;                     /* 30 Hops max */
+  ipHdr->protocol = IPPROTO_ICMP;
+  ipHdr->check = 0 ;
+
+  if( hostToaddr(dst_ip, &tmp) < 0 ) {
+    // perror("Host to addr conversion failed!");
+    close(sockfd);
+    free(sendbuff);
+    free(debugmsg);
+    return(0);
+  }
+
+  ipHdr->daddr = tmp;
+  ipHdr->check = in_cksum( (unsigned short *)ipHdr , sizeof(struct iphdr) );
+  icmpHdr = (struct icmphdr *)( sendbuff + sizeof(struct iphdr) );
+  icmpHdr->type = ICMP_ECHO;
+  icmpHdr->code = 0;
+  icmpHdr->un.echo.id = getpid();
+  icmpHdr->un.echo.sequence = getpid();
+  icmpHdr->checksum = in_cksum( (unsigned short *)icmpHdr , sizeof(struct icmphdr) );
+
+  bzero( (char *)&addr, sizeof(addr) );
+  addr.sin_addr.s_addr = ipHdr->daddr;
+  addr.sin_family = AF_INET;
+
+  /* Add the icmp data part */
+  bcopy(ICMP_DATA,sendbuff+HDRBUFFSIZE,sizeof(ICMP_DATA));
+       
+  if( sendto(sockfd, sendbuff , sizeof(struct iphdr)+sizeof(struct icmphdr) , 0 , (struct sockaddr *)&addr , sizeof(addr)) < 0 ) {
+    //perror("SendTo Error:");
+    close(sockfd);
+    free(sendbuff);
+    free(debugmsg);
+    return(0);
+  }
+
+  /* Handle arp request */
+  sleep(DELAY_TIME);
+
+  /* Echo reply test */
+  recvbuff=(char *)malloc(BUFFSIZE);
+  bzero((char *)recvbuff,BUFFSIZE);
+
+  result=recvfrom_wto(sockfd,recvbuff,BUFFSIZE,(struct sockaddr *)&response_addr,select_time);
+
+#ifdef DEBUG
+  if (result<0) { 
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"ICMP_CHECK : icmp timeout to %s...\n",dst_ip);
+    logmessage(debugmsg,getpid());
+  }
+#endif
+
+  ip = (struct ip *)recvbuff;
+
+  hlen = ip->ip_hl << 2;
+
+  if (result < hlen+ICMP_MINLEN) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"ICMP_CHECK : Received packet too short according to ICMP protocol to %s...\n",dst_ip);
+    logmessage(debugmsg,getpid());
+#endif
+    close(sockfd);
+    free(sendbuff);
+    free(debugmsg);
+    return(0);
+  }
+
+  icp = (struct icmp *)(recvbuff + hlen);
+  if (icp->icmp_type != ICMP_ECHOREPLY) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"ICMP_CHECK : ICMP ECHO REPLY not received from %s !!!\n",dst_ip);
+    logmessage(debugmsg,getpid());
+#endif
+    close(sockfd);
+    free(sendbuff);
+    free(debugmsg);
+    return(0);
+  } else {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"ICMP_CHECK : ICMP ECHO REPLY recived from %s...\n",dst_ip);
+    logmessage(debugmsg,getpid());
+#endif
+  }
+
+  free(sendbuff);
+  free(recvbuff);
+  free(debugmsg);
+
+  close(sockfd);
+  return(1);
+}
diff --git a/keepalived/icmpcheck.h b/keepalived/icmpcheck.h
new file mode 100644 (file)
index 0000000..df862f8
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+ * 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:        icmpcheck.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 ICMPCHECK_H
+#define ICMPCHECK_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#define ICMP_DATA "KeepAlive for LVS v1.0"
+
+#define HDRBUFFSIZE (sizeof(struct icmphdr) + sizeof(struct iphdr))
+#define BUFFSIZE (HDRBUFFSIZE + sizeof(ICMP_DATA))
+
+#define DEFAULT_SELECT_TIME 10
+#define ICMP_MINLEN 8
+#define SIZE_ICMP_HDR ICMP_MINLEN
+
+#define DELAY_TIME 1
+
+#define LOGBUFFER_LENGTH 100
+
+#define select_time (DEFAULT_SELECT_TIME * 100)
+
+/* prototypes  */
+int ICMP_CHECK(char dst_ip[16]);
+
+#endif
diff --git a/keepalived/iputils.c b/keepalived/iputils.c
new file mode 100644 (file)
index 0000000..fc35555
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        IP packets Utilities.
+ *  
+ * 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.
+ */
+
+#include "iputils.h"
+
+int in_cksum(register unsigned short *ptr , int nbytes)
+{
+  register long sum;
+  u_short oddbyte;
+  register u_short answer;
+
+  sum = 0;
+  while (nbytes > 1)  {
+    sum += *ptr++;
+    nbytes -= 2;
+  }
+
+  /* mop up an odd byte, if necessary */
+  if (nbytes == 1) {
+    oddbyte = 0;                                /* make sure top half is zero */
+    *((u_char *) &oddbyte) = *(u_char *)ptr;    /* one byte only */
+    sum += oddbyte;
+  }
+
+  /* Add back carry outs from top 16 bits to low 16 bits. */
+  sum  = (sum >> 16) + (sum & 0xffff);  /* add high-16 to low-16 */
+  sum += (sum >> 16);                   /* add carry */
+  answer = ~sum;                        /* ones-complement, then truncate to 16 bits */
+  return(answer);
+}
+
+int hostToaddr(char *host, u_long *val)
+{
+  long in_addr ;
+  struct hostent *hp;
+
+  if( (in_addr = inet_addr(host)) != -1 ) {
+    *val = in_addr;
+    return 0;
+  } else {
+    while( (hp=gethostbyname(host)) == (struct hostent *)0 ) {
+      if( h_errno == HOST_NOT_FOUND ) {
+        return -1;
+      }
+      if( h_errno == TRY_AGAIN ) {
+        continue;
+      }
+      if( h_errno == NO_ADDRESS ) {
+        return -1;
+      }
+    }
+    bcopy( (const void *)hp->h_addr , (void *)val , hp->h_length );
+    return 0;
+  }
+}
diff --git a/keepalived/iputils.h b/keepalived/iputils.h
new file mode 100644 (file)
index 0000000..afd2928
--- /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:        iputils.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 IPUTILS_H
+#define IPUTILS_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netinet/in.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
diff --git a/keepalived/ipvswrapper.c b/keepalived/ipvswrapper.c
new file mode 100644 (file)
index 0000000..97e8780
--- /dev/null
@@ -0,0 +1,110 @@
+/* 
+ * Soft:        Keepalived is a failover program for the LVS project
+ *              <www.linuxvirtualserver.org>. It monitor & manipulate
+ *              a loadbalanced server pool using multi-layer checks.
+ * 
+ * Part:        IPVS Kernel wrapper. Use setsockopt call to add/remove
+ *              server to/from the loadbalanced server pool.
+ *  
+ * Version:     $Id: 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.
+ */
+
+#include "ipvswrapper.h"
+
+int ipvs_pool_cmd(int cmd, virtualserver *vserver)
+{
+  struct ip_masq_ctl ctl;
+  struct in_addr inaddr;
+  char *debugmsg;
+  int result=0;
+  int sockfd;
+
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  memset(&ctl,0, sizeof(struct ip_masq_ctl));
+
+  ctl.m_target = IP_MASQ_TARGET_VS;
+  ctl.m_cmd = (cmd)?IP_MASQ_CMD_ADD_DEST:IP_MASQ_CMD_DEL_DEST;
+  strcpy(ctl.m_tname,vserver->sched);
+
+  ctl.u.vs_user.weight = atoi(vserver->svr->weight);
+  
+  if (strcmp(vserver->svr->loadbalancing_kind,"NAT")==0)
+    ctl.u.vs_user.masq_flags = 0;
+  else
+    if (strcmp(vserver->svr->loadbalancing_kind,"DR")==0)
+      ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_DROUTE;
+    else
+      if (strcmp(vserver->svr->loadbalancing_kind,"TUN")==0)
+        ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_TUNNEL;
+      else {
+        bzero(debugmsg,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());
+        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.vfwmark  = 0;
+  ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
+  
+  if (inet_aton(vserver->addr_ip,&inaddr) != 0)
+    ctl.u.vs_user.vaddr = inaddr.s_addr;
+  if (inet_aton(vserver->svr->addr_ip,&inaddr) != 0)
+    ctl.u.vs_user.daddr = inaddr.s_addr;
+  ctl.u.vs_user.vport = htons(atoi(vserver->addr_port));
+  ctl.u.vs_user.dport = htons(atoi(vserver->svr->addr_port));
+
+  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());
+#endif
+    free(debugmsg);
+    return IPVS_ERROR;
+  }
+
+  result = setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *)&ctl, sizeof(ctl));
+
+  if (errno == ESRCH) {
+#ifdef DEBUG
+    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());
+#endif
+    close(sockfd);
+    free(debugmsg);
+    return IPVS_ERROR;
+  } else if (errno == ENOENT) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"ipvs_pool_cmd : No such destination %s\n",vserver->svr->addr_ip);
+    logmessage(debugmsg,getpid());
+#endif
+    close(sockfd);
+    free(debugmsg);
+    return IPVS_ERROR;
+  }
+
+  close(sockfd);
+  free(debugmsg);
+  return IPVS_SUCCESS;
+}
diff --git a/keepalived/ipvswrapper.h b/keepalived/ipvswrapper.h
new file mode 100644 (file)
index 0000000..ba56baf
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+ * 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:        ipvswrapper.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 IPVSWRAPPER_H
+#define IPVSWRAPPER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <arpa/inet.h>
+
+#include <asm/types.h>
+#include <net/if.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
+#include <net/ip_masq.h>
+#include <net/ip_vs.h>
+
+#include "cfreader.h"
+
+#define IPVS_ERROR   0
+#define IPVS_SUCCESS 1
+
+#define IPVS_CMD_DEL 0
+#define IPVS_CMD_ADD 1
+
+#define LOGBUFFER_LENGTH 100
+
+/* prototypes */
+int ipvs_pool_cmd(int cmd, virtualserver *vserver);
+
+#endif
diff --git a/keepalived/keepalived.c b/keepalived/keepalived.c
new file mode 100644 (file)
index 0000000..856d96e
--- /dev/null
@@ -0,0 +1,217 @@
+/* 
+ * 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.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 "keepalived.h"
+
+int main(int argc, char **argv)
+{
+  printf(PROG" v"VERSION"\n");
+
+  if (chdir(CONF_HOME_DIR)) {
+    fprintf(stderr,"%s: ",CONF_HOME_DIR);
+    perror(NULL);
+    exit(1);
+  }
+
+  logmessage("Starting keepalived daemon\n",getpid());
+
+  switch (fork()) {
+    case -1:
+      perror("fork()");
+      exit(3);
+    case 0:
+      close(STDIN_FILENO);
+      close(STDOUT_FILENO);
+      close(STDERR_FILENO);
+      if (setsid() == -1) exit(4);
+      break;
+    default:
+      return 0;
+  }
+
+  if (signal(SIGTERM,sig_handler) == SIG_IGN)
+    signal(SIGTERM,SIG_IGN);
+
+  signal(SIGINT,sig_handler);
+  signal(SIGHUP,sig_handler);
+
+  if ((lstVS=(virtualserver *)ConfReader(lstVS,delay_loop))==NULL) {
+    logmessage("Config file contain no data\n",getpid());
+    exit(0);
+  }
+
+  if (!init_services(lstVS)) {
+    logmessage("Ending keepalived daemon\n",getpid());
+    return 0;
+  }
+
+  logmessage("Using LVS dynamic data representation :\n",getpid());
+  PrintLst(lstVS);
+
+  while (keep_going) {
+    perform_checks(lstVS);
+/*    sleep(delay_loop); */
+    sleep(60);
+  }
+
+  return 0;
+}
+
+void sig_handler(int signum)
+{
+  keep_going=0;
+  ClearLst(lstVS);
+  logmessage("Ending keepalived daemon\n",getpid());
+  signal(signum,sig_handler);
+}
+
+void perform_ipvs(int alive, virtualserver *lstptr)
+{
+  char *logbuffer;
+  
+  logbuffer=(char *)malloc(LOGBUFFER_LENGTH);
+
+  if (!lstptr->svr->alive && alive) {
+    lstptr->svr->alive=alive;
+    memset(logbuffer,0,LOGBUFFER_LENGTH);
+    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());
+    ipvs_pool_cmd(IPVS_CMD_ADD,lstptr);
+  } else {
+    lstptr->svr->alive=alive;
+    memset(logbuffer,0,LOGBUFFER_LENGTH);
+    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());
+    ipvs_pool_cmd(IPVS_CMD_DEL,lstptr);
+  }
+  free(logbuffer);
+}
+
+int init_services(virtualserver *lstptr)
+{
+  realserver *pointersvr;
+
+  while(lstptr != NULL) {
+    pointersvr=lstptr->svr;
+    while(lstptr->svr != NULL) {
+      if (!ipvs_pool_cmd(IPVS_CMD_ADD,lstptr))
+        return 0;
+      lstptr->svr=(realserver *)lstptr->svr->next;
+    }
+    lstptr->svr=pointersvr;
+    lstptr=(virtualserver *)lstptr->next;
+  }
+  return 1;
+}
+
+void perform_checks(virtualserver * lstptr)
+{
+  char MD5Result[0x40];
+  realserver *pointersvr;
+  char *logbuffer;
+
+  logbuffer=(char *)malloc(LOGBUFFER_LENGTH);
+
+  while(lstptr != NULL) {
+    pointersvr=lstptr->svr;
+    while(lstptr->svr != NULL) {
+
+      if (strcmp(lstptr->svr->keepalive_method,"ICMP_CHECK") == 0) {
+        if (ICMP_CHECK(lstptr->svr->addr_ip)) {
+          if (!lstptr->svr->alive) {
+            memset(logbuffer,0,LOGBUFFER_LENGTH);
+            sprintf(logbuffer,"ICMP check succeed to %s.\n",lstptr->svr->addr_ip);
+            logmessage(logbuffer,getpid());
+            perform_ipvs(1,lstptr);
+          }
+        } else {
+          if (lstptr->svr->alive) {
+            memset(logbuffer,0,LOGBUFFER_LENGTH);
+            sprintf(logbuffer,"ICMP check failed to %s.\n",lstptr->svr->addr_ip);
+            logmessage(logbuffer,getpid());
+            perform_ipvs(0,lstptr);
+          }
+        }
+      }
+
+      if (strcmp(lstptr->svr->keepalive_method,"TCP_CHECK") == 0) {
+        if (TCP_CHECK(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port)) {
+          logmessage("TCP check succeed\n",getpid());
+          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());
+            perform_ipvs(1,lstptr);
+          }
+        } else {
+          logmessage("TCP check failed\n",getpid());
+          if (lstptr->svr->alive) {
+            bzero(logbuffer,LOGBUFFER_LENGTH);
+            sprintf(logbuffer,"TCP check failed to %s:%s.\n",lstptr->svr->addr_ip,
+                                                             lstptr->svr->addr_port);
+            logmessage(logbuffer,getpid());
+            perform_ipvs(0,lstptr);
+          }
+        }
+      }
+
+      if (strcmp(lstptr->svr->keepalive_method,"HTTP_GET") == 0) {
+
+        if(HTTP_GET(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port,
+                 lstptr->svr->keepalive_url,MD5Result)) {
+
+          if (strcmp(lstptr->svr->keepalive_result,MD5Result) == 0) {
+            logmessage("HTTP GET check succeed\n",getpid());
+            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());
+              perform_ipvs(1,lstptr);
+            }
+          } else {
+            logmessage("HTTP GET check failed\n",getpid());
+            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());
+              perform_ipvs(0,lstptr);
+            }
+          }
+        } else {
+          if(lstptr->svr->alive) {
+            perform_ipvs(0,lstptr);
+          }
+        }
+
+      }
+      lstptr->svr=(realserver *)lstptr->svr->next;
+    }
+    lstptr->svr=pointersvr;
+    lstptr=(virtualserver *)lstptr->next;
+  }
+  free(logbuffer);
+}
diff --git a/keepalived/keepalived.h b/keepalived/keepalived.h
new file mode 100644 (file)
index 0000000..891acfd
--- /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:        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"
+#include "icmpcheck.h"
+#include "tcpcheck.h"
+#include "httpget.h"
+#include "utils.h"
+#include "ipvswrapper.h"
+
+#define LOGBUFFER_LENGTH 100
+
+/* Configuration file home directory */
+#define CONF_HOME_DIR "/etc/keepalived/"
+
+/* Sockets connection errors codes */
+#define ERROR_SOCKET        0
+
+/* Global variables */
+volatile sig_atomic_t keep_going = 1;
+virtualserver *lstVS;
+int delay_loop = 5;
+
+/* Build version */
+#define PROG    "keepalived"
+#define VERSION "0.2.1 (12/23, 2000), Alexandre Cassen"
+
+/* prototypes */
+void sig_handler(int signum);
+void perform_checks(virtualserver * lstptr);
+int init_services(virtualserver *lstptr);
+
+#endif
diff --git a/keepalived/tcpcheck.c b/keepalived/tcpcheck.c
new file mode 100644 (file)
index 0000000..3db0b85
--- /dev/null
@@ -0,0 +1,202 @@
+/* 
+ * 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: 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.
+ */
+
+#include "tcpcheck.h"
+
+#define SEQUENCE 0x28376839
+
+int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG)
+{
+  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 dest;
+  char *packet;
+
+  /* Packet pointer affectation */
+  packet=(char *)malloc(SYNPACKET_LENGTH);
+  bzero(packet,SYNPACKET_LENGTH);
+  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     = htonl(SEQUENCE);
+  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 */
+  dest.sa_family = AF_INET;
+  bcopy(&packet_ip->daddr,&dest.sa_data[2],4);
+  bcopy(&packet_tcp->source,&dest.sa_data[0],2);
+
+  if (sendto(rawsock,packet,sizeof(struct iphdr) + sizeof(struct tcphdr),
+             0,&dest,sizeof(dest)) < 0) {
+    close(rawsock);
+    free(packet);
+    return(SOCKET_ERROR);
+  }
+  free(packet);
+  return(SOCKET_SUCCESS);
+}
+
+int TCP_RCV_SYNACK_PACKET()
+{
+  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 dest;
+  char *packet;
+  int fromlen=0;
+
+  fromlen=sizeof(struct sockaddr);
+
+  /* Packet pointer affectation */
+  packet=(char *)malloc(SYNPACKET_LENGTH);
+  bzero(packet,SYNPACKET_LENGTH);
+  packet_ip=(struct iphdr *)packet;
+  packet_tcp=(struct tcphdr *)(packet_ip+1);
+
+  if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -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));
+
+  if (recvfrom(rawsock,packet,SYNPACKET_LENGTH,
+               0,(struct sockaddr *)&dest,&fromlen) < 0) {
+    free(packet);
+    close(rawsock);
+    return(SOCKET_ERROR);
+  }
+
+  close(rawsock);
+
+  if ( packet_tcp->syn && packet_tcp->ack) {
+    free(packet);
+    return(SOCKET_SUCCESS);
+  } else {
+    free(packet);
+    return(SOCKET_ERROR);
+  }
+}
+
+int TCP_CHECK(char *IP_SRC, char *IP_DST, char *PORT_DST)
+{
+  register int tcpsock;
+  char *debugmsg;
+
+  /* Memory allocation for the data structures */
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+  bzero(debugmsg,LOGBUFFER_LENGTH);
+
+  if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"SYN")) {
+#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()) {
+#ifdef DEBUG
+    memset(debugmsg,0,LOGBUFFER_LENGTH);
+    sprintf(debugmsg,"TCP_CHECK : Didn't recieve SYN response from [%s:%s]\n",IP_DST,PORT_DST);
+    logmessage(debugmsg,getpid());
+#endif
+    free(debugmsg);
+    return(SOCKET_ERROR);
+  }
+
+  if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"RST ACK")) {
+#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/keepalived/tcpcheck.h b/keepalived/tcpcheck.h
new file mode 100644 (file)
index 0000000..52a785d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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:        tcpcheck.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 CFREADER_H
+#define CFREADER_H
+
+#include <stdio.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>
+
+#define SOCKET_ERROR   0
+#define SOCKET_SUCCESS 1
+#define STCP 1111
+
+#define LOGBUFFER_LENGTH 100
+#define SYNPACKET_LENGTH 1024
+#define HOSTNAME_LENGTH  30
+
+/* 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
diff --git a/keepalived/utils.c b/keepalived/utils.c
new file mode 100644 (file)
index 0000000..aabdea4
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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: 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.
+ */
+
+#include "utils.h"
+
+void print_buffer(int count, char *buff)
+{
+  int i,j,c;
+  int printnext=1;
+
+  if(count) {
+    if(count%16)
+      c=count+(16-count%16);
+    else c=count;
+  } else
+    c=count;
+
+  for(i=0;i<c;i++) {
+    if(printnext) {
+      printnext--;
+      printf("%.4x ",i&0xffff);
+    }
+    if(i<count)
+      printf("%3.2x",buff[i]&0xff);
+    else
+      printf("   ");
+    if(!((i+1)%8)) {
+      if((i+1)%16)
+        printf(" -");
+      else {
+        printf("   ");
+        for(j=i-15;j<=i;j++)
+          if(j<count) {
+            if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
+              printf("%c",buff[j]&0xff);
+            else printf(".");
+          } else printf(" ");
+        printf("\n"); printnext=1;
+      }
+    }
+  }
+}
+
+void logmessage(char *msg,int idevent)
+{
+  FILE *logfile;
+  time_t hint;
+  struct tm *date;
+
+  hint = time((long*)0);
+  date = localtime(&hint);
+
+  logfile=fopen(LOGFILE,"ab");
+  fprintf(logfile,"[%.2d/%.2d/%.2d - %.2d:%.2d:%.2d] keepalived[%d]: %s",
+                  date->tm_mday,
+                  date->tm_mon+1,
+                  date->tm_year-100,
+                  date->tm_hour,
+                  date->tm_min,
+                  date->tm_sec,
+                  idevent,msg);
+  fclose(logfile);
+}
diff --git a/keepalived/utils.h b/keepalived/utils.h
new file mode 100644 (file)
index 0000000..42e6984
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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: 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 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"
+
+#endif
diff --git a/libmd-0.3 b/libmd-0.3
new file mode 100644 (file)
index 0000000..fcd15ac
--- /dev/null
+++ b/libmd-0.3
@@ -0,0 +1 @@
+ff