--- /dev/null
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
+
+EXEC= keepalived
+CC= gcc
+#CFLAGS= -Wall -Wunused
+CFLAGS=
+DEFS= md5.h iputils.h utils.h pidfile.h cfreader.h icmpcheck.h tcpcheck.h httpget.h smtpwrapper.h ipvswrapper.h keepalived.h
+OBJECTS= md5.o iputils.o utils.o pidfile.o cfreader.o icmpcheck.o tcpcheck.o httpget.o smtpwrapper.o ipvswrapper.o keepalived.o
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:
+# $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+ $(CC) -o $@ $(INCLUDE) -DDEBUG -c $*.c
+
+all: $(EXEC)
+ strip $(EXEC)
+ @echo ""
+ @echo "Make complete"
+
+$(EXEC): $(OBJECTS) $(DEFS)
+ $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+
+clean:
+ rm -f core *.o $(EXEC) /etc/lvs.conf /etc/keepalived/keepalived.conf /usr/sbin/keepalived /usr/bin/genhash
+ rm -rf /etc/keepalived
+
+install:
+ install -m 700 keepalived /usr/sbin/
+ install -m 755 etc/rc.d/init.d/keepalived.init /etc/rc.d/init.d/
+ mkdir /etc/keepalived
+ mkdir /etc/keepalived/log
+ touch /etc/keepalived/log/keepalived.log
+ install -m 644 etc/lvs.conf /etc/
+ install -m 644 etc/keepalived/keepalived.conf /etc/keepalived/
--- /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: cfreader.c,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Change the dynamic data structure. Move to a tree data
+ * structure.
+ * <+> Revisited the pointer handling for the dynamic data
+ * structure.
+ * <+> Adding keywords support for the configuration file.
+ * <+> Adding support for email notification.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "cfreader.h"
+
+int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
+{
+ virtualserver *pointerptr=lstptr;
+
+ while(lstptr != NULL) {
+ if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+ lstptr=pointerptr;
+ return 1;
+ }
+ lstptr=(virtualserver *)lstptr->next;
+ }
+ lstptr=pointerptr;
+ return 0;
+}
+
+int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
+{
+ realserver *pointerptr=lstptr;
+
+ while(lstptr != NULL) {
+ if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+ lstptr=pointerptr;
+ return 1;
+ }
+ lstptr=(realserver *)lstptr->next;
+ }
+ lstptr=pointerptr;
+ return 0;
+}
+
+notification_email * AddItem_Email(notification_email *lstemail,notification_email *email)
+{
+ notification_email *pointerlst=lstemail;
+
+ if (lstemail != NULL) {
+ while(lstemail->next != NULL) lstemail=(notification_email *)lstemail->next;
+ lstemail->next=(struct notification_email *)email;
+ return pointerlst;
+ } else {
+ lstemail=email;
+ return lstemail;
+ }
+}
+
+virtualserver * AddItem_VS(virtualserver *lstvs,virtualserver *vs)
+{
+ virtualserver *pointerlst=lstvs;
+
+ if(AlreadyExist_VS(lstvs,vs->addr_ip,vs->addr_port)) return lstvs;
+
+ if (lstvs != NULL) {
+ while(lstvs->next != NULL) lstvs=(virtualserver *)lstvs->next;
+ lstvs->next=(struct virtualserver *)vs;
+ return pointerlst;
+ } else {
+ lstvs=vs;
+ return lstvs;
+ }
+}
+
+realserver * AddItem_SVR(realserver *lstsvr,realserver *svr)
+{
+ realserver *pointerlst=lstsvr;
+
+ if(AlreadyExist_SVR(lstsvr,svr->addr_ip,svr->addr_port)) return lstsvr;
+
+ if (lstsvr != NULL) {
+ while(lstsvr->next != NULL) lstsvr=(realserver *)lstsvr->next;
+ lstsvr->next=(struct realserver *)svr;
+ return pointerlst;
+ } else {
+ lstsvr=svr;
+ return lstsvr;
+ }
+}
+
+urls * AddItem_Url(urls *lsturls,urls *url)
+{
+ urls *pointerlst=lsturls;
+
+ if (lsturls != NULL) {
+ while(lsturls->next != NULL) lsturls=(urls *)lsturls->next;
+ lsturls->next=(struct urls *)url;
+ return pointerlst;
+ } else {
+ lsturls=url;
+ return lsturls;
+ }
+}
+
+urls * RemoveUrl(urls * lstptr)
+{
+ urls *t;
+
+ t=(urls *)lstptr->next;
+ free(lstptr);
+ return t;
+}
+
+realserver * RemoveSVR(realserver * lstptr)
+{
+ realserver *t;
+
+ t=(realserver *)lstptr->next;
+
+ if(lstptr->method->http_get != NULL) {
+ while(lstptr->method->http_get->check_urls != NULL)
+ lstptr->method->http_get->check_urls=RemoveUrl(lstptr->method->http_get->check_urls);
+ free(lstptr->method->http_get);
+ }
+
+ if(lstptr->method->tcp_vanilla != NULL)
+ free(lstptr->method->tcp_vanilla);
+
+ free(lstptr->method);
+ free(lstptr);
+ return t;
+}
+
+virtualserver * RemoveVS(virtualserver * lstptr)
+{
+ virtualserver *t;
+
+ t=(virtualserver *)lstptr->next;
+ while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
+ free(lstptr);
+ return t;
+}
+
+notification_email * RemoveEmail(notification_email *lstptr)
+{
+ notification_email *t;
+
+ t=(notification_email *)lstptr->next;
+ free(lstptr);
+ return t;
+}
+
+void ClearConf(configuration_data * lstptr)
+{
+ while(lstptr->email != NULL)
+ lstptr->email=RemoveEmail(lstptr->email);
+
+ while(lstptr->lvstopology != NULL)
+ lstptr->lvstopology=RemoveVS(lstptr->lvstopology);
+}
+
+void PrintConf(configuration_data *lstconf)
+{
+ notification_email *pointeremail;
+ virtualserver *pointervs;
+ realserver *pointersvr;
+ urls *pointerurls;
+ char *tempbuffer;
+
+ tempbuffer=(char *)malloc(TEMPBUFFERLENGTH);
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+
+ if(lstconf == NULL) {
+ logmessage("Empty data configuration !!!\n");
+ } else {
+ logmessage("------< Global definitions >------\n");
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," LVS ID = %s\n",lstconf->lvs_id);
+ logmessage(tempbuffer);
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Delay loop = %s, Smtp server = %s\n",
+ lstconf->delay_loop,lstconf->smtp_server);
+ logmessage(tempbuffer);
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Email notification from = %s\n",lstconf->email_from);
+ logmessage(tempbuffer);
+
+ pointeremail=lstconf->email;
+ while(lstconf->email != NULL) {
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Email notification = %s\n",lstconf->email->addr);
+ logmessage(tempbuffer);
+
+ lstconf->email=(notification_email *)lstconf->email->next;
+ }
+ lstconf->email=pointeremail;
+
+ logmessage("------< LVS Topology >------\n");
+ pointervs=lstconf->lvstopology;
+ while(lstconf->lvstopology != NULL) {
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," VS IP = %s, PORT = %s\n",lstconf->lvstopology->addr_ip,
+ lstconf->lvstopology->addr_port);
+ logmessage(tempbuffer);
+
+ sprintf(tempbuffer," -> lb_algo = %s, lb_kind = %s, persistence = %s, protocol = %s\n",
+ lstconf->lvstopology->sched,lstconf->lvstopology->loadbalancing_kind,
+ lstconf->lvstopology->timeout_persistence,lstconf->lvstopology->service_type);
+ logmessage(tempbuffer);
+
+ pointersvr=lstconf->lvstopology->svr;
+ while(lstconf->lvstopology->svr != NULL) {
+ sprintf(tempbuffer," -> SVR IP = %s, PORT = %s, WEIGHT = %s\n",
+ lstconf->lvstopology->svr->addr_ip,lstconf->lvstopology->svr->addr_port,
+ lstconf->lvstopology->svr->weight);
+ logmessage(tempbuffer);
+
+ /* Displaying ICMP_CHECK resume */
+ if (lstconf->lvstopology->svr->method->flag_type == ICMP_CHECK_ID)
+ logmessage(" -> Keepalive method = ICMP_CHECK\n");
+
+ /* Displaying TCP_CHECK resume */
+ if (lstconf->lvstopology->svr->method->flag_type == TCP_CHECK_ID) {
+ logmessage(" -> Keepalive method = TCP_CHECK\n");
+ sprintf(tempbuffer," -> Connection timeout = %s\n",
+ lstconf->lvstopology->svr->method->tcp_vanilla->connection_to);
+ logmessage(tempbuffer);
+ }
+
+ /* Displaying HTTP_GET resume */
+ if (lstconf->lvstopology->svr->method->flag_type == HTTP_GET_ID) {
+ pointerurls=lstconf->lvstopology->svr->method->http_get->check_urls;
+ logmessage(" -> Keepalive method = HTTP_GET\n");
+ while (lstconf->lvstopology->svr->method->http_get->check_urls != NULL) {
+ sprintf(tempbuffer," -> Url = %s, Digest = %s\n",
+ lstconf->lvstopology->svr->method->http_get->check_urls->url,
+ lstconf->lvstopology->svr->method->http_get->check_urls->digest);
+ logmessage(tempbuffer);
+ lstconf->lvstopology->svr->method->http_get->check_urls=(urls *)lstconf->lvstopology->svr->method->http_get->check_urls->next;
+ }
+ lstconf->lvstopology->svr->method->http_get->check_urls=pointerurls;
+
+ sprintf(tempbuffer," -> Connection timeout = %s, Nb get retry = %s\n",
+ lstconf->lvstopology->svr->method->http_get->connection_to,
+ lstconf->lvstopology->svr->method->http_get->nb_get_retry);
+ logmessage(tempbuffer);
+ sprintf(tempbuffer," -> Delay before retry = %s\n",
+ lstconf->lvstopology->svr->method->http_get->delay_before_retry);
+ logmessage(tempbuffer);
+ }
+
+ lstconf->lvstopology->svr=(realserver *)lstconf->lvstopology->svr->next;
+ }
+ lstconf->lvstopology->svr=pointersvr;
+
+ lstconf->lvstopology=(virtualserver *)lstconf->lvstopology->next;
+ }
+ lstconf->lvstopology=pointervs;
+
+ }
+ free(tempbuffer);
+}
+
+configuration_data * ConfReader(configuration_data *conf_data)
+{
+ FILE *stream;
+ char *string="";
+ virtualserver *pointervs;
+ virtualserver *vsfill;
+ realserver *svrfill;
+ notification_email *emailfill;
+ keepalive_check *methodfill;
+ http_get_check *httpgetfill;
+ urls *urlsfill;
+ tcp_vanilla_check *tcpcheckfill;
+
+ stream=fopen(CONFFILE,"r");
+ if(stream==NULL) {
+ logmessage("ConfReader : Can not read the config file\n");
+ return(NULL);
+ }
+
+ string=(char *)malloc(TEMPBUFFERLENGTH);
+ memset(string,0,TEMPBUFFERLENGTH);
+ conf_data=(configuration_data *)malloc(sizeof(configuration_data));
+ memset(conf_data,0,sizeof(configuration_data));
+
+ /* Initialise the dynamic data structure */
+ conf_data->email=NULL;
+ conf_data->lvstopology=NULL;
+
+ while(!feof(stream)) {
+ fscanf(stream,"%s",string);
+
+ /* Fill in the global defs structure */
+ if(strcmp(string,GLOBALDEFS) == 0)
+ do {
+ if(strcmp(string,DELAY) == 0)
+ fscanf(stream,"%s",conf_data->delay_loop);
+ if(strcmp(string,SMTP) == 0)
+ fscanf(stream,"%s",conf_data->smtp_server);
+ if(strcmp(string,EMAILFROM) == 0)
+ fscanf(stream,"%s",conf_data->email_from);
+ if(strcmp(string,LVSID) == 0)
+ fscanf(stream,"%s",conf_data->lvs_id);
+ if(strcmp(string,EMAIL) == 0)
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ emailfill=(notification_email *)malloc(sizeof(notification_email));
+ memset(emailfill,0,sizeof(notification_email));
+ strncat(emailfill->addr,string,sizeof(emailfill->addr));
+ emailfill->next=NULL;
+ conf_data->email = AddItem_Email(conf_data->email,emailfill);
+ }
+ } while(strcmp(string,ENDFLAG) != 0);
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+
+ /* Fill in virtual server structure */
+ if(strcmp(string,VS) == 0) {
+ vsfill=(virtualserver *)malloc(sizeof(virtualserver));
+ vsfill->next=NULL;
+ conf_data->lvstopology = AddItem_VS(conf_data->lvstopology,vsfill);
+
+ pointervs=conf_data->lvstopology;
+ while(conf_data->lvstopology->next != NULL)
+ conf_data->lvstopology=(virtualserver *)conf_data->lvstopology->next;
+
+ fscanf(stream,"%s",vsfill->addr_ip);
+ fscanf(stream,"%s",vsfill->addr_port);
+ do {
+ if(strcmp(string,LBSCHED) == 0)
+ fscanf(stream,"%s",vsfill->sched);
+ if(strcmp(string,LBKIND) == 0)
+ fscanf(stream,"%s",vsfill->loadbalancing_kind);
+ if(strcmp(string,PTIMEOUT) == 0)
+ fscanf(stream,"%s",vsfill->timeout_persistence);
+ if(strcmp(string,PROTOCOL) == 0)
+ fscanf(stream,"%s",vsfill->service_type);
+
+ /* Fill in real server structure */
+ if(strcmp(string,SVR) == 0) {
+ svrfill=(realserver *)malloc(sizeof(realserver));
+ memset(svrfill,0,sizeof(realserver));
+ fscanf(stream,"%s",svrfill->addr_ip);
+ fscanf(stream,"%s",svrfill->addr_port);
+ svrfill->alive=1;
+ do {
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ if(strcmp(string,WEIGHT) == 0)
+ fscanf(stream,"%s",svrfill->weight);
+
+ if(strcmp(string,ICMPCHECK) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=ICMP_CHECK_ID;
+ methodfill->http_get=NULL;
+ methodfill->tcp_vanilla=NULL;
+ }
+
+ if(strcmp(string,TCPCHECK) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=TCP_CHECK_ID;
+ tcpcheckfill=(tcp_vanilla_check *)malloc(sizeof(tcp_vanilla_check));
+ memset(tcpcheckfill,0,sizeof(tcp_vanilla_check));
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ if(strcmp(string,CTIMEOUT) == 0)
+ fscanf(stream,"%s",tcpcheckfill->connection_to);
+ }
+ } while (strcmp(string,ENDFLAG) != 0);
+ methodfill->http_get=NULL;
+ methodfill->tcp_vanilla=tcpcheckfill;
+ }
+
+ if(strcmp(string,HTTPGET) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=HTTP_GET_ID;
+ httpgetfill=(http_get_check *)malloc(sizeof(http_get_check));
+ memset(httpgetfill,0,sizeof(http_get_check));
+ httpgetfill->check_urls=NULL;
+ do {
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+ if(strcmp(string,CTIMEOUT) == 0)
+ fscanf(stream,"%s",httpgetfill->connection_to);
+ if(strcmp(string,NBGETRETRY) == 0)
+ fscanf(stream,"%s",httpgetfill->nb_get_retry);
+ if(strcmp(string,DELAYRETRY) == 0)
+ fscanf(stream,"%s",httpgetfill->delay_before_retry);
+
+ if(strcmp(string,URL) == 0) {
+ urlsfill=(urls *)malloc(sizeof(urls));
+ memset(urlsfill,0,sizeof(urls));
+ urlsfill->next=NULL;
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+ if(strcmp(string,URLPATH) == 0)
+ fscanf(stream,"%s",urlsfill->url);
+ if(strcmp(string,DIGEST) == 0)
+ fscanf(stream,"%s",urlsfill->digest);
+
+ }
+ } while (strcmp(string,ENDFLAG) != 0);
+ httpgetfill->check_urls=AddItem_Url(httpgetfill->check_urls,urlsfill);
+ }
+
+ }
+ fscanf(stream,"%s",string);
+ } while (strcmp(string,ENDFLAG) != 0);
+ methodfill->http_get=httpgetfill;
+ methodfill->tcp_vanilla=NULL;
+ }
+ }
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+ svrfill->method=methodfill;
+ svrfill->next=NULL;
+ conf_data->lvstopology->svr = AddItem_SVR(conf_data->lvstopology->svr,svrfill);
+ }
+
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+ conf_data->lvstopology=pointervs;
+ }
+ }
+
+ free(string);
+ fclose(stream);
+
+ return(conf_data);
+}
--- /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: cfreader.h,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Adding keywords.
+ * <+> Change change the whole data structure.
+ * <+> Adding LVS ID & notification email for alertes.
+ *
+ * Alexandre Cassen : Initial release : 2000/12/09
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONFFILE "keepalived.conf"
+
+#define TEMPBUFFERLENGTH 100
+
+/* Keywords definition */
+#define GLOBALDEFS "global_defs"
+#define VS "virtual_server"
+#define SVR "real_server"
+#define BEGINFLAG "{"
+#define ENDFLAG "}"
+#define DELAY "delay_loop"
+#define EMAIL "notification_email"
+#define EMAILFROM "notification_email_from"
+#define LVSID "lvs_id"
+#define SMTP "smtp_server"
+#define LBSCHED "lb_algo"
+#define LBKIND "lb_kind"
+#define PTIMEOUT "persistence_timeout"
+#define PROTOCOL "protocol"
+#define WEIGHT "weight"
+#define URL "url"
+#define URLPATH "path"
+#define DIGEST "digest"
+#define CTIMEOUT "connect_timeout"
+#define NBGETRETRY "nb_get_retry"
+#define DELAYRETRY "delay_before_retry"
+
+#define ICMPCHECK "ICMP_CHECK"
+#define TCPCHECK "TCP_CHECK"
+#define HTTPGET "HTTP_GET"
+#define SSLGET "SSL_GET"
+
+/* Check method id */
+#define ICMP_CHECK_ID 0x001
+#define TCP_CHECK_ID 0x002
+#define HTTP_GET_ID 0x003
+#define SSL_GET_ID 0x004
+
+/* Structure definition */
+typedef struct _tcp_vanilla_check {
+ char connection_to[4+1];
+} tcp_vanilla_check;
+
+typedef struct _urls {
+ char url[100+1];
+ char digest[32+1];
+
+ struct urls *next;
+} urls;
+
+typedef struct _http_get_check {
+ char connection_to[4+1];
+ char nb_get_retry[1+1];
+ char delay_before_retry[4+1];
+ urls *check_urls;
+} http_get_check;
+
+typedef struct _keepalive_check {
+ int flag_type;
+ http_get_check *http_get;
+ tcp_vanilla_check *tcp_vanilla;
+} keepalive_check;
+
+typedef struct _real_server {
+ char addr_ip[15+1];
+ char addr_port[5+1];
+ char weight[3+1];
+ keepalive_check *method;
+ int alive;
+
+ struct realserver *next;
+} realserver;
+
+typedef struct _virtual_server {
+ char addr_ip[15+1];
+ char addr_port[5+1];
+ char sched[5+1];
+ char loadbalancing_kind[5+1];
+ char timeout_persistence[4];
+ char service_type[3+1];
+ realserver *svr;
+
+ struct virtualserver *next;
+} virtualserver;
+
+typedef struct _notification_email {
+ char addr[40+1];
+
+ struct notification_email *next;
+} notification_email;
+
+typedef struct _configuration_data {
+ char delay_loop[4+1];
+ char email_from[40+1];
+ char smtp_server[15+1];
+ char lvs_id[20+1];
+ notification_email *email;
+
+ virtualserver *lvstopology;
+} configuration_data;
+
+#endif
# Makefile
# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
-EXEC= keepalived
+EXEC= confreader
CC= gcc
-#CFLAGS= -Wall -Wunused -lmd
-CFLAGS= -lmd
-DEFS= iputils.h utils.h cfreader.h icmpcheck.h tcpcheck.h httpget.h ipvswrapper.h keepalived.h
-OBJECTS= iputils.o utils.o cfreader.o icmpcheck.o tcpcheck.o httpget.o ipvswrapper.o keepalived.o
+#CFLAGS= -Wall -Wunused
+CFLAGS=
+DEFS= main.h cfreader.h
+OBJECTS= main.o cfreader.o utils.o
INCLUDE= -I/usr/src/linux/include
.c.o:
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: cfreader.c,v 0.2.1 2000/12/09 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "cfreader.h"
+
+int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
+{
+ virtualserver *pointerptr=lstptr;
+
+ while(lstptr != NULL) {
+ if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+ lstptr=pointerptr;
+ return 1;
+ }
+ lstptr=(virtualserver *)lstptr->next;
+ }
+ lstptr=pointerptr;
+ return 0;
+}
+
+int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
+{
+ realserver *pointerptr=lstptr;
+
+ while(lstptr != NULL) {
+ if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
+ lstptr=pointerptr;
+ return 1;
+ }
+ lstptr=(realserver *)lstptr->next;
+ }
+ lstptr=pointerptr;
+ return 0;
+}
+
+notification_email * AddItem_Email(notification_email *lstemail,notification_email *email)
+{
+ notification_email *pointerlst=lstemail;
+
+ if (lstemail != NULL) {
+ while(lstemail->next != NULL) lstemail=(notification_email *)lstemail->next;
+ lstemail->next=(struct notification_email *)email;
+ return pointerlst;
+ } else {
+ lstemail=email;
+ return lstemail;
+ }
+}
+
+virtualserver * AddItem_VS(virtualserver *lstvs,virtualserver *vs)
+{
+ virtualserver *pointerlst=lstvs;
+
+ if(AlreadyExist_VS(lstvs,vs->addr_ip,vs->addr_port)) return lstvs;
+
+ if (lstvs != NULL) {
+ while(lstvs->next != NULL) lstvs=(virtualserver *)lstvs->next;
+ lstvs->next=(struct virtualserver *)vs;
+ return pointerlst;
+ } else {
+ lstvs=vs;
+ return lstvs;
+ }
+}
+
+realserver * AddItem_SVR(realserver *lstsvr,realserver *svr)
+{
+ realserver *pointerlst=lstsvr;
+
+ if(AlreadyExist_SVR(lstsvr,svr->addr_ip,svr->addr_port)) return lstsvr;
+
+ if (lstsvr != NULL) {
+ while(lstsvr->next != NULL) lstsvr=(realserver *)lstsvr->next;
+ lstsvr->next=(struct realserver *)svr;
+ return pointerlst;
+ } else {
+ lstsvr=svr;
+ return lstsvr;
+ }
+}
+
+urls * AddItem_Url(urls *lsturls,urls *url)
+{
+ urls *pointerlst=lsturls;
+
+ if (lsturls != NULL) {
+ while(lsturls->next != NULL) lsturls=(urls *)lsturls->next;
+ lsturls->next=(struct urls *)url;
+ return pointerlst;
+ } else {
+ lsturls=url;
+ return lsturls;
+ }
+}
+
+urls * RemoveUrl(urls * lstptr)
+{
+ urls *t;
+
+ t=(urls *)lstptr->next;
+ free(lstptr);
+ return t;
+}
+
+realserver * RemoveSVR(realserver * lstptr)
+{
+ realserver *t;
+
+ t=(realserver *)lstptr->next;
+
+ if(lstptr->method->http_get != NULL) {
+ while(lstptr->method->http_get->check_urls != NULL)
+ lstptr->method->http_get->check_urls=RemoveUrl(lstptr->method->http_get->check_urls);
+ free(lstptr->method->http_get);
+ }
+
+ if(lstptr->method->tcp_vanilla != NULL)
+ free(lstptr->method->tcp_vanilla);
+
+ free(lstptr->method);
+ free(lstptr);
+ return t;
+}
+
+virtualserver * RemoveVS(virtualserver * lstptr)
+{
+ virtualserver *t;
+
+ t=(virtualserver *)lstptr->next;
+ while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
+ free(lstptr);
+ return t;
+}
+
+notification_email * RemoveEmail(notification_email *lstptr)
+{
+ notification_email *t;
+
+ t=(notification_email *)lstptr->next;
+ free(lstptr);
+ return t;
+}
+
+void ClearConf(configuration_data * lstptr)
+{
+ while(lstptr->email != NULL)
+ lstptr->email=RemoveEmail(lstptr->email);
+
+ while(lstptr->lvstopology != NULL)
+ lstptr->lvstopology=RemoveVS(lstptr->lvstopology);
+}
+
+void PrintConf(configuration_data *lstconf)
+{
+ notification_email *pointeremail;
+ virtualserver *pointervs;
+ realserver *pointersvr;
+ urls *pointerurls;
+ char *tempbuffer;
+
+ tempbuffer=(char *)malloc(TEMPBUFFERLENGTH);
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+
+ if(lstconf == NULL) {
+ logmessage("Empty data configuration !!!\n",getpid());
+ } else {
+ logmessage("------< Global definitions >------\n",getpid());
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," LVS ID = %s\n",lstconf->lvs_id);
+ logmessage(tempbuffer,getpid());
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Delay loop = %s, Smtp server = %s\n",
+ lstconf->delay_loop,lstconf->smtp_server);
+ logmessage(tempbuffer,getpid());
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Email notification from = %s\n",lstconf->email_from);
+ logmessage(tempbuffer,getpid());
+
+ pointeremail=lstconf->email;
+ while(lstconf->email != NULL) {
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," Email notification = %s\n",lstconf->email->addr);
+ logmessage(tempbuffer,getpid());
+
+ lstconf->email=(notification_email *)lstconf->email->next;
+ }
+ lstconf->email=pointeremail;
+
+ logmessage("------< LVS Topology >------\n",getpid());
+ pointervs=lstconf->lvstopology;
+ while(lstconf->lvstopology != NULL) {
+ memset(tempbuffer,0,TEMPBUFFERLENGTH);
+ sprintf(tempbuffer," VS IP = %s, PORT = %s\n",lstconf->lvstopology->addr_ip,
+ lstconf->lvstopology->addr_port);
+ logmessage(tempbuffer,getpid());
+
+ sprintf(tempbuffer," -> lb_algo = %s, lb_kind = %s, persistence = %s, protocol = %s\n",
+ lstconf->lvstopology->sched,lstconf->lvstopology->loadbalancing_kind,
+ lstconf->lvstopology->timeout_persistence,lstconf->lvstopology->service_type);
+ logmessage(tempbuffer,getpid());
+
+ pointersvr=lstconf->lvstopology->svr;
+ while(lstconf->lvstopology->svr != NULL) {
+ sprintf(tempbuffer," -> SVR IP = %s, PORT = %s, WEIGHT = %s\n",
+ lstconf->lvstopology->svr->addr_ip,lstconf->lvstopology->svr->addr_port,
+ lstconf->lvstopology->svr->weight);
+ logmessage(tempbuffer,getpid());
+
+ /* Displaying ICMP_CHECK resume */
+ if (lstconf->lvstopology->svr->method->flag_type == ICMP_CHECK_ID)
+ logmessage(" -> Keepalive method = ICMP_CHECK\n",getpid());
+
+ /* Displaying TCP_CHECK resume */
+ if (lstconf->lvstopology->svr->method->flag_type == TCP_CHECK_ID) {
+ logmessage(" -> Keepalive method = TCP_CHECK\n",getpid());
+ sprintf(tempbuffer," -> Connection timeout = %s\n",
+ lstconf->lvstopology->svr->method->tcp_vanilla->connection_to);
+ logmessage(tempbuffer,getpid());
+ }
+
+ /* Displaying HTTP_GET resume */
+ if (lstconf->lvstopology->svr->method->flag_type == HTTP_GET_ID) {
+ pointerurls=lstconf->lvstopology->svr->method->http_get->check_urls;
+ logmessage(" -> Keepalive method = HTTP_GET\n",getpid());
+ while (lstconf->lvstopology->svr->method->http_get->check_urls != NULL) {
+ sprintf(tempbuffer," -> Url = %s, Digest = %s\n",
+ lstconf->lvstopology->svr->method->http_get->check_urls->url,
+ lstconf->lvstopology->svr->method->http_get->check_urls->digest);
+ logmessage(tempbuffer,getpid());
+ lstconf->lvstopology->svr->method->http_get->check_urls=(urls *)lstconf->lvstopology->svr->method->http_get->check_urls->next;
+ }
+ lstconf->lvstopology->svr->method->http_get->check_urls=pointerurls;
+
+ sprintf(tempbuffer," -> Connection timeout = %s, Nb get retry = %s\n",
+ lstconf->lvstopology->svr->method->http_get->connection_to,
+ lstconf->lvstopology->svr->method->http_get->nb_get_retry);
+ logmessage(tempbuffer,getpid());
+ sprintf(tempbuffer," -> Delay before retry = %s\n",
+ lstconf->lvstopology->svr->method->http_get->delay_before_retry);
+ logmessage(tempbuffer,getpid());
+ }
+
+ lstconf->lvstopology->svr=(realserver *)lstconf->lvstopology->svr->next;
+ }
+ lstconf->lvstopology->svr=pointersvr;
+
+ lstconf->lvstopology=(virtualserver *)lstconf->lvstopology->next;
+ }
+ lstconf->lvstopology=pointervs;
+
+ }
+ free(tempbuffer);
+}
+
+configuration_data * ConfReader(configuration_data *conf_data)
+{
+ FILE *stream;
+ char *string="";
+ virtualserver *pointervs;
+ virtualserver *vsfill;
+ realserver *svrfill;
+ notification_email *emailfill;
+ keepalive_check *methodfill;
+ http_get_check *httpgetfill;
+ urls *urlsfill;
+ tcp_vanilla_check *tcpcheckfill;
+
+ stream=fopen(CONFFILE,"r");
+ if(stream==NULL) {
+ logmessage("ConfReader : Can not read the config file\n",getpid());
+ return(NULL);
+ }
+
+ string=(char *)malloc(TEMPBUFFERLENGTH);
+ memset(string,0,TEMPBUFFERLENGTH);
+ conf_data=(configuration_data *)malloc(sizeof(configuration_data));
+ memset(conf_data,0,sizeof(configuration_data));
+
+ /* Initialise the dynamic data structure */
+ conf_data->email=NULL;
+ conf_data->lvstopology=NULL;
+
+ while(!feof(stream)) {
+ fscanf(stream,"%s",string);
+
+ /* Fill in the global defs structure */
+ if(strcmp(string,GLOBALDEFS) == 0)
+ do {
+ if(strcmp(string,DELAY) == 0)
+ fscanf(stream,"%s",conf_data->delay_loop);
+ if(strcmp(string,SMTP) == 0)
+ fscanf(stream,"%s",conf_data->smtp_server);
+ if(strcmp(string,EMAILFROM) == 0)
+ fscanf(stream,"%s",conf_data->email_from);
+ if(strcmp(string,LVSID) == 0)
+ fscanf(stream,"%s",conf_data->lvs_id);
+ if(strcmp(string,EMAIL) == 0)
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ emailfill=(notification_email *)malloc(sizeof(notification_email));
+ memset(emailfill,0,sizeof(notification_email));
+ strncat(emailfill->addr,string,sizeof(emailfill->addr));
+ emailfill->next=NULL;
+ conf_data->email = AddItem_Email(conf_data->email,emailfill);
+ }
+ } while(strcmp(string,ENDFLAG) != 0);
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+
+ /* Fill in virtual server structure */
+ if(strcmp(string,VS) == 0) {
+ vsfill=(virtualserver *)malloc(sizeof(virtualserver));
+ vsfill->next=NULL;
+ conf_data->lvstopology = AddItem_VS(conf_data->lvstopology,vsfill);
+
+ pointervs=conf_data->lvstopology;
+ while(conf_data->lvstopology->next != NULL)
+ conf_data->lvstopology=(virtualserver *)conf_data->lvstopology->next;
+
+ fscanf(stream,"%s",vsfill->addr_ip);
+ fscanf(stream,"%s",vsfill->addr_port);
+ do {
+ if(strcmp(string,LBSCHED) == 0)
+ fscanf(stream,"%s",vsfill->sched);
+ if(strcmp(string,LBKIND) == 0)
+ fscanf(stream,"%s",vsfill->loadbalancing_kind);
+ if(strcmp(string,PTIMEOUT) == 0)
+ fscanf(stream,"%s",vsfill->timeout_persistence);
+ if(strcmp(string,PROTOCOL) == 0)
+ fscanf(stream,"%s",vsfill->service_type);
+
+ /* Fill in real server structure */
+ if(strcmp(string,SVR) == 0) {
+ svrfill=(realserver *)malloc(sizeof(realserver));
+ memset(svrfill,0,sizeof(realserver));
+ fscanf(stream,"%s",svrfill->addr_ip);
+ fscanf(stream,"%s",svrfill->addr_port);
+ svrfill->alive=1;
+ do {
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ if(strcmp(string,WEIGHT) == 0)
+ fscanf(stream,"%s",svrfill->weight);
+
+ if(strcmp(string,ICMPCHECK) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=ICMP_CHECK_ID;
+ methodfill->http_get=NULL;
+ methodfill->tcp_vanilla=NULL;
+ }
+
+ if(strcmp(string,TCPCHECK) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=TCP_CHECK_ID;
+ tcpcheckfill=(tcp_vanilla_check *)malloc(sizeof(tcp_vanilla_check));
+ memset(tcpcheckfill,0,sizeof(tcp_vanilla_check));
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+ if(strcmp(string,CTIMEOUT) == 0)
+ fscanf(stream,"%s",tcpcheckfill->connection_to);
+ }
+ } while (strcmp(string,ENDFLAG) != 0);
+ methodfill->http_get=NULL;
+ methodfill->tcp_vanilla=tcpcheckfill;
+ }
+
+ if(strcmp(string,HTTPGET) == 0) {
+ methodfill=(keepalive_check *)malloc(sizeof(keepalive_check));
+ memset(methodfill,0,sizeof(keepalive_check));
+ methodfill->flag_type=HTTP_GET_ID;
+ httpgetfill=(http_get_check *)malloc(sizeof(http_get_check));
+ memset(httpgetfill,0,sizeof(http_get_check));
+ httpgetfill->check_urls=NULL;
+ do {
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+ if(strcmp(string,CTIMEOUT) == 0)
+ fscanf(stream,"%s",httpgetfill->connection_to);
+ if(strcmp(string,NBGETRETRY) == 0)
+ fscanf(stream,"%s",httpgetfill->nb_get_retry);
+ if(strcmp(string,DELAYRETRY) == 0)
+ fscanf(stream,"%s",httpgetfill->delay_before_retry);
+
+ if(strcmp(string,URL) == 0) {
+ urlsfill=(urls *)malloc(sizeof(urls));
+ memset(urlsfill,0,sizeof(urls));
+ urlsfill->next=NULL;
+ do {
+ fscanf(stream,"%s",string);
+ if(strcmp(string,BEGINFLAG)!=0 && strcmp(string,ENDFLAG)!=0) {
+
+ if(strcmp(string,URLPATH) == 0)
+ fscanf(stream,"%s",urlsfill->url);
+ if(strcmp(string,DIGEST) == 0)
+ fscanf(stream,"%s",urlsfill->digest);
+
+ }
+ } while (strcmp(string,ENDFLAG) != 0);
+ httpgetfill->check_urls=AddItem_Url(httpgetfill->check_urls,urlsfill);
+ }
+
+ }
+ fscanf(stream,"%s",string);
+ } while (strcmp(string,ENDFLAG) != 0);
+ methodfill->http_get=httpgetfill;
+ methodfill->tcp_vanilla=NULL;
+ }
+ }
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+ svrfill->method=methodfill;
+ svrfill->next=NULL;
+ conf_data->lvstopology->svr = AddItem_SVR(conf_data->lvstopology->svr,svrfill);
+ }
+
+ fscanf(stream,"%s",string);
+ } while(strcmp(string,ENDFLAG) != 0);
+ conf_data->lvstopology=pointervs;
+ }
+ }
+
+ free(string);
+ fclose(stream);
+
+ return(conf_data);
+}
--- /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: cfreader.h,v 0.2.1 2000/12/09 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONFFILE "keepalived.conf"
+
+#define TEMPBUFFERLENGTH 100
+
+/* Keywords definition */
+#define GLOBALDEFS "global_defs"
+#define VS "virtual_server"
+#define SVR "real_server"
+#define BEGINFLAG "{"
+#define ENDFLAG "}"
+#define DELAY "delay_loop"
+#define EMAIL "notification_email"
+#define EMAILFROM "notification_email_from"
+#define LVSID "lvs_id"
+#define SMTP "smtp_server"
+#define LBSCHED "lb_algo"
+#define LBKIND "lb_kind"
+#define PTIMEOUT "persistence_timeout"
+#define PROTOCOL "protocol"
+#define WEIGHT "weight"
+#define URL "url"
+#define URLPATH "path"
+#define DIGEST "digest"
+#define CTIMEOUT "connect_timeout"
+#define NBGETRETRY "nb_get_retry"
+#define DELAYRETRY "delay_before_retry"
+
+#define ICMPCHECK "ICMP_CHECK"
+#define TCPCHECK "TCP_CHECK"
+#define HTTPGET "HTTP_GET"
+#define SSLGET "SSL_GET"
+
+/* Check method id */
+#define ICMP_CHECK_ID 0x001
+#define TCP_CHECK_ID 0x002
+#define HTTP_GET_ID 0x003
+#define SSL_GET_ID 0x004
+
+/* Structure definition */
+typedef struct _tcp_vanilla_check {
+ char connection_to[4+1];
+} tcp_vanilla_check;
+
+typedef struct _urls {
+ char url[100+1];
+ char digest[32+1];
+
+ struct urls *next;
+} urls;
+
+typedef struct _http_get_check {
+ char connection_to[4+1];
+ char nb_get_retry[1+1];
+ char delay_before_retry[4+1];
+ urls *check_urls;
+} http_get_check;
+
+typedef struct _keepalive_check {
+ int flag_type;
+ http_get_check *http_get;
+ tcp_vanilla_check *tcp_vanilla;
+} keepalive_check;
+
+typedef struct _real_server {
+ char addr_ip[15+1];
+ char addr_port[5+1];
+ char weight[3+1];
+ keepalive_check *method;
+ int alive;
+
+ struct realserver *next;
+} realserver;
+
+typedef struct _virtual_server {
+ char addr_ip[15+1];
+ char addr_port[5+1];
+ char sched[5+1];
+ char loadbalancing_kind[5+1];
+ char timeout_persistence[4];
+ char service_type[3+1];
+ realserver *svr;
+
+ struct virtualserver *next;
+} virtualserver;
+
+typedef struct _notification_email {
+ char addr[40+1];
+
+ struct notification_email *next;
+} notification_email;
+
+typedef struct _configuration_data {
+ char delay_loop[4+1];
+ char email_from[40+1];
+ char smtp_server[15+1];
+ char lvs_id[20+1];
+ notification_email *email;
+
+ virtualserver *lvstopology;
+} configuration_data;
+
+/* prototypes */
+//configuration_data * ConfReader(configuration_data *conf_data);
+//void ClearConf(configuration_data * lstptr);
+//void PrintConf(configuration_data * lstptr);
+
+#endif
--- /dev/null
+# Configuration File for keepalived
+
+
+global_defs {
+ delay_loop 60
+ notification_email {
+ acassen@domain.com
+ 0633225522@domain.com
+ }
+ notification_email_from keepalived@domain.com
+ smtp_server 192.168.3.62
+ lvs_id LVS_MAIN
+}
+
+virtual_server 10.10.10.2 1358 {
+ lb_algo rr
+ lb_kind NAT
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.200.2 1358 {
+ weight 1
+ HTTP_GET {
+ url {
+ path /testurl/test.jsp
+ digest ec90a42b99ea9a2f5ecbe213ac9eba03
+ }
+ url {
+ path /testurl2/test.jsp
+ digest 640205b7b0fc66c1ea91c463fac6334c
+ }
+ connect_timeout 3
+ nb_get_retry 3
+ delay_before_retry 2
+ }
+ }
+ real_server 192.168.200.3 1358 {
+ weight 1
+ HTTP_GET {
+ url {
+ path /testurl/test.jsp
+ digest 640205b7b0fc66c1ea91c463fac6334c
+ }
+ connect_timeout 3
+ nb_get_retry 3
+ delay_before_retry 2
+ }
+ }
+}
+
+virtual_server 10.10.10.2 8080 {
+ lb_algo rr
+ lb_kind NAT
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.200.4 8080 {
+ weight 1
+ TCP_CHECK {
+ connect_timeout 3
+ }
+ }
+ real_server 192.168.200.5 8080 {
+ weight 1
+ ICMP_CHECK
+ }
+ real_server 192.168.200.6 8080 {
+ weight 1
+ TCP_CHECK {
+ connect_timeout 3
+ }
+ }
+}
+
--- /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.3 2001/01/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/01/01 :
+ * <+> Change the signalhandling.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "main.h"
+
+int main(int argc, char **argv)
+{
+ int delay_loop=60;
+ printf(PROG" v"VERSION"\n");
+
+ if (chdir(CONF_HOME_DIR)) {
+ fprintf(stderr,"%s: ",CONF_HOME_DIR);
+ perror(NULL);
+ exit(1);
+ }
+
+ if ((confDATA=(configuration_data *)ConfReader(confDATA)) == NULL) {
+ exit(0);
+ }
+
+ PrintConf(confDATA);
+ ClearConf(confDATA);
+
+ return 0;
+}
--- /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"
+
+#define LOGBUFFER_LENGTH 100
+
+/* Configuration file home directory */
+#define CONF_HOME_DIR "./"
+
+/* Global variables */
+configuration_data *confDATA;
+
+/* Build version */
+#define PROG "confreader"
+#define VERSION "0.2.6 (02/20, 2001), Alexandre Cassen"
+
+#endif
--- /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: utils.c,v 0.2.1 2000/12/09 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+void print_buffer(int count, char *buff)
+{
+ int i,j,c;
+ int printnext=1;
+
+ if(count) {
+ if(count%16)
+ c=count+(16-count%16);
+ else c=count;
+ } else
+ c=count;
+
+ for(i=0;i<c;i++) {
+ if(printnext) {
+ printnext--;
+ printf("%.4x ",i&0xffff);
+ }
+ if(i<count)
+ printf("%3.2x",buff[i]&0xff);
+ else
+ printf(" ");
+ if(!((i+1)%8)) {
+ if((i+1)%16)
+ printf(" -");
+ else {
+ printf(" ");
+ for(j=i-15;j<=i;j++)
+ if(j<count) {
+ if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
+ printf("%c",buff[j]&0xff);
+ else printf(".");
+ } else printf(" ");
+ printf("\n"); printnext=1;
+ }
+ }
+ }
+}
+
+void logmessage(char *msg,int idevent)
+{
+ printf("%s",msg);
+}
--- /dev/null
+# Configuration File for keepalived
+
+
+global_defs {
+ delay_loop 60
+ notification_email {
+ acassen@domain.com
+ 0633225522@domain.com
+ }
+ notification_email_from keepalived@domain.com
+ smtp_server 192.168.3.62
+ lvs_id LVS_MAIN
+}
+
+virtual_server 10.10.10.2 1358 {
+ lb_algo rr
+ lb_kind NAT
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.200.2 1358 {
+ weight 1
+ HTTP_GET {
+ url {
+ path /testurl/test.jsp
+ digest ec90a42b99ea9a2f5ecbe213ac9eba03
+ }
+ url {
+ path /testurl2/test.jsp
+ digest 640205b7b0fc66c1ea91c463fac6334c
+ }
+ connect_timeout 3
+ nb_get_retry 3
+ delay_before_retry 2
+ }
+ }
+ real_server 192.168.200.3 1358 {
+ weight 1
+ HTTP_GET {
+ url {
+ path /testurl/test.jsp
+ digest 640205b7b0fc66c1ea91c463fac6334c
+ }
+ connect_timeout 3
+ nb_get_retry 3
+ delay_before_retry 2
+ }
+ }
+}
+
+virtual_server 10.10.10.2 8080 {
+ lb_algo rr
+ lb_kind NAT
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.200.4 8080 {
+ weight 1
+ TCP_CHECK {
+ connect_timeout 3
+ }
+ }
+ real_server 192.168.200.5 8080 {
+ weight 1
+ ICMP_CHECK
+ }
+ real_server 192.168.200.6 8080 {
+ weight 1
+ TCP_CHECK {
+ connect_timeout 3
+ }
+ }
+}
+
--- /dev/null
+ipchains -A forward -j MASQ -p tcp -s 192.168.200.0/24 1358 -d 0.0.0.0/0
+ipchains -A forward -j MASQ -p tcp -s 192.168.200.0/24 8080 -d 0.0.0.0/0
+
+ipvsadm -A -t 10.10.10.2:1358 -s rr -p 50
+ipvsadm -A -t 10.10.10.2:8080 -s rr -p 50
--- /dev/null
+#!/bin/sh
+#
+# Startup script for the Keepalived daemon
+#
+# processname: keepalived
+# pidfile: /var/run/keepalived.pid
+# config: /etc/lvs.conf
+# config: /etc/keepalived/keepalived.conf
+
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+# See how we were called.
+case "$1" in
+ start)
+ echo -n "Starting Keepalived for LVS: "
+ sh /etc/lvs.conf
+ daemon keepalived
+ echo
+ ;;
+ stop)
+ echo -n "Shutting down Keepalived for LVS: "
+ killproc keepalived
+ echo
+ ;;
+ *)
+ echo "Usage: $0 {start|stop}"
+ exit 1
+esac
+
+exit 0
EXEC= genhash
CC= gcc
-CFLAGS= -Wall -lmd
-DEFS= genhash.h
-OBJECTS= genhash.o
+CFLAGS= -Wall
+DEFS= genhash.h md5.h
+OBJECTS= md5.o genhash.o
.c.o:
$(CC) -o $@ $(CFLAGS) -c $*.c
$(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
clean:
- rm -f core *.o $(EXEC)
+ rm -f core *.o $(EXEC)
-install:
- cp -av genhash /usr/bin
+install:
+ install -m 755 genhash /usr/bin/
* into the /etc/keepalived/keepalived.conf for the
* HTTP_GET_CHECK.
*
- * Version: $Id: keepalived.c,v 0.2.0 2000/12/09 $
+ * Version: $Id: keepalived.c,v 0.3.0 2001/02/10 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* Changes:
- * Alexandre Cassen : Initial release
+ * Alexandre Cassen : 2000/12/09 Initial release
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
}
}
+char *extract_html(char *buffer, int size_buffer)
+{
+ char *end=buffer+size_buffer;
+
+ while ( buffer < end && !(*buffer++ == '\n' &&
+ (*buffer == '\n' || (*buffer++ == '\r' && *buffer =='\n'))));
+
+ if (*buffer == '\n') return buffer+1;
+ return NULL;
+}
+
int new_sock(int type)
{
int sd;
register int sdesc;
int long_inet;
int rcv_buffer_size=0;
+ long total_length=0;
char *str_request;
+ char *buffertmp;
struct hostent *ip_serv;
struct sockaddr_in adr_serv;
+ struct timeval tv;
+ fd_set rfds, wfds;
+ int rc,val;
+ int arglen;
str_request=(char *)malloc(GET_BUFFER_LENGTH);
- strcpy(str_request,"GET ");
- strcat(str_request,URL);
- strcat(str_request,"\n");
+ buffertmp=(char *)malloc(RCV_BUFFER_LENGTH);
+ memset(buffertmp,0,RCV_BUFFER_LENGTH);
+
+ sprintf(str_request,GETCMD,URL);
if ( (sdesc=new_sock(SOCK_STREAM)) == -1 ) {
- printf("Can not bind remote address\n");
+ printf("-[ Can not bind remote address ]-\n");
+ free(str_request);
+ free(buffertmp);
return(ERROR_SOCKET);
}
long_inet = sizeof(struct sockaddr_in);
if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
- printf("Can not resolve remote host\n");
+ printf("-[ Can not resolve remote host ]-\n");
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
return(ERROR_SOCKET);
}
bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
adr_serv.sin_port=htons(PORT_DST);
- if ( connect(sdesc, (struct sockaddr *)&adr_serv, long_inet) == -1) {
- printf("Can not connect remote host\n");
+ /* Set read/write socket timeout */
+ val=fcntl(sdesc, F_GETFL);
+ fcntl(sdesc, F_SETFL, val | O_NONBLOCK);
+
+ /* Connect the remote host */
+ if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1 ) {
+ switch (errno) {
+ case ETIMEDOUT:
+ case EINTR:
+ case EHOSTUNREACH:
+ printf("-[ Connect error : Timeout ]-\n");
+ break;
+ case ECONNREFUSED:
+ printf("-[ Connect error : Connectiono refused ]-\n");
+ break;
+ case ENETUNREACH:
+ printf("-[ Connect error : Network unreachable ]-\n");
+ break;
+ case EINPROGRESS:
+ printf("-[ NONBLOCK socket connection in progress ]-\n");
+ goto next;
+ default:
+ printf("-[ Connect error : Error code %d (%s) ]-\n",errno,strerror(errno));
+ }
+
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
+ return(ERROR_SOCKET);
+ }
+
+next:
+ /* Timeout settings */
+ tv.tv_sec=SOCKET_TIMEOUT_READ;
+ tv.tv_usec=0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_SET(sdesc,&rfds);
+ FD_SET(sdesc,&wfds);
+
+ rc = select(sdesc+1,NULL,&wfds,NULL,&tv);
+ if (!FD_ISSET(sdesc,&wfds)) {
+ printf("-[ Timeout writing data ]-\n");
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
+ return(ERROR_SOCKET);
+ }
+
+ if (rc <= 0) {
+ printf("-[ select() bad returned descriptor ]-\n");
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
+ return(ERROR_SOCKET);
+ }
+
+ rc = 0;
+ arglen=sizeof(int);
+ if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+ rc = errno;
+
+ if (rc) {
+ printf("-[ Connection failed - error : %d (%s) ]-\n",rc,strerror(rc));
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
return(ERROR_SOCKET);
}
if (send(sdesc,str_request,strlen(str_request),0) == -1) {
- printf("Can not send data to remote host\n");
+ printf("-[ Can not send data to remote host ]-\n");
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
return(ERROR_SOCKET);
}
- rcv_buffer_size=recv(sdesc,buffer,RCV_BUFFER_LENGTH,0);
- if ( rcv_buffer_size == -1 ) {
- printf("Can not recieve data from remote host\n");
+ /* Proceed the HTTP server reply */
+ select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+ printf("-[ Timeout reading data ]-\n");
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
return(ERROR_SOCKET);
}
+ while((rcv_buffer_size = read(sdesc,buffertmp,RCV_BUFFER_LENGTH)) != 0) {
+ if (rcv_buffer_size == -1) {
+ if(errno == EAGAIN) goto end;
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
+ return(ERROR_SOCKET);
+ }
+ printf("-[ Reading data from remote host ]-\n");
+ memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+ memset(buffertmp,0,RCV_BUFFER_LENGTH);
+ total_length += rcv_buffer_size;
+ }
+
+end:
close(sdesc);
free(str_request);
- return(rcv_buffer_size);
+ free(buffertmp);
+ return(total_length);
}
+
int main(int argc, char **argv)
{
char *buffer_http;
- int retcode=0;
- char MDResult[0x40];
+ char *buffer_html;
+ int buffer_http_size=0;
+ char *MDResult;
+ md5_state_t state;
+ md5_byte_t digest[16];
+ int di;
printf(PROG" v"VERSION"\n");
if (argc < 4) {
printf("Usage: %s <IP address> <TCP port> <url path>\n", argv[0]);
- return 0;
+ return(0);
}
buffer_http=(char *)malloc(RCV_BUFFER_LENGTH);
+ MDResult=(char *)malloc(16*2*sizeof(char *));
+ memset(buffer_http,0,RCV_BUFFER_LENGTH);
+ memset(MDResult,0,16*2*sizeof(char *));
- retcode=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
+ buffer_http_size=HTTP_GET(argv[1],atoi(argv[2]),argv[3],buffer_http);
+ buffer_html=extract_html(buffer_http,buffer_http_size);
- if(retcode > 0) {
- printf("\n----[ Buffer Text representation ]----\n");
+ if(buffer_http_size > 0) {
+ printf("---------------------------[ Received Buffer ]----------------------------\n");
printf("%s\n",buffer_http);
- printf("\n----[ Buffer Hexa representation ]----\n");
- printf("Buffer length : %d\n",retcode);
- if(retcode!=0) print_buffer(retcode,buffer_http);
+ printf("--------------------------[ HTTP Header Buffer ]--------------------------\n");
+ print_buffer(buffer_html-buffer_http,buffer_http);
+
+ printf("------------------------------[ HTML Buffer ]-----------------------------\n");
+ print_buffer(buffer_http_size-(buffer_html-buffer_http),buffer_html);
+
+ printf("----------------------------[ HTML MD5 resulting ]------------------------\n");
+ md5_init(&state);
+ md5_append(&state, buffer_html,buffer_http_size-(buffer_html-buffer_http));
+ md5_finish(&state,digest);
+
+ for (di=0; di < 16; ++di)
+ sprintf(MDResult+2*di,"%02x",digest[di]);
- printf("\n----[ MD5 resulting ]----\n");
- MD5Data(buffer_http,retcode,MDResult);
- printf("MD5 256 bits Digest : %s\n",MDResult);
+ printf("MD5 Digest : %s\n",MDResult);
} else {
printf("No buffer returned...\n");
}
+ free(MDResult);
free(buffer_http);
- return 1;
+ return(1);
}
#include <linux/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
+#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>
-#include <md5.h>
+#include <errno.h>
+#include "md5.h"
+
+#define GETCMD "GET %s HTTP/1.0\r\n\r\n"
+
+/* Socket Timeout */
+#define SOCKET_TIMEOUT_READ 3
+#define SOCKET_TIMEOUT_CONNECT 3
/* Sockets connection errors codes */
#define ERROR_SOCKET 0
/* Data buffer length description */
-#define GET_BUFFER_LENGTH 80
+#define GET_BUFFER_LENGTH 180
#define RCV_BUFFER_LENGTH 1024
/* Build version */
--- /dev/null
+/*\r
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.\r
+\r
+ This software is provided 'as-is', without any express or implied\r
+ warranty. In no event will the authors be held liable for any damages\r
+ arising from the use of this software.\r
+\r
+ Permission is granted to anyone to use this software for any purpose,\r
+ including commercial applications, and to alter it and redistribute it\r
+ freely, subject to the following restrictions:\r
+\r
+ 1. The origin of this software must not be misrepresented; you must not\r
+ claim that you wrote the original software. If you use this software\r
+ in a product, an acknowledgment in the product documentation would be\r
+ appreciated but is not required.\r
+ 2. Altered source versions must be plainly marked as such, and must not be\r
+ misrepresented as being the original software.\r
+ 3. This notice may not be removed or altered from any source distribution.\r
+\r
+ L. Peter Deutsch\r
+ ghost@aladdin.com\r
+\r
+ */\r
+/*$Id: md5.c $ */\r
+/*\r
+ Independent implementation of MD5 (RFC 1321).\r
+\r
+ This code implements the MD5 Algorithm defined in RFC 1321.\r
+ It is derived directly from the text of the RFC and not from the\r
+ reference implementation.\r
+\r
+ The original and principal author of md5.c is L. Peter Deutsch\r
+ <ghost@aladdin.com>. Other authors are noted in the change history\r
+ that follows (in reverse chronological order):\r
+\r
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).\r
+ 1999-05-03 lpd Original version.\r
+ */\r
+\r
+#include "md5.h"\r
+\r
+#define T1 0xd76aa478\r
+#define T2 0xe8c7b756\r
+#define T3 0x242070db\r
+#define T4 0xc1bdceee\r
+#define T5 0xf57c0faf\r
+#define T6 0x4787c62a\r
+#define T7 0xa8304613\r
+#define T8 0xfd469501\r
+#define T9 0x698098d8\r
+#define T10 0x8b44f7af\r
+#define T11 0xffff5bb1\r
+#define T12 0x895cd7be\r
+#define T13 0x6b901122\r
+#define T14 0xfd987193\r
+#define T15 0xa679438e\r
+#define T16 0x49b40821\r
+#define T17 0xf61e2562\r
+#define T18 0xc040b340\r
+#define T19 0x265e5a51\r
+#define T20 0xe9b6c7aa\r
+#define T21 0xd62f105d\r
+#define T22 0x02441453\r
+#define T23 0xd8a1e681\r
+#define T24 0xe7d3fbc8\r
+#define T25 0x21e1cde6\r
+#define T26 0xc33707d6\r
+#define T27 0xf4d50d87\r
+#define T28 0x455a14ed\r
+#define T29 0xa9e3e905\r
+#define T30 0xfcefa3f8\r
+#define T31 0x676f02d9\r
+#define T32 0x8d2a4c8a\r
+#define T33 0xfffa3942\r
+#define T34 0x8771f681\r
+#define T35 0x6d9d6122\r
+#define T36 0xfde5380c\r
+#define T37 0xa4beea44\r
+#define T38 0x4bdecfa9\r
+#define T39 0xf6bb4b60\r
+#define T40 0xbebfbc70\r
+#define T41 0x289b7ec6\r
+#define T42 0xeaa127fa\r
+#define T43 0xd4ef3085\r
+#define T44 0x04881d05\r
+#define T45 0xd9d4d039\r
+#define T46 0xe6db99e5\r
+#define T47 0x1fa27cf8\r
+#define T48 0xc4ac5665\r
+#define T49 0xf4292244\r
+#define T50 0x432aff97\r
+#define T51 0xab9423a7\r
+#define T52 0xfc93a039\r
+#define T53 0x655b59c3\r
+#define T54 0x8f0ccc92\r
+#define T55 0xffeff47d\r
+#define T56 0x85845dd1\r
+#define T57 0x6fa87e4f\r
+#define T58 0xfe2ce6e0\r
+#define T59 0xa3014314\r
+#define T60 0x4e0811a1\r
+#define T61 0xf7537e82\r
+#define T62 0xbd3af235\r
+#define T63 0x2ad7d2bb\r
+#define T64 0xeb86d391\r
+\r
+static void\r
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)\r
+{\r
+ md5_word_t\r
+ a = pms->abcd[0], b = pms->abcd[1],\r
+ c = pms->abcd[2], d = pms->abcd[3];\r
+ md5_word_t t;\r
+\r
+#ifndef ARCH_IS_BIG_ENDIAN\r
+# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */\r
+#endif\r
+#if ARCH_IS_BIG_ENDIAN\r
+\r
+ /*\r
+ * On big-endian machines, we must arrange the bytes in the right\r
+ * order. (This also works on machines of unknown byte order.)\r
+ */\r
+ md5_word_t X[16];\r
+ const md5_byte_t *xp = data;\r
+ int i;\r
+\r
+ for (i = 0; i < 16; ++i, xp += 4)\r
+ X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);\r
+\r
+#else /* !ARCH_IS_BIG_ENDIAN */\r
+\r
+ /*\r
+ * On little-endian machines, we can process properly aligned data\r
+ * without copying it.\r
+ */\r
+ md5_word_t xbuf[16];\r
+ const md5_word_t *X;\r
+\r
+ if (!((data - (const md5_byte_t *)0) & 3)) {\r
+ /* data are properly aligned */\r
+ X = (const md5_word_t *)data;\r
+ } else {\r
+ /* not aligned */\r
+ memcpy(xbuf, data, 64);\r
+ X = xbuf;\r
+ }\r
+#endif\r
+\r
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\r
+\r
+ /* Round 1. */\r
+ /* Let [abcd k s i] denote the operation\r
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + F(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 0, 7, T1);\r
+ SET(d, a, b, c, 1, 12, T2);\r
+ SET(c, d, a, b, 2, 17, T3);\r
+ SET(b, c, d, a, 3, 22, T4);\r
+ SET(a, b, c, d, 4, 7, T5);\r
+ SET(d, a, b, c, 5, 12, T6);\r
+ SET(c, d, a, b, 6, 17, T7);\r
+ SET(b, c, d, a, 7, 22, T8);\r
+ SET(a, b, c, d, 8, 7, T9);\r
+ SET(d, a, b, c, 9, 12, T10);\r
+ SET(c, d, a, b, 10, 17, T11);\r
+ SET(b, c, d, a, 11, 22, T12);\r
+ SET(a, b, c, d, 12, 7, T13);\r
+ SET(d, a, b, c, 13, 12, T14);\r
+ SET(c, d, a, b, 14, 17, T15);\r
+ SET(b, c, d, a, 15, 22, T16);\r
+#undef SET\r
+\r
+ /* Round 2. */\r
+ /* Let [abcd k s i] denote the operation\r
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + G(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 1, 5, T17);\r
+ SET(d, a, b, c, 6, 9, T18);\r
+ SET(c, d, a, b, 11, 14, T19);\r
+ SET(b, c, d, a, 0, 20, T20);\r
+ SET(a, b, c, d, 5, 5, T21);\r
+ SET(d, a, b, c, 10, 9, T22);\r
+ SET(c, d, a, b, 15, 14, T23);\r
+ SET(b, c, d, a, 4, 20, T24);\r
+ SET(a, b, c, d, 9, 5, T25);\r
+ SET(d, a, b, c, 14, 9, T26);\r
+ SET(c, d, a, b, 3, 14, T27);\r
+ SET(b, c, d, a, 8, 20, T28);\r
+ SET(a, b, c, d, 13, 5, T29);\r
+ SET(d, a, b, c, 2, 9, T30);\r
+ SET(c, d, a, b, 7, 14, T31);\r
+ SET(b, c, d, a, 12, 20, T32);\r
+#undef SET\r
+\r
+ /* Round 3. */\r
+ /* Let [abcd k s t] denote the operation\r
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define H(x, y, z) ((x) ^ (y) ^ (z))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + H(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 5, 4, T33);\r
+ SET(d, a, b, c, 8, 11, T34);\r
+ SET(c, d, a, b, 11, 16, T35);\r
+ SET(b, c, d, a, 14, 23, T36);\r
+ SET(a, b, c, d, 1, 4, T37);\r
+ SET(d, a, b, c, 4, 11, T38);\r
+ SET(c, d, a, b, 7, 16, T39);\r
+ SET(b, c, d, a, 10, 23, T40);\r
+ SET(a, b, c, d, 13, 4, T41);\r
+ SET(d, a, b, c, 0, 11, T42);\r
+ SET(c, d, a, b, 3, 16, T43);\r
+ SET(b, c, d, a, 6, 23, T44);\r
+ SET(a, b, c, d, 9, 4, T45);\r
+ SET(d, a, b, c, 12, 11, T46);\r
+ SET(c, d, a, b, 15, 16, T47);\r
+ SET(b, c, d, a, 2, 23, T48);\r
+#undef SET\r
+\r
+ /* Round 4. */\r
+ /* Let [abcd k s t] denote the operation\r
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + I(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 0, 6, T49);\r
+ SET(d, a, b, c, 7, 10, T50);\r
+ SET(c, d, a, b, 14, 15, T51);\r
+ SET(b, c, d, a, 5, 21, T52);\r
+ SET(a, b, c, d, 12, 6, T53);\r
+ SET(d, a, b, c, 3, 10, T54);\r
+ SET(c, d, a, b, 10, 15, T55);\r
+ SET(b, c, d, a, 1, 21, T56);\r
+ SET(a, b, c, d, 8, 6, T57);\r
+ SET(d, a, b, c, 15, 10, T58);\r
+ SET(c, d, a, b, 6, 15, T59);\r
+ SET(b, c, d, a, 13, 21, T60);\r
+ SET(a, b, c, d, 4, 6, T61);\r
+ SET(d, a, b, c, 11, 10, T62);\r
+ SET(c, d, a, b, 2, 15, T63);\r
+ SET(b, c, d, a, 9, 21, T64);\r
+#undef SET\r
+\r
+ /* Then perform the following additions. (That is increment each\r
+ of the four registers by the value it had before this block\r
+ was started.) */\r
+ pms->abcd[0] += a;\r
+ pms->abcd[1] += b;\r
+ pms->abcd[2] += c;\r
+ pms->abcd[3] += d;\r
+}\r
+\r
+void\r
+md5_init(md5_state_t *pms)\r
+{\r
+ pms->count[0] = pms->count[1] = 0;\r
+ pms->abcd[0] = 0x67452301;\r
+ pms->abcd[1] = 0xefcdab89;\r
+ pms->abcd[2] = 0x98badcfe;\r
+ pms->abcd[3] = 0x10325476;\r
+}\r
+\r
+void\r
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)\r
+{\r
+ const md5_byte_t *p = data;\r
+ int left = nbytes;\r
+ int offset = (pms->count[0] >> 3) & 63;\r
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);\r
+\r
+ if (nbytes <= 0)\r
+ return;\r
+\r
+ /* Update the message length. */\r
+ pms->count[1] += nbytes >> 29;\r
+ pms->count[0] += nbits;\r
+ if (pms->count[0] < nbits)\r
+ pms->count[1]++;\r
+\r
+ /* Process an initial partial block. */\r
+ if (offset) {\r
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);\r
+\r
+ memcpy(pms->buf + offset, p, copy);\r
+ if (offset + copy < 64)\r
+ return;\r
+ p += copy;\r
+ left -= copy;\r
+ md5_process(pms, pms->buf);\r
+ }\r
+\r
+ /* Process full blocks. */\r
+ for (; left >= 64; p += 64, left -= 64)\r
+ md5_process(pms, p);\r
+\r
+ /* Process a final partial block. */\r
+ if (left)\r
+ memcpy(pms->buf, p, left);\r
+}\r
+\r
+void\r
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])\r
+{\r
+ static const md5_byte_t pad[64] = {\r
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+ };\r
+ md5_byte_t data[8];\r
+ int i;\r
+\r
+ /* Save the length before padding. */\r
+ for (i = 0; i < 8; ++i)\r
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));\r
+ /* Pad to 56 bytes mod 64. */\r
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);\r
+ /* Append the length. */\r
+ md5_append(pms, data, 8);\r
+ for (i = 0; i < 16; ++i)\r
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));\r
+}\r
--- /dev/null
+/*\r
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.\r
+\r
+ This software is provided 'as-is', without any express or implied\r
+ warranty. In no event will the authors be held liable for any damages\r
+ arising from the use of this software.\r
+\r
+ Permission is granted to anyone to use this software for any purpose,\r
+ including commercial applications, and to alter it and redistribute it\r
+ freely, subject to the following restrictions:\r
+\r
+ 1. The origin of this software must not be misrepresented; you must not\r
+ claim that you wrote the original software. If you use this software\r
+ in a product, an acknowledgment in the product documentation would be\r
+ appreciated but is not required.\r
+ 2. Altered source versions must be plainly marked as such, and must not be\r
+ misrepresented as being the original software.\r
+ 3. This notice may not be removed or altered from any source distribution.\r
+\r
+ L. Peter Deutsch\r
+ ghost@aladdin.com\r
+\r
+ */\r
+/*$Id: md5.h $ */\r
+/*\r
+ Independent implementation of MD5 (RFC 1321).\r
+\r
+ This code implements the MD5 Algorithm defined in RFC 1321.\r
+ It is derived directly from the text of the RFC and not from the\r
+ reference implementation.\r
+\r
+ The original and principal author of md5.h is L. Peter Deutsch\r
+ <ghost@aladdin.com>. Other authors are noted in the change history\r
+ that follows (in reverse chronological order):\r
+\r
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);\r
+ added conditionalization for C++ compilation from Martin\r
+ Purschke <purschke@bnl.gov>.\r
+ 1999-05-03 lpd Original version.\r
+ */\r
+\r
+#ifndef md5_INCLUDED\r
+# define md5_INCLUDED\r
+\r
+/*\r
+ * This code has some adaptations for the Ghostscript environment, but it\r
+ * will compile and run correctly in any environment with 8-bit chars and\r
+ * 32-bit ints. Specifically, it assumes that if the following are\r
+ * defined, they have the same meaning as in Ghostscript: P1, P2, P3,\r
+ * ARCH_IS_BIG_ENDIAN.\r
+ */\r
+\r
+typedef unsigned char md5_byte_t; /* 8-bit byte */\r
+typedef unsigned int md5_word_t; /* 32-bit word */\r
+\r
+/* Define the state of the MD5 Algorithm. */\r
+typedef struct md5_state_s {\r
+ md5_word_t count[2]; /* message length in bits, lsw first */\r
+ md5_word_t abcd[4]; /* digest buffer */\r
+ md5_byte_t buf[64]; /* accumulate block */\r
+} md5_state_t;\r
+\r
+#ifdef __cplusplus\r
+extern "C" \r
+{\r
+#endif\r
+\r
+/* Initialize the algorithm. */\r
+#ifdef P1\r
+void md5_init(P1(md5_state_t *pms));\r
+#else\r
+void md5_init(md5_state_t *pms);\r
+#endif\r
+\r
+/* Append a string to the message. */\r
+#ifdef P3\r
+void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));\r
+#else\r
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);\r
+#endif\r
+\r
+/* Finish the message and return the digest. */\r
+#ifdef P2\r
+void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));\r
+#else\r
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+} /* end extern "C" */\r
+#endif\r
+\r
+#endif /* md5_INCLUDED */\r
--- /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: httpget.c,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Use a non blocking timeouted tcp connection.
+ * <+> Adding support for multi-url. Can perform a HTTP GET
+ * over multiple url on the same tcp service (usefull for
+ * HTTP server owning multiple applications servers).
+ * <+> Adding HTTP GET retry.
+ * <+> Remove the libmd call, use the L. Peter Deutsch
+ * independant md5 implementation.
+ * <+> Parse the whole HTTP get reply, computing a md5sum
+ * over the html response part.
+ * <+> Adding delay support between HTTP get retry.
+ *
+ * Alexandre Cassen : Initial release : 2000/12/09
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "httpget.h"
+
+char *extract_html(char *buffer, int size_buffer)
+{
+ char *end=buffer+size_buffer;
+
+ while ( buffer < end &&
+ !(*buffer++ == '\n' &&
+ (*buffer == '\n' || (*buffer ++ == '\r' && *buffer =='\n'))));
+
+ if (*buffer == '\n') return buffer+1;
+ return NULL;
+}
+
+int GET(char *IP_DST, char *PORT_DST, char *URL, char *buffer,int ctimeout)
+{
+ register int sdesc;
+ int long_inet;
+ int rcv_buffer_size=0;
+ long total_length=0;
+ char *str_request;
+ struct hostent *ip_serv;
+ struct sockaddr_in adr_serv;
+ struct linger li = { 0 };
+ char *debugmsg;
+ char *buffertmp;
+ struct timeval tv;
+ fd_set rfds, wfds;
+ int rc, flags;
+ int arglen;
+
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+ buffertmp=(char *)malloc(GET_BUFFER_LENGTH);
+ str_request=(char *)malloc(GET_REQUEST_BUFFER_LENGTH);
+ memset(buffertmp,0,GET_BUFFER_LENGTH);
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ memset(str_request,0,GET_REQUEST_BUFFER_LENGTH);
+
+ sprintf(str_request,GETCMD,URL);
+
+ if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ return(SOCKET_ERROR);
+ }
+
+ /* free the tcp port after closing the socket descriptor */
+ li.l_onoff=1;
+ li.l_linger=0;
+ setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+ long_inet = sizeof(struct sockaddr_in);
+
+ if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Can not resolve remote host %s\n",IP_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ memset(&adr_serv,0,long_inet);
+ adr_serv.sin_family=ip_serv->h_addrtype;
+ bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+ adr_serv.sin_port=htons(atoi(PORT_DST));
+
+ /* Set read/write socket timeout */
+ flags=fcntl(sdesc, F_GETFL);
+ fcntl(sdesc, F_SETFL, flags | O_NONBLOCK);
+
+ /* Connect the remote host */
+ if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1) {
+ switch (errno) {
+ case ETIMEDOUT:
+ case EINTR:
+ case EHOSTUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ECONNREFUSED:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ENETUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case EINPROGRESS: // NONBLOCK socket connection in progress
+ goto next;
+ default:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ }
+
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+next:
+ /* Timeout settings */
+ tv.tv_sec=ctimeout;
+ tv.tv_usec=0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_SET(sdesc,&rfds);
+ FD_SET(sdesc,&wfds);
+
+ rc = select(sdesc+1,NULL,&wfds,NULL,&tv);
+ if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Timeout writing data to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ if (rc < 0) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ rc = 0;
+ arglen=sizeof(int);
+ if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+ rc = errno;
+
+ if (rc) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending the http get request */
+ if (send(sdesc,str_request,strlen(str_request),0) == -1) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Can not send data to remote host %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Proceed the HTTP server reply */
+ select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Timeout reading data from %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ while((rcv_buffer_size = read(sdesc,buffertmp,GET_BUFFER_LENGTH)) != 0) {
+ if ( rcv_buffer_size == -1 ) {
+ if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : Can not recieve data from remote host %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+ memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+ memset(buffertmp,0,GET_BUFFER_LENGTH);
+ total_length += rcv_buffer_size;
+ }
+
+end:
+ close(sdesc);
+ free(str_request);
+ free(debugmsg);
+ free(buffertmp);
+ return(total_length);
+}
+
+int HTTP_GET(char *IP_DST,char *PORT_DST,char *URL,char *MDResult,int ctimeout,int getretry,int rdelay)
+{
+ char *buffer_http;
+ char *buffer_html;
+ char *debugmsg;
+ md5_state_t state;
+ md5_byte_t digest[16];
+ int buffer_http_size=0;
+ int split_offset=0;
+ int nb_retry=0;
+ int di;
+
+
+ buffer_http=(char *)malloc(GET_BUFFER_LENGTH);
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+
+ while (nb_retry < getretry) {
+ sleep(rdelay);
+ memset(buffer_http,0,GET_BUFFER_LENGTH);
+
+ buffer_http_size=GET(IP_DST,PORT_DST,URL,buffer_http,ctimeout);
+ buffer_html=extract_html(buffer_http,buffer_http_size);
+
+ if (buffer_http_size > 0) {
+ if ((buffer_http_size-(buffer_html-buffer_http)) == 0) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : No html buffer received from %s:%s. Retry\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ nb_retry++;
+ } else {
+ md5_init(&state);
+ md5_append(&state, buffer_html,buffer_http_size-(buffer_html-buffer_http));
+ md5_finish(&state,digest);
+ for (di=0; di < 16; ++di)
+ sprintf(MDResult+2*di,"%02x",digest[di]);
+ free(debugmsg);
+ free(buffer_http);
+ return(1);
+ }
+ } else {
+ free(debugmsg);
+ free(buffer_http);
+ return(0);
+ }
+ }
+
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"HTTP_GET : No html buffer received from %s:%s after %d retry\n",IP_DST,PORT_DST,getretry);
+ logmessage(debugmsg);
+#endif
+
+ free(debugmsg);
+ free(buffer_http);
+ return(0);
+}
*
* Part: httpget.c include file.
*
- * Version: $Id: httpget.h,v 0.2.1 2000/12/09 $
+ * Version: $Id: httpget.h,v 0.2.6 2001/03/01 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* Changes:
- * Alexandre Cassen : Initial release
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Change the GET method.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
-#include <md5.h>
+#include <errno.h>
+#include "md5.h"
#define SOCKET_ERROR 0
#define SOCKET_SUCCESS 1
+#define GETCMD "GET %s HTTP/1.0\r\n\r\n"
+
#define MD5_BUFFER_LENGTH 32
#define GET_REQUEST_BUFFER_LENGTH 128
#define GET_BUFFER_LENGTH 2048
#define LOGBUFFER_LENGTH 100
-/* prototypes */
-int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x40]);
-
#endif
* Alexandre Cassen : 2001/01/01 :
* <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
* Call this function in ICMP_RCV_ECHOREPLY with 1s timeout.
- * <+> Added a timer (2s timeouted) in ICMP_RCV_ECHOREPLY to check
- * ECHO_REPLY. Check perform on icmp type flag, remote ip address.
+ * <+> Added a timer (2s timeouted) in ICMP_RCV_ECHOREPLY to check.
+ * Check perform on icmp type flag, remote ip address.
* <+> Added a 3 time ECHO_REQUEST send retry.
*
* Alexandre Cassen : 2000/12/09 : Initial release
if (result<0) {
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : icmp timeout to [%s]...\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
}
#endif
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : Received packet too short according to ICMP protocol from [%s]...\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
}
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] retry\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
/* timer to evaluate packet loosed */
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] packet losed\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
close(sockfd);
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : Can't send ECHO_REQUEST to [%s]\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
free(debugmsg);
return(SOCKET_ERROR);
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : Reexpedite ECHO_REQUEST to [%s]\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
loop=(retry==NB_RETRY)?0:1;
}
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] after 3 try\n",IP_DST);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
free(debugmsg);
return(SOCKET_ERROR);
#define select_time (DEFAULT_SELECT_TIME * 100)
/* prototypes */
-int ICMP_CHECK(char *IP_DST);
+//int ICMP_CHECK(char *IP_DST);
#endif
#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
* Part: IPVS Kernel wrapper. Use setsockopt call to add/remove
* server to/from the loadbalanced server pool.
*
- * Version: $Id: ipvswrapper.c,v 0.2.1 2000/12/09 $
+ * Version: $Id: ipvswrapper.c,v 0.2.1 2001/03/01 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* Changes:
- * Alexandre Cassen : Initial release
+ * Alexandre Cassen : 2000/12/09 : Initial release
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
ctl.u.vs_user.weight = atoi(vserver->svr->weight);
- if (strcmp(vserver->svr->loadbalancing_kind,"NAT")==0)
+ if (strcmp(vserver->loadbalancing_kind,"NAT")==0)
ctl.u.vs_user.masq_flags = 0;
else
- if (strcmp(vserver->svr->loadbalancing_kind,"DR")==0)
+ if (strcmp(vserver->loadbalancing_kind,"DR")==0)
ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_DROUTE;
else
- if (strcmp(vserver->svr->loadbalancing_kind,"TUN")==0)
+ if (strcmp(vserver->loadbalancing_kind,"TUN")==0)
ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_TUNNEL;
else {
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ipvs_pool_cmd : service [%s:%s] [%s] unknown routing method...\n",
vserver->svr->addr_ip, vserver->svr->addr_port,
- vserver->svr->loadbalancing_kind);
- logmessage(debugmsg,getpid());
- logmessage("ipvs_pool_cmd : Check your configuration file...\n",getpid());
+ vserver->loadbalancing_kind);
+ logmessage(debugmsg);
+ logmessage("ipvs_pool_cmd : Check your configuration file...\n");
free(debugmsg);
return(IPVS_ERROR);
}
ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff); /* f:f:f:f for default netmask */
- ctl.u.vs_user.protocol = (strcmp(vserver->svr->service_type,"UDP")==0)?IPPROTO_UDP:IPPROTO_TCP;
- ctl.u.vs_user.timeout = (strcmp(vserver->timeout_persistence,"NULL")==0)?0:atoi(vserver->timeout_persistence);
+ ctl.u.vs_user.protocol = (strcmp(vserver->service_type,"UDP")==0)?IPPROTO_UDP:IPPROTO_TCP;
+ ctl.u.vs_user.timeout = (atoi(vserver->timeout_persistence)==0)?0:atoi(vserver->timeout_persistence);
ctl.u.vs_user.vfwmark = 0;
ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (sockfd == -1) {
#ifdef DEBUG
- logmessage("ipvs__pool_cmd : Can not initialize SOCK_RAW descriptor\n",getpid());
+ logmessage("ipvs__pool_cmd : Can not initialize SOCK_RAW descriptor\n");
#endif
free(debugmsg);
return IPVS_ERROR;
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ipvs_pool_cmd : Virtual service [%s:%s] not defined.\n",
vserver->addr_ip, vserver->addr_port);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
close(sockfd);
free(debugmsg);
#ifdef DEBUG
memset(debugmsg,0,LOGBUFFER_LENGTH);
sprintf(debugmsg,"ipvs_pool_cmd : No such destination %s\n",vserver->svr->addr_ip);
- logmessage(debugmsg,getpid());
+ logmessage(debugmsg);
#endif
close(sockfd);
free(debugmsg);
#define LOGBUFFER_LENGTH 100
-/* prototypes */
-int ipvs_pool_cmd(int cmd, virtualserver *vserver);
-
#endif
*
* Part: Main program structure.
*
- * Version: $Id: keepalived.c,v 0.2.3 2001/01/01 $
+ * Version: $Id: keepalived.c,v 0.2.6 2001/03/01 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* Changes:
- * Alexandre Cassen : 2001/01/01 :
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Adding support for multi-url md5sum check.
+ * <+> Adding pidfile lock.
* <+> Change the signalhandling.
+ * <+> Change the dynamic data structure.
+ * <+> Use a global var to stock the daemon pid.
*
* Alexandre Cassen : 2000/12/09 : Initial release
*
int main(int argc, char **argv)
{
+ struct sigaction nact, oact;
+
printf(PROG" v"VERSION"\n");
if (chdir(CONF_HOME_DIR)) {
exit(1);
}
- logmessage("Starting keepalived daemon\n",getpid());
+ initdaemonpid(getpid());
+ logmessage("Starting keepalived daemon\n");
switch (fork()) {
case -1:
return 0;
}
- if (signal(SIGTERM,sig_handler) == SIG_IGN)
- signal(SIGTERM,SIG_IGN);
- signal(SIGINT,SIG_IGN);
- signal(SIGHUP,SIG_IGN);
+ initdaemonpid(getpid());
+ if(keepalived_running()) {
+ logmessage("Keepalived is already running.\n");
+ return(0);
+ } else
+ if(!pidfile_write(getpid()))
+ logmessage("Can not write keepalived pidfile.\n");
+
+ /* init signal handling */
+ sigemptyset(&nact.sa_mask);
+ nact.sa_handler = sig_handler;
+ nact.sa_flags = SA_RESTART;
+ sigaction(SIGALRM,&nact,&oact);
+ sigaction(SIGTERM,&nact,&oact);
+ sigaction(SIGKILL,&nact,&oact);
+ sigaction(SIGSEGV,&nact,&oact);
+ sigaction(SIGHUP,&nact,&oact);
+ sigaction(SIGINT,&nact,&oact);
- if ((lstVS=(virtualserver *)ConfReader(lstVS,delay_loop))==NULL) {
- logmessage("Config file contain no data\n",getpid());
+ if ((lstCONF=(configuration_data *)ConfReader(lstCONF))==NULL) {
+ logmessage("Config file contain no data\n");
exit(0);
}
- if (!init_services(lstVS)) {
- logmessage("Ending keepalived daemon\n",getpid());
+ logmessage("Using LVS dynamic data representation :\n");
+ PrintConf(lstCONF);
+
+ if (!init_services(lstCONF->lvstopology)) {
+ logmessage("Ending keepalived daemon\n");
return 0;
}
- logmessage("Using LVS dynamic data representation :\n",getpid());
- PrintLst(lstVS);
-
while (keep_going) {
- perform_checks(lstVS);
- sleep(delay_loop);
+ perform_checks(lstCONF);
+ sleep(atoi(lstCONF->delay_loop));
}
-
- return 0;
}
-void sig_handler(int signum)
+static void sig_handler(int signum)
{
keep_going=0;
- ClearLst(lstVS);
- logmessage("Ending keepalived daemon\n",getpid());
- signal(signum,sig_handler);
+ ClearConf(lstCONF);
+ logmessage("Ending keepalived daemon\n");
+ pidfile_rm();
+ exit(1);
}
void perform_ipvs(int alive, virtualserver *lstptr)
sprintf(logbuffer,"Adding service [%s:%s] to VS [%s:%s]\n",
lstptr->svr->addr_ip,lstptr->svr->addr_port,
lstptr->addr_ip,lstptr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
ipvs_pool_cmd(IPVS_CMD_ADD,lstptr);
} else {
lstptr->svr->alive=alive;
sprintf(logbuffer,"Removing service [%s:%s] from VS [%s:%s]\n",
lstptr->svr->addr_ip,lstptr->svr->addr_port,
lstptr->addr_ip,lstptr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
ipvs_pool_cmd(IPVS_CMD_DEL,lstptr);
}
free(logbuffer);
return 1;
}
-void perform_checks(virtualserver * lstptr)
+void perform_checks(configuration_data *lstconf)
{
- char MD5Result[0x40];
+ char *MD5Result;
+ virtualserver *lstptr;
realserver *pointersvr;
+ urls *pointerurls;
char *logbuffer;
+ int connectionerror;
+ int digesterror;
+
+ lstptr=lstconf->lvstopology;
logbuffer=(char *)malloc(LOGBUFFER_LENGTH);
+ MD5Result=(char *)malloc(16*2*sizeof(char *));
while(lstptr != NULL) {
pointersvr=lstptr->svr;
while(lstptr->svr != NULL) {
- if (strcmp(lstptr->svr->keepalive_method,"ICMP_CHECK") == 0) {
+ if (lstptr->svr->method->flag_type == ICMP_CHECK_ID) {
if (ICMP_CHECK(lstptr->svr->addr_ip)) {
-#ifdef DEBUG
- logmessage("ICMP check succeed\n",getpid());
-#endif
+
if (!lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"ICMP check succeed to %s.\n",lstptr->svr->addr_ip);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(1,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> ICMP CHECK succeed on service <=\n\n"
+ "The service has been added to the server pool\n");
}
} else {
-#ifdef DEBUG
- logmessage("ICMP check failed\n",getpid());
-#endif
if (lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"ICMP check failed to %s.\n",lstptr->svr->addr_ip);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(0,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> ICMP CHECK failed on service <=\n\n"
+ "The service has been removed from the server pool\n");
}
}
}
- if (strcmp(lstptr->svr->keepalive_method,"TCP_CHECK") == 0) {
- if (TCP_CHECK(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port)) {
-#ifdef DEBUG
- logmessage("TCP check succeed\n",getpid());
-#endif
+ if (lstptr->svr->method->flag_type == TCP_CHECK_ID) {
+ if (TCP_CHECK(lstptr->svr->addr_ip,lstptr->svr->addr_port)) {
if (!lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"TCP check succeed to %s:%s.\n",lstptr->svr->addr_ip,
lstptr->svr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(1,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> TCP CHECK succeed on service <=\n\n"
+ "The service has been added to the server pool\n");
}
} else {
-#ifdef DEBUG
- logmessage("TCP check failed\n",getpid());
-#endif
if (lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"TCP check failed to %s:%s.\n",lstptr->svr->addr_ip,
lstptr->svr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(0,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> TCP CHECK failed on service <=\n\n"
+ "The service has been removed from the server pool\n");
}
}
}
- if (strcmp(lstptr->svr->keepalive_method,"HTTP_GET") == 0) {
+ if (lstptr->svr->method->flag_type == HTTP_GET_ID) {
+ connectionerror=0;
+ digesterror=0;
+
+ /* perform the multi urls md5 check */
+ pointerurls=lstptr->svr->method->http_get->check_urls;
+ while((lstptr->svr->method->http_get->check_urls != NULL) &&
+ !connectionerror && !digesterror) {
+ memset(MD5Result,0,16*2*sizeof(char *));
+
+ if(!HTTP_GET(lstptr->svr->addr_ip,lstptr->svr->addr_port,
+ lstptr->svr->method->http_get->check_urls->url,MD5Result,
+ atoi(lstptr->svr->method->http_get->connection_to),
+ atoi(lstptr->svr->method->http_get->nb_get_retry),
+ atoi(lstptr->svr->method->http_get->delay_before_retry)))
+ connectionerror=1;
+
+ if (strcmp(lstptr->svr->method->http_get->check_urls->digest,MD5Result) != 0)
+ digesterror=1;
+
+ lstptr->svr->method->http_get->check_urls=(urls *)lstptr->svr->method->http_get->check_urls->next;
+ }
+ lstptr->svr->method->http_get->check_urls=pointerurls;
+
+ if(!connectionerror) {
- if(HTTP_GET(lstptr->addr_ip,lstptr->svr->addr_ip,lstptr->svr->addr_port,
- lstptr->svr->keepalive_url,MD5Result)) {
+ if (!digesterror) {
- if (strcmp(lstptr->svr->keepalive_result,MD5Result) == 0) {
-#ifdef DEBUG
- logmessage("HTTP GET check succeed\n",getpid());
-#endif
if (!lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"HTTP GET check succeed to %s:%s.\n",lstptr->svr->addr_ip,
lstptr->svr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(1,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"UP","=> HTTP GET check succeed on service <=\n\n"
+ "The service has been added to the server pool\n");
}
} else {
-#ifdef DEBUG
- logmessage("HTTP GET check failed\n",getpid());
-#endif
if (lstptr->svr->alive) {
memset(logbuffer,0,LOGBUFFER_LENGTH);
sprintf(logbuffer,"HTTP GET check failed to %s:%s.\n",lstptr->svr->addr_ip,
lstptr->svr->addr_port);
- logmessage(logbuffer,getpid());
+ logmessage(logbuffer);
perform_ipvs(0,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> HTTP GET check failed on service <=\n\n"
+ "The service has been removed from the server pool\n");
}
}
} else {
if(lstptr->svr->alive) {
perform_ipvs(0,lstptr);
+ SMTP_SEND_ALERTES(lstconf,lstptr,"DOWN","=> HTTP GET check failed on service <=\n\n"
+ "The service has been removed from the server pool\n");
}
}
lstptr->svr=pointersvr;
lstptr=(virtualserver *)lstptr->next;
}
+ free(MD5Result);
free(logbuffer);
}
#include <fcntl.h>
#include "cfreader.h"
+#include "smtpwrapper.h"
#include "icmpcheck.h"
#include "tcpcheck.h"
#include "httpget.h"
/* Global variables */
volatile sig_atomic_t keep_going = 1;
-virtualserver *lstVS;
-int delay_loop = 60;
+configuration_data *lstCONF;
/* Build version */
#define PROG "keepalived"
-#define VERSION "0.2.3 (01/01, 2001), Alexandre Cassen"
+#define VERSION "0.2.6 (03/01, 2001), Alexandre Cassen"
/* prototypes */
-void sig_handler(int signum);
-void perform_checks(virtualserver * lstptr);
+static void sig_handler(int signum);
+void perform_checks(configuration_data * lstconf);
int init_services(virtualserver *lstptr);
#endif
+++ /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: cfreader.c,v 0.2.1 2000/12/09 $
- *
- * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- * Alexandre Cassen : Initial release
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "cfreader.h"
-
-int AlreadyExist_VS(virtualserver *lstptr, char ip[16], char port[6])
-{
- virtualserver *pointerptr=lstptr;
-
- while(lstptr != NULL) {
- if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
- lstptr=pointerptr;
- return 1;
- }
- lstptr=(virtualserver *)lstptr->next;
- }
- lstptr=pointerptr;
- return 0;
-}
-
-int AlreadyExist_SVR(realserver *lstptr, char ip[16], char port[6])
-{
- realserver *pointerptr=lstptr;
-
- while(lstptr != NULL) {
- if((strcmp(lstptr->addr_ip,ip)==0) && (strcmp(lstptr->addr_port,port)==0)) {
- lstptr=pointerptr;
- return 1;
- }
- lstptr=(realserver *)lstptr->next;
- }
- lstptr=pointerptr;
- return 0;
-}
-
-virtualserver * AddItem_VS(virtualserver *lstptr, char ip[16], char port[6], char sched[6], char tpersistence[4])
-{
- virtualserver *pointerlst=lstptr;
-
- if(AlreadyExist_VS(lstptr,ip,port)) return lstptr;
-
- if (lstptr != NULL) {
- while(lstptr->next != NULL) lstptr=(virtualserver *)lstptr->next;
- lstptr->next=(struct virtualserver *)malloc(sizeof(virtualserver));
- lstptr=(virtualserver *)lstptr->next;
- lstptr->svr=NULL;
- lstptr->next=NULL;
-
- /* Fill in the data structure */
- strncat(lstptr->addr_ip,ip,sizeof(lstptr->addr_ip));
- strncat(lstptr->addr_port,port,sizeof(lstptr->addr_port));
- strncat(lstptr->sched,sched,sizeof(lstptr->sched));
- strncat(lstptr->timeout_persistence,tpersistence,sizeof(lstptr->timeout_persistence));
-
- return pointerlst;
- } else {
- lstptr=(virtualserver *)malloc(sizeof(virtualserver));
- lstptr->svr=NULL;
- lstptr->next=NULL;
-
- /* Fill in the data structure */
- strncat(lstptr->addr_ip,ip,sizeof(lstptr->addr_ip));
- strncat(lstptr->addr_port,port,sizeof(lstptr->addr_port));
- strncat(lstptr->sched,sched,sizeof(lstptr->sched));
- strncat(lstptr->timeout_persistence,tpersistence,sizeof(lstptr->timeout_persistence));
-
- return lstptr;
- }
-}
-
-virtualserver * AddItem_SVR(virtualserver *lstvs,
- char ip_vs[16], char port_vs[6],
- realserver *server)
-{
- virtualserver *pointerlst=lstvs;
- realserver *pointersvr;
-
-
- while( (lstvs->next != NULL) &&
- !((strcmp(lstvs->addr_ip,ip_vs)==0) &&
- (strcmp(lstvs->addr_port,port_vs)==0)) )
- lstvs=(virtualserver *)lstvs->next;
-
- if( (strcmp(lstvs->addr_ip,ip_vs)==0) &&
- (strcmp(lstvs->addr_port,port_vs)==0) ) {
-
- if(AlreadyExist_SVR(lstvs->svr,server->addr_ip,server->addr_port)) return pointerlst;
-
- if (lstvs->svr != NULL) {
- pointersvr=lstvs->svr;
-
- while(lstvs->svr->next != NULL) lstvs->svr=(realserver *)lstvs->svr->next;
-
- lstvs->svr->next=(struct realserver *)server;
-
- lstvs->svr=pointersvr;
- } else {
- lstvs->svr=(realserver *)server;
- }
- }
- return pointerlst;
-}
-
-void PrintLst(virtualserver * lstptr)
-{
- realserver *pointersvr;
- char *tempbuff;
-
- tempbuff=(char *)malloc(TEMPBUFFERLENGTH);
-
- if(lstptr == NULL)
- printf("Queue empty !!!\n");
- else
- while(lstptr != NULL) {
- memset(tempbuff,0,TEMPBUFFERLENGTH);
- sprintf(tempbuff,"VS IP = %s, Port = %s, SCHED = %s, PERSISTENCE TIMEOUT = %s\n",
- lstptr->addr_ip, lstptr->addr_port,
- lstptr->sched, lstptr->timeout_persistence);
- logmessage(tempbuff,getpid());
- pointersvr=lstptr->svr;
- while(lstptr->svr != NULL) {
- memset(tempbuff,0,TEMPBUFFERLENGTH);
- sprintf(tempbuff," -> SVR IP = %s, Port = %s\n",lstptr->svr->addr_ip,lstptr->svr->addr_port);
- logmessage(tempbuff,getpid());
-
- memset(tempbuff,0,TEMPBUFFERLENGTH);
- sprintf(tempbuff," -> KM = %s, KA = %s, KU = %s, KR = %s\n",
- lstptr->svr->keepalive_method, lstptr->svr->keepalive_url,
- lstptr->svr->keepalive_algo, lstptr->svr->keepalive_result);
- logmessage(tempbuff,getpid());
-
- memset(tempbuff,0,TEMPBUFFERLENGTH);
- sprintf(tempbuff," -> LB = %s, Weight = %s, ST = %s, Alive = %d\n",
- lstptr->svr->loadbalancing_kind, lstptr->svr->weight,
- lstptr->svr->service_type, lstptr->svr->alive);
- logmessage(tempbuff,getpid());
-
- lstptr->svr=(realserver *)lstptr->svr->next;
- }
- lstptr->svr=pointersvr;
- lstptr=(virtualserver *)lstptr->next;
- }
- free(tempbuff);
-}
-
-realserver * RemoveSVR(realserver * lstptr)
-{
- realserver *t;
-
-// printf(" Removing SVR : (%s,%s)\n",lstptr->addr_ip,lstptr->addr_port);
- t=(realserver *)lstptr->next;
- free(lstptr);
- return t;
-}
-
-virtualserver * RemoveVS(virtualserver * lstptr)
-{
- virtualserver *t;
-
-// printf("Removing VS : (%s,%s)\n",lstptr->addr_ip,lstptr->addr_port);
- t=(virtualserver *)lstptr->next;
- while(lstptr->svr != NULL) lstptr->svr=RemoveSVR(lstptr->svr);
- free(lstptr);
- return t;
-}
-
-void ClearLst(virtualserver * lstptr)
-{
- while(lstptr != NULL) {
- lstptr=RemoveVS(lstptr);
- }
-}
-
-virtualserver * AddItem(virtualserver *lstvs, char ip_vs[16], char port_vs[6],
- char ip_svr[16], char port_svr[16], char kmethod[12],
- char kurl[101],char kalgo[11], char kresult[33], char lbkind[6],
- char weight[4], char stype[4])
-{
- realserver *server;
- server=(realserver *)malloc(sizeof(realserver));
-
- strncat(server->addr_ip,ip_svr,sizeof(server->addr_ip));
- strncat(server->addr_port,port_svr,sizeof(server->addr_port));
- strncat(server->keepalive_method,kmethod,sizeof(server->keepalive_method));
- strncat(server->keepalive_url,kurl,sizeof(server->keepalive_url));
- strncat(server->keepalive_algo,kalgo,sizeof(server->keepalive_algo));
- strncat(server->keepalive_result,kresult,sizeof(server->keepalive_result));
- strncat(server->loadbalancing_kind,lbkind,sizeof(server->loadbalancing_kind));
- strncat(server->weight,weight,sizeof(server->weight));
- strncat(server->service_type,stype,sizeof(server->service_type));
-
- server->alive=1;
- server->next=NULL;
-
- lstvs=AddItem_SVR(lstvs,ip_vs,port_vs,server);
-
- return lstvs;
-}
-
-virtualserver * ConfReader(virtualserver *lst_vs, int delay_loop)
-{
- FILE *stream;
- char *string="";
- virtualserver *vsfill;
- realserver *svrfill;
-
- lst_vs=NULL; /* Initialise the dynamic data structure */
-
- string=(char *)malloc(TEMPBUFFERLENGTH);
- vsfill=(virtualserver *)malloc(sizeof(virtualserver));
- svrfill=(realserver *)malloc(sizeof(realserver));
- svrfill->alive=1;
- svrfill->next=NULL;
-
- stream=fopen(CONFFILE,"r");
- if(stream==NULL) {
- logmessage("ConfReader : Can not read the config file\n",getpid());
- return(NULL);
- }
-
- while(!feof(stream)) {
- fscanf(stream,"%s",string);
- if(strcmp(string,DELAYWORD) == 0) {
- fscanf(stream,"%s",string);
- delay_loop=atoi(string);
- }
- if(strcmp(string,VSWORD) == 0) {
- fscanf(stream,"%s",vsfill->addr_ip);
- fscanf(stream,"%s",vsfill->addr_port);
- fscanf(stream,"%s",vsfill->sched);
- fscanf(stream,"%s",vsfill->timeout_persistence);
- lst_vs = AddItem_VS(lst_vs,vsfill->addr_ip,vsfill->addr_port,vsfill->sched,
- vsfill->timeout_persistence);
- fscanf(stream,"%s",string);
- fscanf(stream,"%s",string);
- do {
- if(strcmp(string,SVRWORD) == 0) {
- fscanf(stream,"%s",svrfill->addr_ip);
- fscanf(stream,"%s",svrfill->addr_port);
- fscanf(stream,"%s",string);
- fscanf(stream,"%s",svrfill->keepalive_method);
- fscanf(stream,"%s",svrfill->keepalive_url);
- fscanf(stream,"%s",svrfill->keepalive_algo);
- fscanf(stream,"%s",svrfill->keepalive_result);
- fscanf(stream,"%s",svrfill->loadbalancing_kind);
- fscanf(stream,"%s",svrfill->weight);
- fscanf(stream,"%s",svrfill->service_type);
- fscanf(stream,"%s",string);
-
- lst_vs = AddItem(lst_vs,vsfill->addr_ip,vsfill->addr_port,
- svrfill->addr_ip,svrfill->addr_port,svrfill->keepalive_method,
- svrfill->keepalive_url,svrfill->keepalive_algo,
- svrfill->keepalive_result,svrfill->loadbalancing_kind,
- svrfill->weight,
- svrfill->service_type);
- }
- fscanf(stream,"%s",string);
- } while(strcmp(string,ENDFLAG) != 0);
- }
- }
-
- free(string);
- free(vsfill);
- free(svrfill);
- fclose(stream);
-
- return lst_vs;
-}
+++ /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: cfreader.h,v 0.2.1 2000/12/09 $
- *
- * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- * Alexandre Cassen : Initial release
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef CFREADER_H
-#define CFREADER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define CONFFILE "keepalived.conf"
-
-#define TEMPBUFFERLENGTH 100
-
-#define DELAYWORD "delay_loop"
-#define VSWORD "virtual_server"
-#define SVRWORD "real_server"
-#define BEGINFLAG "{"
-#define ENDFLAG "}"
-
-/* Structure definition */
-typedef struct _real_server {
- char addr_ip[15+1];
- char addr_port[5+1];
- char keepalive_method[11+1];
- char keepalive_url[100+1];
- char keepalive_algo[10+1];
- char keepalive_result[32+1];
- char loadbalancing_kind[5+1];
- char weight[3+1];
- char service_type[3+1];
- int alive;
-
- struct realserver *next;
-} realserver;
-
-typedef struct _virtual_server {
- char addr_ip[15+1];
- char addr_port[5+1];
- char sched[5+1];
- char timeout_persistence[4];
- realserver *svr;
-
- struct virtualserver *next;
-} virtualserver;
-
-
-/* prototypes */
-virtualserver * ConfReader(virtualserver *lst_vs, int delay_loop);
-void ClearLst(virtualserver * lstptr);
-void PrintLst(virtualserver * lstptr);
-
-#endif
+++ /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: httpget.c,v 0.2.1 2000/12/09 $
- *
- * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- * Alexandre Cassen : Initial release
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "httpget.h"
-
-int GET(char *IP_SRC,char *IP_DST, char *PORT_DST, char *URL, char *buffer)
-{
- register int sdesc;
- int long_inet;
- int rcv_buffer_size=0;
- char *str_request;
- struct hostent *ip_serv;
- struct sockaddr_in adr_serv;
- struct linger li = { 0 };
- char *debugmsg;
-
- if (!TCP_CHECK(IP_SRC,IP_DST,PORT_DST)) {
-#ifdef DEBUG
- logmessage("HTTP_GET : TCP check failed...\n",getpid());
-#endif
- return 0;
- }
-
- debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
- str_request=(char *)malloc(GET_REQUEST_BUFFER_LENGTH);
- strcpy(str_request,"GET ");
- strcat(str_request,URL);
- strcat(str_request,"\n");
-
- if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"HTTP_GET : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(str_request);
- free(debugmsg);
- return(SOCKET_ERROR);
- }
-
- /* free the tcp port after closing the socket descriptor */
- li.l_onoff=1;
- li.l_linger=0;
- setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
- long_inet = sizeof(struct sockaddr_in);
-
- if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"HTTP_GET : Can not resolve remote host %s\n",IP_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(str_request);
- free(debugmsg);
- close(sdesc);
- return(SOCKET_ERROR);
- }
-
- memset(&adr_serv,0,long_inet);
- adr_serv.sin_family=ip_serv->h_addrtype;
- bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
- adr_serv.sin_port=htons(atoi(PORT_DST));
-
- if ( connect(sdesc, (struct sockaddr *)&adr_serv, long_inet) == -1) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"HTTP_GET : Can not connect remote host %s:%s\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(str_request);
- free(debugmsg);
- close(sdesc);
- return(SOCKET_ERROR);
- }
-
- if (send(sdesc,str_request,strlen(str_request),0) == -1) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"HTTP_GET : Can not send data to remote host %s:%s\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(str_request);
- free(debugmsg);
- close(sdesc);
- return(SOCKET_ERROR);
- }
-
- rcv_buffer_size=recv(sdesc,buffer,GET_BUFFER_LENGTH,0);
- if ( rcv_buffer_size == -1 ) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"HTTP_GET : Can not recieve data from remote host %s:%s\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(str_request);
- free(debugmsg);
- close(sdesc);
- return(SOCKET_ERROR);
- }
-
- close(sdesc);
- free(str_request);
- free(debugmsg);
- return(rcv_buffer_size);
-}
-
-int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x40])
-{
- char *bufferget;
- int retcode=0;
-
- bufferget=(char *)malloc(GET_BUFFER_LENGTH);
- memset(bufferget,0,GET_BUFFER_LENGTH);
-
- if ((retcode=GET(IP_SRC,IP_DST,PORT_DST,URL,bufferget))!=0) {
- MD5Data(bufferget,retcode,MDResult);
- free(bufferget);
- return(1);
- } else {
- free(bufferget);
- return(0);
- }
- free(bufferget);
-}
+++ /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: tcpcheck.c,v 0.2.3 2000/12/29 $
- *
- * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
- *
- * Changes:
- * Alexandre Cassen : 2000/12/29 :
- * <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
- * Call this function in TCP_RCV_SYNACK_PACKET with 1s timeout.
- * <+> Added a timer (2s timeouted) in TCP_RCV_SYNACK_PACKET to check
- * SYN|ACK packet. Check perform on tcp sequence, remote tcp port number,
- * tcp SYN|ACK flag, remote ip address.
- * <+> Added a 3 time SYN packet send retry.
- *
- * Alexandre Cassen : 2000/12/09 : Initial release
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include "tcpcheck.h"
-
-int recvfrom_to(int s, char *buf, int len, struct sockaddr *saddr, int timo)
-{
- int nfound,slen,n;
- struct timeval to;
- fd_set readset,writeset;
-
- to.tv_sec = timo/1000;
- to.tv_usec = 0;
-
- FD_ZERO(&readset);
- FD_ZERO(&writeset);
- FD_SET(s,&readset);
- nfound = select(s+1,&readset,&writeset,NULL,&to);
- if (nfound<0) {
-#ifdef DEBUG
- logmessage("TCP_CHECK : Select socket descriptor error...\n",getpid());
-#endif
- return(-1);
- }
- if (nfound==0) {
-#ifdef DEBUG
- logmessage("TCP_CHECK : Timeout receiving SYN response...\n",getpid());
-#endif
- return -1;
- }
- slen=sizeof(struct sockaddr_in);
- n=recvfrom(s,buf,len,0,saddr,&slen);
- if (n<0) {
-#ifdef DEBUG
- logmessage("TCP_CHECK : recvfrom error...\n",getpid());
-#endif
- return -1;
- }
- return n;
-}
-
-int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG,unsigned long int SEQ)
-{
- register int rawsock;
- struct linger li = { 0 };
-
- /* Packet Data representation */
- struct iphdr *packet_ip;
- struct tcphdr *packet_tcp;
- struct tcphdr_pseudo packet_tcppseudo;
- struct sockaddr_in dest;
- char *packet;
-
- /* Packet pointer affectation */
- packet=(char *)malloc(SYNPACKET_LENGTH);
- memset(packet,0,SYNPACKET_LENGTH);
- memset(&dest,0,sizeof(struct sockaddr_in));
- packet_ip=(struct iphdr *)packet;
- packet_tcp=(struct tcphdr *)(packet_ip+1);
-
- if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1 ) {
- free(packet);
- return (SOCKET_ERROR);
- }
-
- /* free the tcp port after closing the socket descriptor */
- li.l_onoff=1;
- li.l_linger=0;
- setsockopt(rawsock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
- /* Fill in the IP header structure */
- packet_ip->version = 4;
- packet_ip->ihl = 5;
- packet_ip->tos = 0 ;
- packet_ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
- packet_ip->id = htons(random());
- packet_ip->frag_off = 0;
- packet_ip->ttl = 30; /* 30 Hops Max */
- packet_ip->protocol = IPPROTO_TCP;
- packet_ip->saddr = inet_addr(IP_SRC);
- packet_ip->daddr = inet_addr(IP_DST);
- packet_ip->check = in_cksum((unsigned short *)packet_ip, sizeof(struct iphdr));
-
- /* Fill in the TCP header structure */
- packet_tcp->source = htons(STCP);
- packet_tcp->dest = htons(atoi(PORT_DST));
- packet_tcp->seq = SEQ;
- packet_tcp->doff = sizeof(struct tcphdr)/4;
- packet_tcp->ack_seq = 0;
- packet_tcp->res1 = 0;
- packet_tcp->fin = (strstr(FLAG,"FIN"))?1:0;
- packet_tcp->syn = (strstr(FLAG,"SYN"))?1:0;
- packet_tcp->rst = (strstr(FLAG,"RST"))?1:0;
- packet_tcp->psh = (strstr(FLAG,"PSH"))?1:0;
- packet_tcp->ack = (strstr(FLAG,"ACK"))?1:0;
- packet_tcp->urg = (strstr(FLAG,"URG"))?1:0;
- packet_tcp->res2 = 0;
- packet_tcp->window = htons(65535);
- packet_tcp->check = 0;
- packet_tcp->urg_ptr = 0;
-
- /* Fill in the TCP pseudo structure */
- packet_tcppseudo.saddr = packet_ip->saddr;
- packet_tcppseudo.daddr = packet_ip->daddr;
- packet_tcppseudo.zero = 0;
- packet_tcppseudo.proto = packet_ip->protocol;
- packet_tcppseudo.tcplen = htons(sizeof(struct tcphdr));
- bcopy((char *)packet_tcp, (char *)&packet_tcppseudo.tcp, sizeof(struct tcphdr));
-
- packet_tcp->check = in_cksum((unsigned short *)&packet_tcppseudo,
- sizeof(struct tcphdr_pseudo));
-
- /* Fill in the Sockaddr structure */
- /* A little fake, IP & PORT are in IP & TCP headers */
- dest.sin_family = AF_INET;
- dest.sin_port = packet_tcp->dest;
- dest.sin_addr.s_addr = packet_ip->daddr;
-
- if (sendto(rawsock,packet,sizeof(struct iphdr) + sizeof(struct tcphdr),
- 0,&dest,sizeof(dest)) < 0) {
- close(rawsock);
- free(packet);
- return(SOCKET_ERROR);
- }
-
- close(rawsock);
- free(packet);
- return(SOCKET_SUCCESS);
-}
-
-int TCP_RCV_SYNACK_PACKET(char *IP_DST, char *PORT_DST, unsigned long int SEQ)
-{
- register int rawsock;
- struct linger li = { 0 };
- time_t hint;
- struct tm *date;
- int timer_before, timer_after;
- int loop = 1;
- char *debugmsg;
-
- /* Packet Data representation */
- struct iphdr *packet_ip;
- struct tcphdr *packet_tcp;
- struct tcphdr_pseudo packet_tcppseudo;
- struct sockaddr_in dest;
- char *packet;
-
- /* Packet pointer affectation */
- debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
- packet=(char *)malloc(SYNPACKET_LENGTH);
- memset(packet,0,SYNPACKET_LENGTH);
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- memset(&dest,0,sizeof(struct sockaddr_in));
- packet_ip=(struct iphdr *)packet;
- packet_tcp=(struct tcphdr *)(packet_ip+1);
-
- if ( (rawsock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1 ) {
- free(debugmsg);
- free(packet);
- return (SOCKET_ERROR);
- }
-
- /* free the tcp port after closing the socket descriptor */
- li.l_onoff=1;
- li.l_linger=0;
- setsockopt(rawsock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
-
- /* Fill in the Sockaddr structure */
- memset(&dest,0,sizeof(struct sockaddr_in));
- dest.sin_family = AF_INET;
- dest.sin_port = htons(atoi(PORT_DST));
- dest.sin_addr.s_addr = inet_addr(IP_DST);
-
- /* Timer initialization */
- /* We can also use a signal SIGALRM and catch this signal with handler to break the loop */
- hint = time((long*)0);
- date = localtime(&hint);
- timer_before = date->tm_sec;
-
- while(loop) {
- if (recvfrom_to(rawsock,packet,SYNPACKET_LENGTH,(struct sockaddr *)&dest,1000) < 0) {
- close(rawsock);
- free(debugmsg);
- free(packet);
- return(SOCKET_ERROR);
- }
-
- if ( packet_tcp->syn && packet_tcp->ack &&
- (packet_tcp->ack_seq == SEQ) &&
- (packet_ip->saddr == dest.sin_addr.s_addr) &&
- (packet_tcp->source == htons(atoi(PORT_DST))) ) {
- close(rawsock);
- free(debugmsg);
- free(packet);
- return(SOCKET_SUCCESS);
- }
-
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : SYN|ACK packet not recieved from [%s:%s]. Retry\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
-
- /* timer to evaluate packet loosed */
- hint = time((long*)0);
- date = localtime(&hint);
- timer_after = date->tm_sec;
-
- if(abs(timer_after-timer_before)>1) loop=0;
- }
-
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : SYN|ACK packet loosed from [%s:%s]\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
-
- close(rawsock);
- free(debugmsg);
- free(packet);
- return(SOCKET_ERROR);
-}
-
-int TCP_CHECK(char *IP_SRC, char *IP_DST, char *PORT_DST)
-{
- register int tcpsock;
- char *debugmsg;
- int loop=1;
- int retry=0;
- unsigned long int SEQTCP=0;
-
- /* Memory allocation for the data structures */
- debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
-
- while(loop) {
- SEQTCP = random() & 0xffff;
-
- if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"SYN",htonl(SEQTCP-1))) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : Can't send SYN request to [%s:%s]\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(debugmsg);
- return(SOCKET_ERROR);
- }
- if(TCP_RCV_SYNACK_PACKET(IP_DST,PORT_DST,htonl(SEQTCP))) {
- loop=0;
- } else {
- retry++;
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : Reexpedite SYN request to [%s:%s]\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- loop=(retry==NB_RETRY)?0:1;
- }
- }
-
- if (retry==NB_RETRY) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : SYN|ACK response not recieved from [%s:%s] after 3 try\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(debugmsg);
- return(SOCKET_ERROR);
- }
-
- /* The we send a RST TCP packet to be sure that the remote host */
- /* close the communication channel. */
- /* Needed some time by MS Windows .... damned... */
-
- if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"RST ACK",SEQTCP)) {
-#ifdef DEBUG
- memset(debugmsg,0,LOGBUFFER_LENGTH);
- sprintf(debugmsg,"TCP_CHECK : Can't send RST to [%s:%s]\n",IP_DST,PORT_DST);
- logmessage(debugmsg,getpid());
-#endif
- free(debugmsg);
- return(SOCKET_ERROR);
- }
-
- free(debugmsg);
- return(SOCKET_SUCCESS);
-}
--- /dev/null
+/*\r
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.\r
+\r
+ This software is provided 'as-is', without any express or implied\r
+ warranty. In no event will the authors be held liable for any damages\r
+ arising from the use of this software.\r
+\r
+ Permission is granted to anyone to use this software for any purpose,\r
+ including commercial applications, and to alter it and redistribute it\r
+ freely, subject to the following restrictions:\r
+\r
+ 1. The origin of this software must not be misrepresented; you must not\r
+ claim that you wrote the original software. If you use this software\r
+ in a product, an acknowledgment in the product documentation would be\r
+ appreciated but is not required.\r
+ 2. Altered source versions must be plainly marked as such, and must not be\r
+ misrepresented as being the original software.\r
+ 3. This notice may not be removed or altered from any source distribution.\r
+\r
+ L. Peter Deutsch\r
+ ghost@aladdin.com\r
+\r
+ */\r
+/*$Id: md5.c $ */\r
+/*\r
+ Independent implementation of MD5 (RFC 1321).\r
+\r
+ This code implements the MD5 Algorithm defined in RFC 1321.\r
+ It is derived directly from the text of the RFC and not from the\r
+ reference implementation.\r
+\r
+ The original and principal author of md5.c is L. Peter Deutsch\r
+ <ghost@aladdin.com>. Other authors are noted in the change history\r
+ that follows (in reverse chronological order):\r
+\r
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).\r
+ 1999-05-03 lpd Original version.\r
+ */\r
+\r
+#include "md5.h"\r
+\r
+#define T1 0xd76aa478\r
+#define T2 0xe8c7b756\r
+#define T3 0x242070db\r
+#define T4 0xc1bdceee\r
+#define T5 0xf57c0faf\r
+#define T6 0x4787c62a\r
+#define T7 0xa8304613\r
+#define T8 0xfd469501\r
+#define T9 0x698098d8\r
+#define T10 0x8b44f7af\r
+#define T11 0xffff5bb1\r
+#define T12 0x895cd7be\r
+#define T13 0x6b901122\r
+#define T14 0xfd987193\r
+#define T15 0xa679438e\r
+#define T16 0x49b40821\r
+#define T17 0xf61e2562\r
+#define T18 0xc040b340\r
+#define T19 0x265e5a51\r
+#define T20 0xe9b6c7aa\r
+#define T21 0xd62f105d\r
+#define T22 0x02441453\r
+#define T23 0xd8a1e681\r
+#define T24 0xe7d3fbc8\r
+#define T25 0x21e1cde6\r
+#define T26 0xc33707d6\r
+#define T27 0xf4d50d87\r
+#define T28 0x455a14ed\r
+#define T29 0xa9e3e905\r
+#define T30 0xfcefa3f8\r
+#define T31 0x676f02d9\r
+#define T32 0x8d2a4c8a\r
+#define T33 0xfffa3942\r
+#define T34 0x8771f681\r
+#define T35 0x6d9d6122\r
+#define T36 0xfde5380c\r
+#define T37 0xa4beea44\r
+#define T38 0x4bdecfa9\r
+#define T39 0xf6bb4b60\r
+#define T40 0xbebfbc70\r
+#define T41 0x289b7ec6\r
+#define T42 0xeaa127fa\r
+#define T43 0xd4ef3085\r
+#define T44 0x04881d05\r
+#define T45 0xd9d4d039\r
+#define T46 0xe6db99e5\r
+#define T47 0x1fa27cf8\r
+#define T48 0xc4ac5665\r
+#define T49 0xf4292244\r
+#define T50 0x432aff97\r
+#define T51 0xab9423a7\r
+#define T52 0xfc93a039\r
+#define T53 0x655b59c3\r
+#define T54 0x8f0ccc92\r
+#define T55 0xffeff47d\r
+#define T56 0x85845dd1\r
+#define T57 0x6fa87e4f\r
+#define T58 0xfe2ce6e0\r
+#define T59 0xa3014314\r
+#define T60 0x4e0811a1\r
+#define T61 0xf7537e82\r
+#define T62 0xbd3af235\r
+#define T63 0x2ad7d2bb\r
+#define T64 0xeb86d391\r
+\r
+static void\r
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)\r
+{\r
+ md5_word_t\r
+ a = pms->abcd[0], b = pms->abcd[1],\r
+ c = pms->abcd[2], d = pms->abcd[3];\r
+ md5_word_t t;\r
+\r
+#ifndef ARCH_IS_BIG_ENDIAN\r
+# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */\r
+#endif\r
+#if ARCH_IS_BIG_ENDIAN\r
+\r
+ /*\r
+ * On big-endian machines, we must arrange the bytes in the right\r
+ * order. (This also works on machines of unknown byte order.)\r
+ */\r
+ md5_word_t X[16];\r
+ const md5_byte_t *xp = data;\r
+ int i;\r
+\r
+ for (i = 0; i < 16; ++i, xp += 4)\r
+ X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);\r
+\r
+#else /* !ARCH_IS_BIG_ENDIAN */\r
+\r
+ /*\r
+ * On little-endian machines, we can process properly aligned data\r
+ * without copying it.\r
+ */\r
+ md5_word_t xbuf[16];\r
+ const md5_word_t *X;\r
+\r
+ if (!((data - (const md5_byte_t *)0) & 3)) {\r
+ /* data are properly aligned */\r
+ X = (const md5_word_t *)data;\r
+ } else {\r
+ /* not aligned */\r
+ memcpy(xbuf, data, 64);\r
+ X = xbuf;\r
+ }\r
+#endif\r
+\r
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\r
+\r
+ /* Round 1. */\r
+ /* Let [abcd k s i] denote the operation\r
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + F(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 0, 7, T1);\r
+ SET(d, a, b, c, 1, 12, T2);\r
+ SET(c, d, a, b, 2, 17, T3);\r
+ SET(b, c, d, a, 3, 22, T4);\r
+ SET(a, b, c, d, 4, 7, T5);\r
+ SET(d, a, b, c, 5, 12, T6);\r
+ SET(c, d, a, b, 6, 17, T7);\r
+ SET(b, c, d, a, 7, 22, T8);\r
+ SET(a, b, c, d, 8, 7, T9);\r
+ SET(d, a, b, c, 9, 12, T10);\r
+ SET(c, d, a, b, 10, 17, T11);\r
+ SET(b, c, d, a, 11, 22, T12);\r
+ SET(a, b, c, d, 12, 7, T13);\r
+ SET(d, a, b, c, 13, 12, T14);\r
+ SET(c, d, a, b, 14, 17, T15);\r
+ SET(b, c, d, a, 15, 22, T16);\r
+#undef SET\r
+\r
+ /* Round 2. */\r
+ /* Let [abcd k s i] denote the operation\r
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + G(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 1, 5, T17);\r
+ SET(d, a, b, c, 6, 9, T18);\r
+ SET(c, d, a, b, 11, 14, T19);\r
+ SET(b, c, d, a, 0, 20, T20);\r
+ SET(a, b, c, d, 5, 5, T21);\r
+ SET(d, a, b, c, 10, 9, T22);\r
+ SET(c, d, a, b, 15, 14, T23);\r
+ SET(b, c, d, a, 4, 20, T24);\r
+ SET(a, b, c, d, 9, 5, T25);\r
+ SET(d, a, b, c, 14, 9, T26);\r
+ SET(c, d, a, b, 3, 14, T27);\r
+ SET(b, c, d, a, 8, 20, T28);\r
+ SET(a, b, c, d, 13, 5, T29);\r
+ SET(d, a, b, c, 2, 9, T30);\r
+ SET(c, d, a, b, 7, 14, T31);\r
+ SET(b, c, d, a, 12, 20, T32);\r
+#undef SET\r
+\r
+ /* Round 3. */\r
+ /* Let [abcd k s t] denote the operation\r
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define H(x, y, z) ((x) ^ (y) ^ (z))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + H(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 5, 4, T33);\r
+ SET(d, a, b, c, 8, 11, T34);\r
+ SET(c, d, a, b, 11, 16, T35);\r
+ SET(b, c, d, a, 14, 23, T36);\r
+ SET(a, b, c, d, 1, 4, T37);\r
+ SET(d, a, b, c, 4, 11, T38);\r
+ SET(c, d, a, b, 7, 16, T39);\r
+ SET(b, c, d, a, 10, 23, T40);\r
+ SET(a, b, c, d, 13, 4, T41);\r
+ SET(d, a, b, c, 0, 11, T42);\r
+ SET(c, d, a, b, 3, 16, T43);\r
+ SET(b, c, d, a, 6, 23, T44);\r
+ SET(a, b, c, d, 9, 4, T45);\r
+ SET(d, a, b, c, 12, 11, T46);\r
+ SET(c, d, a, b, 15, 16, T47);\r
+ SET(b, c, d, a, 2, 23, T48);\r
+#undef SET\r
+\r
+ /* Round 4. */\r
+ /* Let [abcd k s t] denote the operation\r
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */\r
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))\r
+#define SET(a, b, c, d, k, s, Ti) t = a + I(b,c,d) + X[k] + Ti; a = ROTATE_LEFT(t, s) + b\r
+ /* Do the following 16 operations. */\r
+ SET(a, b, c, d, 0, 6, T49);\r
+ SET(d, a, b, c, 7, 10, T50);\r
+ SET(c, d, a, b, 14, 15, T51);\r
+ SET(b, c, d, a, 5, 21, T52);\r
+ SET(a, b, c, d, 12, 6, T53);\r
+ SET(d, a, b, c, 3, 10, T54);\r
+ SET(c, d, a, b, 10, 15, T55);\r
+ SET(b, c, d, a, 1, 21, T56);\r
+ SET(a, b, c, d, 8, 6, T57);\r
+ SET(d, a, b, c, 15, 10, T58);\r
+ SET(c, d, a, b, 6, 15, T59);\r
+ SET(b, c, d, a, 13, 21, T60);\r
+ SET(a, b, c, d, 4, 6, T61);\r
+ SET(d, a, b, c, 11, 10, T62);\r
+ SET(c, d, a, b, 2, 15, T63);\r
+ SET(b, c, d, a, 9, 21, T64);\r
+#undef SET\r
+\r
+ /* Then perform the following additions. (That is increment each\r
+ of the four registers by the value it had before this block\r
+ was started.) */\r
+ pms->abcd[0] += a;\r
+ pms->abcd[1] += b;\r
+ pms->abcd[2] += c;\r
+ pms->abcd[3] += d;\r
+}\r
+\r
+void\r
+md5_init(md5_state_t *pms)\r
+{\r
+ pms->count[0] = pms->count[1] = 0;\r
+ pms->abcd[0] = 0x67452301;\r
+ pms->abcd[1] = 0xefcdab89;\r
+ pms->abcd[2] = 0x98badcfe;\r
+ pms->abcd[3] = 0x10325476;\r
+}\r
+\r
+void\r
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)\r
+{\r
+ const md5_byte_t *p = data;\r
+ int left = nbytes;\r
+ int offset = (pms->count[0] >> 3) & 63;\r
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);\r
+\r
+ if (nbytes <= 0)\r
+ return;\r
+\r
+ /* Update the message length. */\r
+ pms->count[1] += nbytes >> 29;\r
+ pms->count[0] += nbits;\r
+ if (pms->count[0] < nbits)\r
+ pms->count[1]++;\r
+\r
+ /* Process an initial partial block. */\r
+ if (offset) {\r
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);\r
+\r
+ memcpy(pms->buf + offset, p, copy);\r
+ if (offset + copy < 64)\r
+ return;\r
+ p += copy;\r
+ left -= copy;\r
+ md5_process(pms, pms->buf);\r
+ }\r
+\r
+ /* Process full blocks. */\r
+ for (; left >= 64; p += 64, left -= 64)\r
+ md5_process(pms, p);\r
+\r
+ /* Process a final partial block. */\r
+ if (left)\r
+ memcpy(pms->buf, p, left);\r
+}\r
+\r
+void\r
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])\r
+{\r
+ static const md5_byte_t pad[64] = {\r
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+ };\r
+ md5_byte_t data[8];\r
+ int i;\r
+\r
+ /* Save the length before padding. */\r
+ for (i = 0; i < 8; ++i)\r
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));\r
+ /* Pad to 56 bytes mod 64. */\r
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);\r
+ /* Append the length. */\r
+ md5_append(pms, data, 8);\r
+ for (i = 0; i < 16; ++i)\r
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));\r
+}\r
--- /dev/null
+/*\r
+ Copyright (C) 1999 Aladdin Enterprises. All rights reserved.\r
+\r
+ This software is provided 'as-is', without any express or implied\r
+ warranty. In no event will the authors be held liable for any damages\r
+ arising from the use of this software.\r
+\r
+ Permission is granted to anyone to use this software for any purpose,\r
+ including commercial applications, and to alter it and redistribute it\r
+ freely, subject to the following restrictions:\r
+\r
+ 1. The origin of this software must not be misrepresented; you must not\r
+ claim that you wrote the original software. If you use this software\r
+ in a product, an acknowledgment in the product documentation would be\r
+ appreciated but is not required.\r
+ 2. Altered source versions must be plainly marked as such, and must not be\r
+ misrepresented as being the original software.\r
+ 3. This notice may not be removed or altered from any source distribution.\r
+\r
+ L. Peter Deutsch\r
+ ghost@aladdin.com\r
+\r
+ */\r
+/*$Id: md5.h $ */\r
+/*\r
+ Independent implementation of MD5 (RFC 1321).\r
+\r
+ This code implements the MD5 Algorithm defined in RFC 1321.\r
+ It is derived directly from the text of the RFC and not from the\r
+ reference implementation.\r
+\r
+ The original and principal author of md5.h is L. Peter Deutsch\r
+ <ghost@aladdin.com>. Other authors are noted in the change history\r
+ that follows (in reverse chronological order):\r
+\r
+ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.\r
+ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);\r
+ added conditionalization for C++ compilation from Martin\r
+ Purschke <purschke@bnl.gov>.\r
+ 1999-05-03 lpd Original version.\r
+ */\r
+\r
+#ifndef md5_INCLUDED\r
+# define md5_INCLUDED\r
+\r
+/*\r
+ * This code has some adaptations for the Ghostscript environment, but it\r
+ * will compile and run correctly in any environment with 8-bit chars and\r
+ * 32-bit ints. Specifically, it assumes that if the following are\r
+ * defined, they have the same meaning as in Ghostscript: P1, P2, P3,\r
+ * ARCH_IS_BIG_ENDIAN.\r
+ */\r
+\r
+typedef unsigned char md5_byte_t; /* 8-bit byte */\r
+typedef unsigned int md5_word_t; /* 32-bit word */\r
+\r
+/* Define the state of the MD5 Algorithm. */\r
+typedef struct md5_state_s {\r
+ md5_word_t count[2]; /* message length in bits, lsw first */\r
+ md5_word_t abcd[4]; /* digest buffer */\r
+ md5_byte_t buf[64]; /* accumulate block */\r
+} md5_state_t;\r
+\r
+#ifdef __cplusplus\r
+extern "C" \r
+{\r
+#endif\r
+\r
+/* Initialize the algorithm. */\r
+#ifdef P1\r
+void md5_init(P1(md5_state_t *pms));\r
+#else\r
+void md5_init(md5_state_t *pms);\r
+#endif\r
+\r
+/* Append a string to the message. */\r
+#ifdef P3\r
+void md5_append(P3(md5_state_t *pms, const md5_byte_t *data, int nbytes));\r
+#else\r
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);\r
+#endif\r
+\r
+/* Finish the message and return the digest. */\r
+#ifdef P2\r
+void md5_finish(P2(md5_state_t *pms, md5_byte_t digest[16]));\r
+#else\r
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+} /* end extern "C" */\r
+#endif\r
+\r
+#endif /* md5_INCLUDED */\r
--- /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: Pid file lock utils.
+ *
+ * Version: $Id: pidfile.c,v 0.2.6 2001/03/05 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "pidfile.h"
+
+int pidfile_write(int pid)
+{
+ FILE *pidfile = fopen(PIDFILENAME,"w");
+
+ if(!pidfile) {
+ logmessage("pidfile_write : Can not open pidfile\n");
+ return(0);
+ }
+ fprintf(pidfile,"%d\n",pid);
+ fclose(pidfile);
+ return(1);
+}
+
+void pidfile_rm()
+{
+ unlink(PIDFILENAME);
+}
+
+int keepalived_running()
+{
+ FILE *pidfile;
+
+ if ((pidfile=fopen(PIDFILENAME,"r")) == NULL)
+ return 0;
+
+ fclose(pidfile);
+ return 1;
+}
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
*
- * Part: utils.c include file.
+ * Part: pidfile.c include file.
*
- * Version: $Id: utils.h,v 0.2.1 2000/12/09 $
+ * Version: $Id: pidfile.h,v 0.2.6 2001/03/05 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* 2 of the License, or (at your option) any later version.
*/
-#ifndef UTILS_H
-#define UTILS_H
+#ifndef PIDFILE_H
+#define PIDFILE_H
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
-#define LOGFILE "log/keepalived.log"
+#define PIDFILENAME "/var/run/keepalived.pid"
#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: SMTP WRAPPER connect to a specified smtp server and send mail
+ * using the smtp protocol according to the RFC 822. A non blocking
+ * timeouted connection is used to handle smtp protocol.
+ *
+ * Version: $Id: smtpwrapper.c,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 : Initial release
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "smtpwrapper.h"
+
+int send_to(register int sdesc, fd_set wfds, struct timeval tv, char *buffer)
+{
+ select(sdesc+1,NULL,&wfds,NULL,&tv);
+ if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Timeout writing data to smtp server\n");
+#endif
+ return(SOCKET_ERROR);
+ }
+
+ if (send(sdesc,buffer,strlen(buffer),0) == -1) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Can not send data to remote smtp server\n");
+#endif
+ return(SOCKET_ERROR);
+ }
+
+ return(SOCKET_SUCCESS);
+}
+
+int read_to(register int sdesc, fd_set rfds, struct timeval tv, char *buffer)
+{
+ int rcv_buffer_size=0;
+ long total_length=0;
+ char *buffertmp;
+
+ buffertmp=(char *)malloc(BUFFER_LENGTH);
+ memset(buffertmp,0,BUFFER_LENGTH);
+
+ select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Timeout receiving data from smtp server\n");
+#endif
+ free(buffertmp);
+ return(SOCKET_ERROR);
+ }
+
+ while((rcv_buffer_size = read(sdesc,buffertmp,BUFFER_LENGTH)) != 0) {
+ if ( rcv_buffer_size == -1 ) {
+ if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Can not recieve data from remote smtp server\n");
+#endif
+ free(buffertmp);
+ return(SOCKET_ERROR);
+ }
+ memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+ memset(buffertmp,0,BUFFER_LENGTH);
+ total_length += rcv_buffer_size;
+ }
+
+end:
+ free(buffertmp);
+ return(SOCKET_SUCCESS);
+}
+
+int smtp_cmd(register int sdesc,fd_set rfds,fd_set wfds,struct timeval tv,char *smtpcmd,char *retcode)
+{
+ char *buffer;
+ char *smtpcode;
+
+ buffer=(char *)malloc(BUFFER_LENGTH);
+ smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+
+ /* Sending SMTP command to remote smtp server */
+ if (!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+
+ /* Processing SMTP server reply */
+ memset(buffer,0,BUFFER_LENGTH);
+ if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+ /* Look for response code */
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+ if(strcmp(smtpcode,retcode) != 0) {
+#ifdef DEBUG
+ logmessage(buffer);
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_SUCCESS);
+}
+
+int SMTP_SENDMAIL(char *IP_DST, char *PORT_DST, char *from, char *to,char *subject,char *body,int ctimeout)
+{
+ register int sdesc;
+ int long_inet;
+ struct hostent *ip_serv;
+ struct sockaddr_in adr_serv;
+ struct linger li = { 0 };
+ char *debugmsg;
+ char *buffer;
+ char *smtpcode;
+ char *smtpcmd;
+ struct timeval tv;
+ fd_set rfds, wfds;
+ int rc, flags;
+ int arglen;
+
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+ buffer=(char *)malloc(BUFFER_LENGTH);
+ smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+ smtpcmd=(char *)malloc(SMTP_CMD_LENGTH);
+ memset(buffer,0,BUFFER_LENGTH);
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+
+ if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ return(SOCKET_ERROR);
+ }
+
+ /* free the tcp port after closing the socket descriptor */
+ li.l_onoff=1;
+ li.l_linger=0;
+ setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+ long_inet = sizeof(struct sockaddr_in);
+
+ if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Can not resolve remote host %s\n",IP_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ memset(&adr_serv,0,long_inet);
+ adr_serv.sin_family=ip_serv->h_addrtype;
+ bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+ adr_serv.sin_port=htons(atoi(PORT_DST));
+
+ /* Set read/write socket timeout */
+ flags=fcntl(sdesc, F_GETFL);
+ fcntl(sdesc, F_SETFL, flags | O_NONBLOCK);
+
+ /* Connect the remote host */
+ if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1) {
+ switch (errno) {
+ case ETIMEDOUT:
+ case EINTR:
+ case EHOSTUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ECONNREFUSED:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ENETUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case EINPROGRESS: // NONBLOCK socket connection in progress
+ goto next;
+ default:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ }
+
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+next:
+ /* Timeout settings */
+ tv.tv_sec=ctimeout;
+ tv.tv_usec=0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_SET(sdesc,&rfds);
+ FD_SET(sdesc,&wfds);
+
+ rc = select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Timeout reading data to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ if (rc < 0) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ rc = 0;
+ arglen=sizeof(int);
+ if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+ rc = errno;
+
+ if (rc) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Proceed the SMTP server reply */
+ if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Look for connect code */
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+ if(strcmp(smtpcode,SMTP_CONNECT) != 0) {
+#ifdef DEBUG
+ logmessage("Can not connect remote smtp server.\n");
+#endif
+ }
+
+ /* Sending host identification */
+ memset(buffer,0,BUFFER_LENGTH);
+ if(gethostname(buffer,500)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error resolving local hostname\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending EHLO command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"EHLO %s\n",buffer);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_EHLO)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending MAIL FROM command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"MAIL FROM:%s\n",from);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_MAIL_FROM)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending MAIL FROM.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending RCPT TO command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"RCPT TO:%s\n",to);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_RCPT_TO)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending RCPT TO.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending DATA command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"DATA\n");
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DATA)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending DATA.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending smtp header to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"Subject: %s\nX-Mailer: Keepalived SmtpWrapper\n\n",subject);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp header.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending smtp body to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"\n\n%s\n\n",body);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp body.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending DATA command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"\n.\n");
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DOT)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending trailing DOT.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending quit to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"QUIT\n",body);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp quit.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ close(sdesc);
+ free(debugmsg);
+ free(buffer);
+ return(SOCKET_SUCCESS);
+}
+
+void SMTP_SEND_ALERTES(configuration_data *lstconf,virtualserver *lstvs,char *subject,char *body)
+{
+ char *tmpbuff;
+ char *debugmsg;
+ notification_email *pointeremail;
+
+ tmpbuff=(char *)malloc(500);
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+ memset(tmpbuff,0,500);
+
+ sprintf(tmpbuff,"[%s] %s:%s - %s",lstconf->lvs_id,lstvs->svr->addr_ip,lstvs->svr->addr_port,subject);
+
+ pointeremail=lstconf->email;
+ while(lstconf->email != NULL) {
+ if(!SMTP_SENDMAIL(lstconf->smtp_server,SMTP_PORT,lstconf->email_from,lstconf->email->addr,tmpbuff,body,6)) {
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SEND_ALERTES : Can not send alerte to %s.\n",lstconf->email->addr);
+ logmessage(debugmsg);
+ }
+ lstconf->email=(notification_email *)lstconf->email->next;
+ }
+ lstconf->email=pointeremail;
+
+ free(tmpbuff);
+ free(debugmsg);
+}
--- /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: smtpwrapper.c include file.
+ *
+ * Version: $Id: smtpwrapper.h,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef SMTPWRAPPER_H
+#define SMTPWRAPPER_H
+
+#include <signal.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "cfreader.h"
+
+#define SOCKET_ERROR 0
+#define SOCKET_SUCCESS 1
+#define SOCKET_TIMEOUT 3
+
+#define SMTP_PORT "25"
+
+#define SMTP_CONNECT "220"
+#define SMTP_EHLO "250"
+#define SMTP_MAIL_FROM "250"
+#define SMTP_RCPT_TO "250"
+#define SMTP_DATA "354"
+#define SMTP_DOT "250"
+
+
+#define LOGBUFFER_LENGTH 100
+#define BUFFER_LENGTH 1024
+#define SMTP_ERROR_CODE_LENGTH 4
+#define SMTP_CMD_LENGTH 500
+
+#endif
--- /dev/null
+# Makefile
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
+
+EXEC= smtpsend
+CC= gcc
+#CFLAGS= -Wall -Wunused
+CFLAGS=
+DEFS= main.h smtpwrapper.h
+OBJECTS= main.o smtpwrapper.o utils.o
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:
+# $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+ $(CC) -o $@ $(INCLUDE) -DDEBUG -c $*.c
+
+all: $(EXEC)
+ strip $(EXEC)
+ @echo ""
+ @echo "Make complete"
+
+$(EXEC): $(OBJECTS) $(DEFS)
+ $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS)
+
+clean:
+ rm -f core *.o $(EXEC)
--- /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.3 2001/01/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/01/01 :
+ * <+> Change the signalhandling.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "main.h"
+
+int main(int argc, char **argv)
+{
+ printf(PROG" v"VERSION"\n");
+
+ SMTP_SENDMAIL("172.31.47.40","25","keepalived@smsgw.cplusfrn.com","acassen@smsgw.cplusfrn.com","le sujet","Test de body",6);
+
+ return 0;
+}
--- /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 "smtpwrapper.h"
+
+/* Build version */
+#define PROG "smtpwrapper"
+#define VERSION "0.2.6 (03/01, 2001), Alexandre Cassen"
+
+#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: SMTP WRAPPER connect to a specified smtp server and send mail
+ * using the smtp protocol according to the RFC 822. A non blocking
+ * timeouted connection is used to handle smtp protocol.
+ *
+ * Version: $Id: smtpwrapper.c,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 : Initial release
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "smtpwrapper.h"
+
+int send_to(register int sdesc, fd_set wfds, struct timeval tv, char *buffer)
+{
+ select(sdesc+1,NULL,&wfds,NULL,&tv);
+ if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Timeout writing data to smtp server\n");
+#endif
+ return(SOCKET_ERROR);
+ }
+
+ if (send(sdesc,buffer,strlen(buffer),0) == -1) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Can not send data to remote smtp server\n");
+#endif
+ return(SOCKET_ERROR);
+ }
+
+ return(SOCKET_SUCCESS);
+}
+
+int read_to(register int sdesc, fd_set rfds, struct timeval tv, char *buffer)
+{
+ int rcv_buffer_size=0;
+ long total_length=0;
+ char *buffertmp;
+
+ buffertmp=(char *)malloc(BUFFER_LENGTH);
+ memset(buffertmp,0,BUFFER_LENGTH);
+
+ select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Timeout receiving data from smtp server\n");
+#endif
+ free(buffertmp);
+ return(SOCKET_ERROR);
+ }
+
+ while((rcv_buffer_size = read(sdesc,buffertmp,BUFFER_LENGTH)) != 0) {
+ if ( rcv_buffer_size == -1 ) {
+ if(errno == EAGAIN) goto end;
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Can not recieve data from remote smtp server\n");
+#endif
+ free(buffertmp);
+ return(SOCKET_ERROR);
+ }
+ memcpy(buffer+total_length,buffertmp,rcv_buffer_size);
+ memset(buffertmp,0,BUFFER_LENGTH);
+ total_length += rcv_buffer_size;
+ }
+
+end:
+ free(buffertmp);
+ return(SOCKET_SUCCESS);
+}
+
+int smtp_cmd(register int sdesc,fd_set rfds,fd_set wfds,struct timeval tv,char *smtpcmd,char *retcode)
+{
+ char *buffer;
+ char *smtpcode;
+
+ buffer=(char *)malloc(BUFFER_LENGTH);
+ smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+
+ /* Sending SMTP command to remote smtp server */
+ if (!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+
+ /* Processing SMTP server reply */
+ memset(buffer,0,BUFFER_LENGTH);
+ if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+ /* Look for response code */
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+ if(strcmp(smtpcode,retcode) != 0) {
+#ifdef DEBUG
+ logmessage(buffer);
+#endif
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_ERROR);
+ }
+
+ free(buffer);
+ free(smtpcode);
+ return(SOCKET_SUCCESS);
+}
+
+int SMTP_SENDMAIL(char *IP_DST, char *PORT_DST, char *from, char *to,char *subject,char *body,int ctimeout)
+{
+ register int sdesc;
+ int long_inet;
+ struct hostent *ip_serv;
+ struct sockaddr_in adr_serv;
+ struct linger li = { 0 };
+ char *debugmsg;
+ char *buffer;
+ char *smtpcode;
+ char *smtpcmd;
+ struct timeval tv;
+ fd_set rfds, wfds;
+ int rc, flags;
+ int arglen;
+
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+ buffer=(char *)malloc(BUFFER_LENGTH);
+ smtpcode=(char *)malloc(SMTP_ERROR_CODE_LENGTH);
+ smtpcmd=(char *)malloc(SMTP_CMD_LENGTH);
+ memset(buffer,0,BUFFER_LENGTH);
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+
+ if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ return(SOCKET_ERROR);
+ }
+
+ /* free the tcp port after closing the socket descriptor */
+ li.l_onoff=1;
+ li.l_linger=0;
+ setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+ long_inet = sizeof(struct sockaddr_in);
+
+ if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Can not resolve remote host %s\n",IP_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ memset(&adr_serv,0,long_inet);
+ adr_serv.sin_family=ip_serv->h_addrtype;
+ bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+ adr_serv.sin_port=htons(atoi(PORT_DST));
+
+ /* Set read/write socket timeout */
+ flags=fcntl(sdesc, F_GETFL);
+ fcntl(sdesc, F_SETFL, flags | O_NONBLOCK);
+
+ /* Connect the remote host */
+ if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1) {
+ switch (errno) {
+ case ETIMEDOUT:
+ case EINTR:
+ case EHOSTUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ECONNREFUSED:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ENETUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case EINPROGRESS: // NONBLOCK socket connection in progress
+ goto next;
+ default:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ }
+
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+next:
+ /* Timeout settings */
+ tv.tv_sec=ctimeout;
+ tv.tv_usec=0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_SET(sdesc,&rfds);
+ FD_SET(sdesc,&wfds);
+
+ rc = select(sdesc+1,&rfds,NULL,NULL,&tv);
+ if (!FD_ISSET(sdesc,&rfds)) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Timeout reading data to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ if (rc < 0) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ rc = 0;
+ arglen=sizeof(int);
+ if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+ rc = errno;
+
+ if (rc) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"SMTP_SENDMAIL : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Proceed the SMTP server reply */
+ if(!read_to(sdesc,rfds,tv,buffer)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error receiving data from smtp server.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Look for connect code */
+ memset(smtpcode,0,SMTP_ERROR_CODE_LENGTH);
+ memcpy(smtpcode,buffer,SMTP_ERROR_CODE_LENGTH-1);
+ if(strcmp(smtpcode,SMTP_CONNECT) != 0) {
+#ifdef DEBUG
+ logmessage("Can not connect remote smtp server.\n");
+#endif
+ }
+
+ /* Sending host identification */
+ memset(buffer,0,BUFFER_LENGTH);
+ if(gethostname(buffer,500)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error resolving local hostname\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending EHLO command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"EHLO %s\n",buffer);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_EHLO)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending EHLO.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending MAIL FROM command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"MAIL FROM:%s\n",from);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_MAIL_FROM)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending MAIL FROM.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending RCPT TO command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"RCPT TO:%s\n",to);
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_RCPT_TO)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending RCPT TO.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending DATA command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"DATA\n");
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DATA)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending DATA.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending smtp header to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"Subject: %s\nX-Mailer: Keepalived SmtpWrapper\n\n",subject);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp header.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending smtp body to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"\n\n%s\n\n",body);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp body.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending DATA command to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"\n.\n");
+ if(!smtp_cmd(sdesc,wfds,rfds,tv,smtpcmd,SMTP_DOT)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending trailing DOT.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ /* Sending quit to remote smtp server */
+ memset(smtpcmd,0,SMTP_CMD_LENGTH);
+ sprintf(smtpcmd,"QUIT\n",body);
+ if(!send_to(sdesc,wfds,tv,smtpcmd)) {
+#ifdef DEBUG
+ logmessage("SMTP_SENDMAIL : Error sending smtp quit.\n");
+#endif
+ free(debugmsg);
+ free(buffer);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ close(sdesc);
+ free(debugmsg);
+ free(buffer);
+ return(SOCKET_SUCCESS);
+}
--- /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: smtpwrapper.c include file.
+ *
+ * Version: $Id: smtpwrapper.h,v 0.2.6 2001/03/01 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef CFREADER_H
+#define CFREADER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define SOCKET_ERROR 0
+#define SOCKET_SUCCESS 1
+#define SOCKET_TIMEOUT 3
+
+#define SMTP_CONNECT "220"
+#define SMTP_EHLO "250"
+#define SMTP_MAIL_FROM "250"
+#define SMTP_RCPT_TO "250"
+#define SMTP_DATA "354"
+#define SMTP_DOT "250"
+
+
+#define LOGBUFFER_LENGTH 100
+#define BUFFER_LENGTH 1024
+#define SMTP_ERROR_CODE_LENGTH 4
+#define SMTP_CMD_LENGTH 500
+
+#endif
--- /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: utils.c,v 0.2.1 2000/12/09 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+void print_buffer(int count, char *buff)
+{
+ int i,j,c;
+ int printnext=1;
+
+ if(count) {
+ if(count%16)
+ c=count+(16-count%16);
+ else c=count;
+ } else
+ c=count;
+
+ for(i=0;i<c;i++) {
+ if(printnext) {
+ printnext--;
+ printf("%.4x ",i&0xffff);
+ }
+ if(i<count)
+ printf("%3.2x",buff[i]&0xff);
+ else
+ printf(" ");
+ if(!((i+1)%8)) {
+ if((i+1)%16)
+ printf(" -");
+ else {
+ printf(" ");
+ for(j=i-15;j<=i;j++)
+ if(j<count) {
+ if( (buff[j]&0xff) >= 0x20 && (buff[j]&0xff)<=0x7e)
+ printf("%c",buff[j]&0xff);
+ else printf(".");
+ } else printf(" ");
+ printf("\n"); printnext=1;
+ }
+ }
+ }
+}
+
+void logmessage(char *msg)
+{
+ printf("%s",msg);
+}
--- /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: tcpcheck.c,v 0.2.5 2001/02/16 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/02/16 :
+ * <-> Suppress the whole RAW_SOCKET tcpcheck level initial implementation.
+ * <+> Replace the RAW_SOCKET initial implementation by a vanilla tcpcheck.
+ * Using non blocking & no_linger socket. Use a timeval to set socket
+ * descriptor timeout.
+ *
+ * Alexandre Cassen : 2000/12/29 :
+ * <+> Added recvfrom_to() function to handle recvfrom timeouted connection.
+ * Call this function in TCP_RCV_SYNACK_PACKET with 1s timeout.
+ * <+> Added a timer (2s timeouted) in TCP_RCV_SYNACK_PACKET to check
+ * SYN|ACK packet. Check perform on tcp sequence, remote tcp port number,
+ * tcp SYN|ACK flag, remote ip address.
+ * <+> Added a 3 time SYN packet send retry.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "tcpcheck.h"
+
+int TCP_CHECK(const char *IP_DST, const char *PORT_DST)
+{
+ register int sdesc;
+ int long_inet;
+ char *debugmsg;
+ struct hostent *ip_serv;
+ struct sockaddr_in adr_serv;
+ struct linger li = { 0 };
+ struct timeval tv;
+ fd_set wfds;
+ int rc, val;
+ int arglen;
+
+ /* Memory allocation for the data structures */
+ debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+
+ if ( (sdesc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Can not bind remote address %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ return(SOCKET_ERROR);
+ }
+
+ /* free the tcp port after closing the socket descriptor */
+ li.l_onoff=1;
+ li.l_linger=0;
+ setsockopt(sdesc,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
+
+ long_inet = sizeof(struct sockaddr_in);
+
+ if ( (ip_serv=gethostbyname(IP_DST)) == NULL) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Can not resolve remote host %s\n",IP_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ memset(&adr_serv,0,long_inet);
+ adr_serv.sin_family=ip_serv->h_addrtype;
+ bcopy(ip_serv->h_addr, &adr_serv.sin_addr.s_addr,ip_serv->h_length);
+ adr_serv.sin_port=htons(atoi(PORT_DST));
+
+ /* Set read/write socket timeout */
+ val=fcntl(sdesc, F_GETFL);
+ fcntl(sdesc, F_SETFL, val | O_NONBLOCK);
+
+ /* Connect the remote host */
+ if ( (rc=connect(sdesc, (struct sockaddr *)&adr_serv, long_inet)) == -1) {
+ switch (errno) {
+ case ETIMEDOUT:
+ case EINTR:
+ case EHOSTUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Connection timeout to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ECONNREFUSED:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Connection refused to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case ENETUNREACH:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Network unreachable to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ break;
+ case EINPROGRESS: // NONBLOCK socket connection in progress
+ goto next;
+ default:
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Network error [%s] to %s:%s\n",strerror(errno),IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ }
+
+ free(debugmsg);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+next:
+ /* Timeout settings */
+ tv.tv_sec=SOCKET_TIMEOUT;
+ tv.tv_usec=0;
+ FD_ZERO(&wfds);
+ FD_SET(sdesc,&wfds);
+
+ rc = select(sdesc+1,NULL,&wfds,NULL,&tv);
+ if (!FD_ISSET(sdesc,&wfds)) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Timeout writing data to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ if (rc < 0) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Select returned descriptor error to %s:%s\n",IP_DST,PORT_DST);
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ rc = 0;
+ arglen=sizeof(int);
+ if (getsockopt(sdesc,SOL_SOCKET,SO_ERROR,&rc,&arglen) < 0)
+ rc = errno;
+
+ if (rc) {
+#ifdef DEBUG
+ memset(debugmsg,0,LOGBUFFER_LENGTH);
+ sprintf(debugmsg,"TCP_CHECK : Connection failed to %s:%s (%s)\n",IP_DST,PORT_DST,strerror(rc));
+ logmessage(debugmsg);
+#endif
+ free(debugmsg);
+ close(sdesc);
+ return(SOCKET_ERROR);
+ }
+
+ free(debugmsg);
+ return(SOCKET_SUCCESS);
+}
#include <sys/time.h>
#include <linux/ip.h>
#include <linux/tcp.h>
+#include <fcntl.h>
+#include <errno.h>
#define SOCKET_ERROR 0
#define SOCKET_SUCCESS 1
-#define STCP 1111
+#define SOCKET_TIMEOUT 3
#define LOGBUFFER_LENGTH 100
-#define SYNPACKET_LENGTH 1024
-#define HOSTNAME_LENGTH 30
-
-#define NB_RETRY 3
-
-/* Structures used */
-struct tcphdr_pseudo {
- unsigned int saddr;
- unsigned int daddr;
- unsigned char zero;
- unsigned char proto;
- unsigned short tcplen;
- struct tcphdr tcp;
-};
-
-/* prototypes */
-int TCP_CHECK(char *IP_SRC, char *IP_DST, char *PORT_DST);
#endif
*
* Part: General program utils.
*
- * Version: $Id: utils.c,v 0.2.1 2000/12/09 $
+ * Version: $Id: utils.c,v 0.2.6 2001/03/01 $
*
* Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
*
* Changes:
- * Alexandre Cassen : Initial release
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Adding daemonpid var to stock running keepalived daemon pid.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
}
}
-void logmessage(char *msg,int idevent)
+void initdaemonpid(int pid)
+{
+ daemonpid=pid;
+}
+
+void logmessage(char *msg)
{
FILE *logfile;
time_t hint;
date->tm_hour,
date->tm_min,
date->tm_sec,
- idevent,msg);
+ daemonpid,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: utils.h,v 0.2.6 2001/03/09 $
+ *
+ * Author: Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+ *
+ * Changes:
+ * Alexandre Cassen : 2001/03/01 :
+ * <+> Adding global daemon pid var.
+ *
+ * Alexandre Cassen : 2000/12/09 : Initial release
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <string.h>
+
+#define LOGFILE "log/keepalived.log"
+
+/* Globals defs */
+int daemonpid;
+
+#endif