keepalived-0.2.3 v0.2.3
authorAlexandre Cassen <acassen@freebox.fr>
Tue, 2 Jan 2001 22:00:51 +0000 (23:00 +0100)
committerAlexandre Cassen <acassen@freebox.fr>
Mon, 28 Sep 2009 08:58:52 +0000 (10:58 +0200)
18 files changed:
genhash/Makefile
keepalived/Makefile
keepalived/cfreader.c
keepalived/cfreader.h
keepalived/httpget.c
keepalived/httpget.h
keepalived/icmpcheck.c
keepalived/icmpcheck.h
keepalived/iputils.c
keepalived/iputils.h
keepalived/ipvswrapper.c
keepalived/ipvswrapper.h
keepalived/keepalived.c
keepalived/keepalived.h
keepalived/tcpcheck.c
keepalived/tcpcheck.h
keepalived/utils.c
keepalived/utils.h

index 000c444..a560f0d 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile
-# Alexandre Cassen <Alexandre.Cassen@canal-plus.com>
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
 
 EXEC= genhash
 CC= gcc
@@ -21,4 +21,4 @@ clean:
        rm -f core *.o $(EXEC) 
 
 install:
-       cp -av genhash /usr/bin/
+       cp -av genhash /usr/bin
index 20d0125..9ca1c82 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile
-# Alexandre Cassen <Alexandre.Cassen@canal-plus.com>
+# Alexandre Cassen <Alexandre.Cassen@wanadoo.fr>
 
 EXEC= keepalived
 CC= gcc
index c81f8ce..a6318b0 100644 (file)
@@ -7,7 +7,7 @@
  *              data structure representation the conf file representing
  *              the loadbalanced server pool.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: cfreader.c,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
@@ -131,24 +131,24 @@ void PrintLst(virtualserver * lstptr)
     printf("Queue empty !!!\n");
   else
     while(lstptr != NULL) {
-      bzero(tempbuff,TEMPBUFFERLENGTH);
+      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) {
-        bzero(tempbuff,TEMPBUFFERLENGTH);
+        memset(tempbuff,0,TEMPBUFFERLENGTH);
         sprintf(tempbuff," -> SVR IP = %s, Port = %s\n",lstptr->svr->addr_ip,lstptr->svr->addr_port);
         logmessage(tempbuff,getpid());
 
-        bzero(tempbuff,TEMPBUFFERLENGTH);
+        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());
 
-        bzero(tempbuff,TEMPBUFFERLENGTH);
+        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);
index ab4c3cd..5d3fd63 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        cfreader.c include file.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: cfreader.h,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
index cc36fdc..bf82c9b 100644 (file)
@@ -7,7 +7,7 @@
  *              url, compute a MD5 over this result and match it to the
  *              expected value.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: httpget.c,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
@@ -76,7 +76,7 @@ int GET(char *IP_SRC,char *IP_DST, char *PORT_DST, char *URL, char *buffer)
     return(SOCKET_ERROR);
   }
 
-  bzero(&adr_serv,long_inet);
+  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));
@@ -130,7 +130,7 @@ int HTTP_GET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *URL,char MDResult[0x
   int retcode=0;
 
   bufferget=(char *)malloc(GET_BUFFER_LENGTH);
-  bzero(bufferget,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);
index e6e316a..8105f05 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        httpget.c include file.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: httpget.h,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
index 64da749..66ab6d2 100644 (file)
@@ -6,12 +6,19 @@
  * Part:        ICMP CHECK. Build an ICMP packet and send it to a remote
  *              server.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: icmpcheck.c,v 0.2.3 2001/01/01 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:     
- *              Alexandre Cassen      :       Initial release
+ *         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 3 time ECHO_REQUEST 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
@@ -27,34 +34,29 @@ int recvfrom_wto(int s, char *buf, int len, struct sockaddr *saddr, int timo)
   struct timeval to;
   fd_set readset,writeset;
 
-  to.tv_sec  = timo/100000;
-  to.tv_usec = (timo - (to.tv_sec*100000))*10;
+  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) { 
-    //printf("select failed !!!\n"); 
     return(-1);
   }
-  if (nfound==0) return -1;  /* timeout */
+  if (nfound==0) return -1;
   slen=sizeof(struct sockaddr);
   n=recvfrom(s,buf,len,0,saddr,&slen);
-  if (n<0) return -1; // printf("Error recvfrom");
+  if (n<0) return -1;
   return n;
 }
 
-int ICMP_CHECK(char dst_ip[16])
+int ICMP_SEND_ECHOREQUEST(char *IP_DST)
 {
   struct iphdr *ipHdr;
   struct icmphdr *icmpHdr;
-  struct sockaddr_in addr ;
-  struct sockaddr_in response_addr ;
-  struct ip *ip;
-  struct icmp *icp;
+  struct sockaddr_in addr;
   unsigned char *sendbuff;
-  unsigned char *recvbuff;
   char *debugmsg;
   char on = 1;
   int hlen;
@@ -66,19 +68,20 @@ int ICMP_CHECK(char dst_ip[16])
   debugmsg=(char *)malloc(LOGBUFFER_LENGTH);   
   sendbuff = (unsigned char *)malloc(BUFFSIZE);
 
-  bzero(sendbuff,BUFFSIZE);
+  memset(debugmsg,0,BUFFSIZE);
+  memset(sendbuff,0,BUFFSIZE);
        
-  if( (sockfd = socket( AF_INET , SOCK_RAW , IPPROTO_ICMP )) < 0 ) {
+  if((sockfd = socket( AF_INET , SOCK_RAW , IPPROTO_ICMP )) < 0) {
     free(debugmsg);
     free(sendbuff);
-    return(0);
+    return(SOCKET_ERROR);
   }
        
-  if( setsockopt(sockfd , IPPROTO_IP , IP_HDRINCL , &on , sizeof(on)) < 0 ) {
+  if(setsockopt(sockfd , IPPROTO_IP , IP_HDRINCL , &on , sizeof(on)) < 0) {
     free(debugmsg);
     free(sendbuff);
     close(sockfd);
-    return(0);
+    return(SOCKET_ERROR);
   }
 
   ipHdr = (struct iphdr *)sendbuff;
@@ -93,12 +96,11 @@ int ICMP_CHECK(char dst_ip[16])
   ipHdr->protocol = IPPROTO_ICMP;
   ipHdr->check = 0 ;
 
-  if( hostToaddr(dst_ip, &tmp) < 0 ) {
-    // perror("Host to addr conversion failed!");
+  if( hostToaddr(IP_DST, &tmp) < 0 ) {
     close(sockfd);
     free(sendbuff);
     free(debugmsg);
-    return(0);
+    return(SOCKET_ERROR);
   }
 
   ipHdr->daddr = tmp;
@@ -110,77 +112,167 @@ int ICMP_CHECK(char dst_ip[16])
   icmpHdr->un.echo.sequence = getpid();
   icmpHdr->checksum = in_cksum( (unsigned short *)icmpHdr , sizeof(struct icmphdr) );
 
-  bzero( (char *)&addr, sizeof(addr) );
+  memset((char *)&addr,0,sizeof(addr));
   addr.sin_addr.s_addr = ipHdr->daddr;
   addr.sin_family = AF_INET;
 
-  /* Add the icmp data part */
-  bcopy(ICMP_DATA,sendbuff+HDRBUFFSIZE,sizeof(ICMP_DATA));
+  /* Add the icmp data part 
+  memcpy(sendbuff+HDRBUFFSIZE,ICMP_DATA,sizeof(ICMP_DATA)); */
        
   if( sendto(sockfd, sendbuff , sizeof(struct iphdr)+sizeof(struct icmphdr) , 0 , (struct sockaddr *)&addr , sizeof(addr)) < 0 ) {
-    //perror("SendTo Error:");
     close(sockfd);
     free(sendbuff);
     free(debugmsg);
-    return(0);
+    return(SOCKET_ERROR);
   }
 
-  /* Handle arp request */
-  sleep(DELAY_TIME);
+  close(sockfd);
+  free(sendbuff);
+  free(debugmsg);
+  return(SOCKET_SUCCESS);
+}
+
+int ICMP_RCV_ECHOREPLY(char *IP_DST)
+{
+  struct sockaddr_in response_addr ;
+  struct iphdr *ip;
+  struct icmphdr *icp;
+  unsigned char *recvbuff;
+  char *debugmsg;
+  time_t hint;
+  struct tm *date;
+  int timer_before, timer_after;
+  char on = 1;
+  int hlen;
+  int result;
+  int sockfd;
+  int loop=1;
 
-  /* Echo reply test */
+  /* Packet pointer affectation */
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);   
   recvbuff=(char *)malloc(BUFFSIZE);
-  bzero((char *)recvbuff,BUFFSIZE);
+  memset((char *)recvbuff,0,BUFFSIZE);
 
-  result=recvfrom_wto(sockfd,recvbuff,BUFFSIZE,(struct sockaddr *)&response_addr,select_time);
+  if((sockfd = socket( AF_INET , SOCK_RAW , IPPROTO_ICMP )) < 0) {
+    free(debugmsg);
+    free(recvbuff);
+    return(SOCKET_ERROR);
+  }
+       
+  if(setsockopt(sockfd , IPPROTO_IP , IP_HDRINCL , &on , sizeof(on)) < 0) {
+    free(debugmsg);
+    free(recvbuff);
+    close(sockfd);
+    return(SOCKET_ERROR);
+  }
+
+  /* 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) {
+    result=recvfrom_wto(sockfd,recvbuff,BUFFSIZE,(struct sockaddr *)&response_addr,select_time);
 
 #ifdef DEBUG
-  if (result<0) { 
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"ICMP_CHECK : icmp timeout to %s...\n",dst_ip);
-    logmessage(debugmsg,getpid());
-  }
+    if (result<0) { 
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"ICMP_CHECK : icmp timeout to [%s]...\n",IP_DST);
+      logmessage(debugmsg,getpid());
+    }
 #endif
 
-  ip = (struct ip *)recvbuff;
+    ip = (struct iphdr *)recvbuff;
+    hlen = ip->ihl << 2;
+
+    if (result < hlen+ICMP_MINLEN) {
+#ifdef DEBUG
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"ICMP_CHECK : Received packet too short according to ICMP protocol from [%s]...\n",IP_DST);
+      logmessage(debugmsg,getpid());
+#endif
+    }
 
-  hlen = ip->ip_hl << 2;
+    icp = (struct icmphdr *)(recvbuff + hlen);
+    if ( (icp->type == ICMP_ECHOREPLY) && 
+         (ip->saddr == inet_addr(IP_DST)) &&
+         (result >= hlen+ICMP_MINLEN) ) {
+      close(sockfd);
+      free(recvbuff);
+      free(debugmsg);
+      return(SOCKET_SUCCESS);
+    }
 
-  if (result < hlen+ICMP_MINLEN) {
 #ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"ICMP_CHECK : Received packet too short according to ICMP protocol to %s...\n",dst_ip);
-    logmessage(debugmsg,getpid());
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] retry\n",IP_DST);
+      logmessage(debugmsg,getpid());
 #endif
-    close(sockfd);
-    free(sendbuff);
-    free(debugmsg);
-    return(0);
+
+    /* 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;
   }
 
-  icp = (struct icmp *)(recvbuff + hlen);
-  if (icp->icmp_type != ICMP_ECHOREPLY) {
 #ifdef DEBUG
-    memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"ICMP_CHECK : ICMP ECHO REPLY not received from %s !!!\n",dst_ip);
-    logmessage(debugmsg,getpid());
+  memset(debugmsg,0,LOGBUFFER_LENGTH);
+  sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] packet losed\n",IP_DST);
+  logmessage(debugmsg,getpid());
 #endif
-    close(sockfd);
-    free(sendbuff);
-    free(debugmsg);
-    return(0);
-  } else {
+
+  close(sockfd);
+  free(recvbuff);
+  free(debugmsg);
+  return(SOCKET_ERROR);
+}
+
+int ICMP_CHECK(char *IP_DST)
+{
+  char *debugmsg;
+  int loop=1;
+  int retry=0;
+
+  /* Memory allocation for the data structures */
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
+
+  while(loop) {
+
+    if(!ICMP_SEND_ECHOREQUEST(IP_DST)) {
+#ifdef DEBUG
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"ICMP_CHECK : Can't send ECHO_REQUEST to [%s]\n",IP_DST);
+      logmessage(debugmsg,getpid());
+#endif
+      free(debugmsg);
+      return(SOCKET_ERROR);
+    }
+    if(ICMP_RCV_ECHOREPLY(IP_DST)) {
+      loop=0;
+    } else {
+      retry++;
+#ifdef DEBUG
+      memset(debugmsg,0,LOGBUFFER_LENGTH);
+      sprintf(debugmsg,"ICMP_CHECK : Reexpedite ECHO_REQUEST to [%s]\n",IP_DST);
+      logmessage(debugmsg,getpid());
+#endif
+      loop=(retry==NB_RETRY)?0:1;
+    }
+  }
+
+  if(retry==NB_RETRY) {
 #ifdef DEBUG
     memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"ICMP_CHECK : ICMP ECHO REPLY recived from %s...\n",dst_ip);
+    sprintf(debugmsg,"ICMP_CHECK : ECHO_REPLY not received from [%s] after 3 try\n",IP_DST);
     logmessage(debugmsg,getpid());
 #endif
+    free(debugmsg);
+    return(SOCKET_ERROR);
   }
 
-  free(sendbuff);
-  free(recvbuff);
   free(debugmsg);
-
-  close(sockfd);
-  return(1);
+  return(SOCKET_SUCCESS);
 }
index df862f8..ae41786 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        icmpcheck.c include file.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: icmpcheck.h,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
 
-#define ICMP_DATA "KeepAlive for LVS v1.0"
+#define ICMP_DATA "keepalived for LVS"
+
+#define SOCKET_ERROR   0
+#define SOCKET_SUCCESS 1
 
 #define HDRBUFFSIZE (sizeof(struct icmphdr) + sizeof(struct iphdr))
 #define BUFFSIZE (HDRBUFFSIZE + sizeof(ICMP_DATA))
 #define SIZE_ICMP_HDR ICMP_MINLEN
 
 #define DELAY_TIME 1
+#define NB_RETRY   3
 
 #define LOGBUFFER_LENGTH 100
 
 #define select_time (DEFAULT_SELECT_TIME * 100)
 
 /* prototypes  */
-int ICMP_CHECK(char dst_ip[16]);
+int ICMP_CHECK(char *IP_DST);
 
 #endif
index fc35555..252b109 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        IP packets Utilities.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: iputils.c,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
index afd2928..f36fc54 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        iputils.c include file.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: iputils.h,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
index 97e8780..0fcf24d 100644 (file)
@@ -6,7 +6,7 @@
  * Part:        IPVS Kernel wrapper. Use setsockopt call to add/remove
  *              server to/from the loadbalanced server pool.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: ipvswrapper.c,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
@@ -47,7 +47,7 @@ int ipvs_pool_cmd(int cmd, virtualserver *vserver)
       if (strcmp(vserver->svr->loadbalancing_kind,"TUN")==0)
         ctl.u.vs_user.masq_flags = IP_MASQ_F_VS_TUNNEL;
       else {
-        bzero(debugmsg,LOGBUFFER_LENGTH);
+        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);
index ba56baf..355bd55 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * Part:        ipvswrapper.c include file.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: ipvswrapper.h,v 0.2.1 2000/12/09 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
index 856d96e..d2dc4a7 100644 (file)
@@ -5,12 +5,15 @@
  *
  * Part:        Main program structure.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: keepalived.c,v 0.2.3 2001/01/01 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:       
- *              Alexandre Cassen      :       Initial release
+ *         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
@@ -48,9 +51,8 @@ int main(int argc, char **argv)
 
   if (signal(SIGTERM,sig_handler) == SIG_IGN)
     signal(SIGTERM,SIG_IGN);
-
-  signal(SIGINT,sig_handler);
-  signal(SIGHUP,sig_handler);
+  signal(SIGINT,SIG_IGN);
+  signal(SIGHUP,SIG_IGN);
 
   if ((lstVS=(virtualserver *)ConfReader(lstVS,delay_loop))==NULL) {
     logmessage("Config file contain no data\n",getpid());
@@ -67,8 +69,7 @@ int main(int argc, char **argv)
 
   while (keep_going) {
     perform_checks(lstVS);
-/*    sleep(delay_loop); */
-    sleep(60);
+    sleep(delay_loop);
   }
 
   return 0;
@@ -87,7 +88,6 @@ void perform_ipvs(int alive, virtualserver *lstptr)
   char *logbuffer;
   
   logbuffer=(char *)malloc(LOGBUFFER_LENGTH);
-
   if (!lstptr->svr->alive && alive) {
     lstptr->svr->alive=alive;
     memset(logbuffer,0,LOGBUFFER_LENGTH);
@@ -139,6 +139,9 @@ void perform_checks(virtualserver * lstptr)
 
       if (strcmp(lstptr->svr->keepalive_method,"ICMP_CHECK") == 0) {
         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);
@@ -146,6 +149,9 @@ void perform_checks(virtualserver * lstptr)
             perform_ipvs(1,lstptr);
           }
         } 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);
@@ -157,7 +163,9 @@ void perform_checks(virtualserver * lstptr)
 
       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->alive) {
             memset(logbuffer,0,LOGBUFFER_LENGTH);
             sprintf(logbuffer,"TCP check succeed to %s:%s.\n",lstptr->svr->addr_ip,
@@ -166,9 +174,11 @@ void perform_checks(virtualserver * lstptr)
             perform_ipvs(1,lstptr);
           }
         } else {
+#ifdef DEBUG
           logmessage("TCP check failed\n",getpid());
+#endif
           if (lstptr->svr->alive) {
-            bzero(logbuffer,LOGBUFFER_LENGTH);
+            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());
@@ -183,7 +193,9 @@ void perform_checks(virtualserver * lstptr)
                  lstptr->svr->keepalive_url,MD5Result)) {
 
           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,
@@ -192,7 +204,9 @@ void perform_checks(virtualserver * lstptr)
               perform_ipvs(1,lstptr);
             }
           } 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,
index 891acfd..d11b930 100644 (file)
 /* Global variables */
 volatile sig_atomic_t keep_going = 1;
 virtualserver *lstVS;
-int delay_loop = 5;
+int delay_loop = 60;
 
 /* Build version */
 #define PROG    "keepalived"
-#define VERSION "0.2.1 (12/23, 2000), Alexandre Cassen"
+#define VERSION "0.2.3 (01/01, 2001), Alexandre Cassen"
 
 /* prototypes */
 void sig_handler(int signum);
index 3db0b85..a884eb6 100644 (file)
@@ -7,13 +7,22 @@
  *              server. This check implement the tcp half open connection
  *              check.
  *  
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: tcpcheck.c,v 0.2.3 2000/12/29 $
  * 
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *              
  * Changes:     
- *              Alexandre Cassen      :       Initial release
- *              
+ *         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
 
 #include "tcpcheck.h"
 
-#define SEQUENCE 0x28376839
+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)
+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 };
@@ -33,12 +76,13 @@ int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG)
   struct iphdr *packet_ip;
   struct tcphdr *packet_tcp;
   struct tcphdr_pseudo packet_tcppseudo;
-  struct sockaddr dest;
+  struct sockaddr_in dest;
   char *packet;
 
   /* Packet pointer affectation */
   packet=(char *)malloc(SYNPACKET_LENGTH);
-  bzero(packet,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);
 
@@ -68,7 +112,7 @@ int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG)
   /* Fill in the TCP header structure */
   packet_tcp->source  = htons(STCP);
   packet_tcp->dest    = htons(atoi(PORT_DST));
-  packet_tcp->seq     = htonl(SEQUENCE);
+  packet_tcp->seq     = SEQ;
   packet_tcp->doff    = sizeof(struct tcphdr)/4;
   packet_tcp->ack_seq = 0;
   packet_tcp->res1    = 0;
@@ -95,9 +139,10 @@ int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG)
                              sizeof(struct tcphdr_pseudo));
 
   /* Fill in the Sockaddr structure */
-  dest.sa_family = AF_INET;
-  bcopy(&packet_ip->daddr,&dest.sa_data[2],4);
-  bcopy(&packet_tcp->source,&dest.sa_data[0],2);
+  /* 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) {
@@ -105,32 +150,40 @@ int TCP_SEND_PACKET(char *IP_SRC,char *IP_DST,char *PORT_DST,char *FLAG)
     free(packet);
     return(SOCKET_ERROR);
   }
+
+  close(rawsock);
   free(packet);
   return(SOCKET_SUCCESS);
 }
 
-int TCP_RCV_SYNACK_PACKET()
+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 dest;
+  struct sockaddr_in dest;
   char *packet;
-  int fromlen=0;
-
-  fromlen=sizeof(struct sockaddr);
 
   /* Packet pointer affectation */
+  debugmsg=(char *)malloc(LOGBUFFER_LENGTH);
   packet=(char *)malloc(SYNPACKET_LENGTH);
-  bzero(packet,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);
   }
@@ -140,54 +193,113 @@ int TCP_RCV_SYNACK_PACKET()
   li.l_linger=0;
   setsockopt(rawsock,SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(struct linger));
 
-  if (recvfrom(rawsock,packet,SYNPACKET_LENGTH,
-               0,(struct sockaddr *)&dest,&fromlen) < 0) {
-    free(packet);
-    close(rawsock);
-    return(SOCKET_ERROR);
-  }
+  /* 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);
 
-  close(rawsock);
+  /* 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;
 
-  if ( packet_tcp->syn && packet_tcp->ack) {
-    free(packet);
-    return(SOCKET_SUCCESS);
-  } else {
-    free(packet);
-    return(SOCKET_ERROR);
+  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);
-  bzero(debugmsg,LOGBUFFER_LENGTH);
 
-  if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"SYN")) {
+  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());
+      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);
+      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(!TCP_RCV_SYNACK_PACKET()) {
+  if (retry==NB_RETRY) {
 #ifdef DEBUG
     memset(debugmsg,0,LOGBUFFER_LENGTH);
-    sprintf(debugmsg,"TCP_CHECK : Didn't recieve SYN response from [%s:%s]\n",IP_DST,PORT_DST);
+    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);
   }
 
-  if(!TCP_SEND_PACKET(IP_SRC,IP_DST,PORT_DST,"RST ACK")) {
+  /* 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);
index 52a785d..8c3384e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        tcpcheck.c include file.
  *
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: tcpcheck.h,v 0.2.1 2000/12/09 $
  *
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *
@@ -22,6 +22,7 @@
 #define CFREADER_H
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <signal.h>
 #include <netdb.h>
 
 #define SOCKET_ERROR   0
 #define SOCKET_SUCCESS 1
-#define STCP 1111
+#define STCP           1111
 
 #define LOGBUFFER_LENGTH 100
 #define SYNPACKET_LENGTH 1024
 #define HOSTNAME_LENGTH  30
 
+#define NB_RETRY 3
+
 /* Structures used */
 struct tcphdr_pseudo {
   unsigned int saddr;
index aabdea4..719670c 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        General program utils.
  *
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: utils.c,v 0.2.1 2000/12/09 $
  *
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *
index 42e6984..231c8e8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Part:        utils.c include file.
  *
- * Version:     $Id: keepalived.c,v 0.2.1 2000/12/09 $
+ * Version:     $Id: utils.h,v 0.2.1 2000/12/09 $
  *
  * Author:      Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
  *