--- /dev/null
+# 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/
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+# 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/
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+# 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
+ }
+}
+
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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