* keepalived-0.7.6 released.
* Created a common library for code modularization. This lib will
be used by all Keepalived components (genhash + Keepalived) to
reduce repeated and duplicated code.
* Rewrote the genhash utility using the common lib. The design is
similar to Keepalived core design.
* Reviewed the autoconf and Makefiles for new code architecture.
* Created a html utility lib for HTTP headers manipulations.
* Extended the CHECK_HTTP and CHECK_SSL checkers to support remote
webserver HTTP header status_code. HTTP status_code is parsed
according to rfc2616.6.1. The keyword created for the new feature is
"status_code" inside and "url" declaration. "status_code" feature
can be mixed with "digest" feature. See the samples directory
keepalived/samples/keepalived.conf.status_code for example.
* Review the CHECK_HTTP and CHECK_SSL MD5SUM code to use a common
stream handling function.
* Matthijs van der Klip, <Matthijs.van.der.Klip@tech.omroep.nl> and I
fixed a bug into the HTTP/SSL code that close the socket fd even
if remote webserver has not been connected. As a result of fact,
next socket created were imediatly closed. As a side effect, this
altered the SMTP notification when remote webserver checked fall. No
SMTP notification were sent if webserver were detected DOWN. Thanks
to Matthijs for time debugging and investigation.
* VRRP : Rewrote the previous Gratuitous ARP facility. Created a lib
(vrrp_arp.c) dealing with PF_PACKET-SOCK_RAW-ETH_P_RARP and
sockaddr_ll.
* VRRP : Some cosmetics patch for messages logging.
* VRRP : Fixed an issue during VRRP packet building, appending VRRP
VIPs to the VRRP packet in the network order form.
* VRRP : Reviewed the previous VRRP packet building process to not
create the ARP header. Removec the previous hacky
PF_PACKET-SOCK_PACKET-0x300 to use AF_INET-SOCK_RAW-PROTO to leave
kernel appending ARP header since code doesn t currently support
VRRP VMAC.
* VRRP : Rewrote the previous vrrp_send_pkt() function to deal with
sendmsg(). optimization lazzyness :)
* VRRP : Extended the interfaces library to support common utility
functions (if_setsockopt_hdrincl, if_setsockopt_bindtodevice, ...)
* VRRP : Finally extend the code to support VRRP IPSEC-AH authentication
method. Created a IPSEC-AH seq_number syncrhonization mecanism during
VRRP MASTER/BACKUP elections.
* VRRP : Extended the VRRP TSM to speed up instances syncrhonization
during FAULT->BACKUP & FAULT->MASTER state transition.
* Some cosmetics patches. This release is proposed as a 1.0.0 STABLE
release candidate.
+2002-11-20 Alexandre Cassen <acassen@linux-vs.org>
+ * keepalived-0.7.6 released.
+ * Created a common library for code modularization. This lib will
+ be used by all Keepalived components (genhash + Keepalived) to
+ reduce repeated and duplicated code.
+ * Rewrote the genhash utility using the common lib. The design is
+ similar to Keepalived core design.
+ * Reviewed the autoconf and Makefiles for new code architecture.
+ * Created a html utility lib for HTTP headers manipulations.
+ * Extended the CHECK_HTTP and CHECK_SSL checkers to support remote
+ webserver HTTP header status_code. HTTP status_code is parsed
+ according to rfc2616.6.1. The keyword created for the new feature is
+ "status_code" inside and "url" declaration. "status_code" feature
+ can be mixed with "digest" feature. See the samples directory
+ keepalived/samples/keepalived.conf.status_code for example.
+ * Review the CHECK_HTTP and CHECK_SSL MD5SUM code to use a common
+ stream handling function.
+ * Matthijs van der Klip, <Matthijs.van.der.Klip@tech.omroep.nl> and I
+ fixed a bug into the HTTP/SSL code that close the socket fd even
+ if remote webserver has not been connected. As a result of fact,
+ next socket created were imediatly closed. As a side effect, this
+ altered the SMTP notification when remote webserver checked fall. No
+ SMTP notification were sent if webserver were detected DOWN. Thanks
+ to Matthijs for time debugging and investigation.
+ * VRRP : Rewrote the previous Gratuitous ARP facility. Created a lib
+ (vrrp_arp.c) dealing with PF_PACKET-SOCK_RAW-ETH_P_RARP and
+ sockaddr_ll.
+ * VRRP : Some cosmetics patch for messages logging.
+ * VRRP : Fixed an issue during VRRP packet building, appending VRRP
+ VIPs to the VRRP packet in the network order form.
+ * VRRP : Reviewed the previous VRRP packet building process to not
+ create the ARP header. Removec the previous hacky
+ PF_PACKET-SOCK_PACKET-0x300 to use AF_INET-SOCK_RAW-PROTO to leave
+ kernel appending ARP header since code doesn t currently support
+ VRRP VMAC.
+ * VRRP : Rewrote the previous vrrp_send_pkt() function to deal with
+ sendmsg(). optimization lazzyness :)
+ * VRRP : Extended the interfaces library to support common utility
+ functions (if_setsockopt_hdrincl, if_setsockopt_bindtodevice, ...)
+ * VRRP : Finally extend the code to support VRRP IPSEC-AH authentication
+ method. Created a IPSEC-AH seq_number syncrhonization mecanism during
+ VRRP MASTER/BACKUP elections.
+ * VRRP : Extended the VRRP TSM to speed up instances syncrhonization
+ during FAULT->BACKUP & FAULT->MASTER state transition.
+ * Some cosmetics patches. This release is proposed as a 1.0.0 STABLE
+ release candidate.
+
2002-09-17 Alexandre Cassen <acassen@linux-vs.org>
* keepalived-0.7.1 released.
* Fixed a MISC_CHECK issue when registering next timer checker. Must
# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
all:
+ $(MAKE) -C lib || exit 1;
$(MAKE) -C keepalived
$(MAKE) -C genhash
@echo ""
@echo "Make complete"
clean:
+ $(MAKE) -C lib clean
$(MAKE) -C keepalived clean
$(MAKE) -C genhash clean
distclean:
+ $(MAKE) -C lib distclean
$(MAKE) -C keepalived distclean
$(MAKE) -C genhash distclean
rm -f Makefile
done
-OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile"
+OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile lib/Makefile"
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
if test "$KERN" = "_KRNL_2_4_"; then
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
AC_CHECK_FUNCS(gettimeofday select socket strerror strtol uname)
dnl ----[ Process output target ]----
-OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile"
+OUTPUT_TARGET="$OUTPUT_TARGET keepalived/Makefile keepalived/healthcheck/Makefile keepalived/vrrp/Makefile lib/Makefile"
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
if test "$KERN" = "_KRNL_2_4_"; then
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
--- /dev/null
+Alexandre Cassen, <Alexandre.Cassen@wanadoo.fr>
+++ /dev/null
-Alexandre Cassen <acassen@linux-vs.org>
-Jan Holmberg <jan@artech.se>
+2002-11-18 Alexandre Cassen <acassen@linux-vs.org>
+ * Rewrote the whole previous code to use common
+ template libraries.
+
2002-01-17 Alexandre Cassen <acassen@linux-vs.org>
* Patched the dynamic GET request lenght allocation.
The global synopsis for the tool is :
[user@lvs]$ genhash --help
- genhash Version 0.4.9 (30/11, 2001)
+ genhash v1.0.0 (18/11, 2002)
Usage:
genhash -s server-address -p port -u url
- genhash -S -K priv-key-file -P pem-password -s server-address -p port -u url
- genhash -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url
+ genhash -S -s server-address -p port -u url
genhash -h
- genhash -v
+ genhash -r
Commands:
Either long or short options are allowed.
genhash --server -s Use the specified remote server address.
genhash --port -p Use the specified remote server port.
genhash --url -u Use the specified remote server url.
- genhash --use-private-key -K Use the specified SSL private key.
- genhash --use-password -P Use the specified SSL private key password.
- genhash --use-certificate -C Use the specified SSL Certificate file.
+ genhash --use-virtualhost -V Use the specified virtualhost in GET query.
+ genhash --verbose -v Use verbose mode output.
genhash --help -h Display this short inlined help screen.
- genhash --version -v Display the version number
+ genhash --release -r Display the release number
Imagine we have a remote HTTP/HTTPS server owning the IP address 192.168.200.10.
We want to generate a MD5SUM over the server root url (/).
-# Makefile
+# Makefile.in
#
-# Keepalived OpenSource project.
-#
-# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+# Copyright (C) 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = ../bin/genhash
-EXEC = genhash
-BIN = ../bin
-prefix = @prefix@
+prefix = @prefix@
exec_prefix = @exec_prefix@
-bindir = @bindir@
+bindir = @bindir@
-CC = gcc
-CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes
-LDFLAGS = @LIBS@ @LDFLAGS@
+CC = @CC@
+INCLUDES = -I../lib
+CFLAGS = @CFLAGS@ $(INCLUDES) \
+ -Wall -Wunused -Wstrict-prototypes
+LDFLAGS = -lssl -lpopt
-OBJS = main.o client.o common.o
+OBJS = main.o sock.o layer4.o http.o ssl.o
+LIB_OBJS = ../lib/timer.o ../lib/scheduler.o \
+ ../lib/memory.o ../lib/list.o ../lib/utils.o \
+ ../lib/html.o
all: $(EXEC)
- strip $(BIN)/$(EXEC)
+ strip $(EXEC)
@echo ""
@echo "Make complete"
-$(EXEC): $(OBJS)
- $(CC) $(OBJS) -o $(BIN)/$(EXEC) $(LDFLAGS)
+$(EXEC): $(LIB_OBJS) $(OBJS)
+ $(CC) $(LIB_OBJS) $(OBJS) -o $(EXEC) $(LDFLAGS)
clean:
rm -f core *.o
install:
install -d $(bindir)
- install -m 755 $(BIN)/$(EXEC) $(bindir)/
+ install -m 755 $(EXEC) $(bindir)/
+
+mrproper: clean distclean
+ rm -f config.*
+
+# Code dependencies
+
+main.o: main.c main.h ../lib/utils.h sock.h ../lib/timer.h \
+ http.h ssl.h ../lib/scheduler.h ../lib/memory.h
+sock.o: sock.c sock.h ../lib/utils.h layer4.h ssl.h main.h \
+ ../lib/memory.h
+layer4.o: layer4.c layer4.h ../lib/scheduler.h ../lib/utils.h \
+ main.h ssl.h
+http.o: http.c http.h sock.h ../lib/scheduler.h ../lib/utils.h \
+ layer4.h main.h ../lib/html.h ../lib/timer.h ../lib/scheduler.h \
+ ../lib/memory.h
+ssl.o: ssl.c ssl.h http.h main.h ../lib/utils.h ../lib/html.h
+++ /dev/null
-* Create a generic function to handle remote server reply.
- That way we will remove duplicate code for read reply.
-* beautifull the code.
+++ /dev/null
-/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
- *
- * Part: Layer4 global functions.
- *
- * Version: $Id: client.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
- *
- * Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * 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 "client.h"
-
-int
-tcp_connect(int fd, char *host, int port)
-{
- int long_inet = sizeof (struct sockaddr_in);
- struct sockaddr_in adr_serv;
- struct hostent *ip_serv;
- int arglen;
- struct timeval tv;
- fd_set wfds;
- int rc, val;
-
- /* Proceed remote hostname */
- memset(&ip_serv, 0, sizeof (struct hostent));
- if ((ip_serv = gethostbyname(host)) == NULL)
- return TCP_RESOLV_ERROR;
-
- /* Fill in connection structure */
- memset(&adr_serv, 0, long_inet);
- adr_serv.sin_family = AF_INET;
- adr_serv.sin_port = htons(port);
- adr_serv.sin_addr = *(struct in_addr *) ip_serv->h_addr;
-
- /* Set read/write socket nonblock */
- val = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, val | O_NONBLOCK);
-
- /* Connect the remote host */
- rc = connect(fd, (struct sockaddr *) &adr_serv, long_inet);
- if (rc == -1) {
- if (errno != EINPROGRESS) {
- rc = errno;
- return TCP_CONNECT_ERROR;
- }
- }
-
- /* Timeout settings */
- tv.tv_sec = SOCKET_TIMEOUT_READ;
- tv.tv_usec = 0;
- FD_ZERO(&wfds);
- FD_SET(fd, &wfds);
-
- rc = select(fd + 1, NULL, &wfds, NULL, &tv);
- if (!FD_ISSET(fd, &wfds))
- return TCP_WRITE_TIMEOUT;
-
- if (rc <= 0)
- return TCP_SELECT_ERROR;
-
- rc = 0;
- arglen = sizeof (int);
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &rc, &arglen) < 0)
- rc = errno;
- if (rc)
- return TCP_CONNECT_FAILED;
-
- /* Restore socket parameters */
- fcntl(fd, F_SETFL, val);
-
- return TCP_CONNECT_SUCCESS;
-}
-
-int
-tcp_send(int fd, char *request, int len)
-{
- if (send(fd, request, len, 0) == -1)
- return TCP_SEND_ERROR;
- return 0;
-}
-
-int
-tcp_read_to(int fd)
-{
- struct timeval tv;
- fd_set rfds;
-
- /* Timeout settings */
- tv.tv_sec = SOCKET_TIMEOUT_READ;
- tv.tv_usec = 0;
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
-
- /* attempt read data */
- select(fd + 1, &rfds, NULL, NULL, &tv);
- if (!FD_ISSET(fd, &rfds))
- return TCP_READ_TIMEOUT;
- return 0;
-}
-
-int
-tcp_sock(void)
-{
- int fd;
- struct sockaddr_in adr_local;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
- return (-1);
- memset(&adr_local, 0, sizeof (struct sockaddr_in));
- adr_local.sin_family = AF_INET;
- adr_local.sin_port = htons(0);
- adr_local.sin_addr.s_addr = htonl(INADDR_ANY);
-
- if (bind
- (fd, (struct sockaddr *) &adr_local, sizeof (struct sockaddr_in)))
- return (-1);
-
- return (fd);
-}
+++ /dev/null
-/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
- *
- * Part: client.c include file.
- *
- * Version: $Id: client.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
- *
- * Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * 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 _CLIENT_H
-#define _CLIENT_H
-
-/* System includes */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-/* Socket timeout */
-#define SOCKET_TIMEOUT_READ 3
-#define SOCKET_TIMEOUT_WRITE 3
-
-/* Return codes */
-/* systems predefined ret codes */
-#define OUT_OF_MEMORY (1 << 0)
-
-/* TCP predefined ret codes */
-#define TCP_BIND_ERROR (1 << 1)
-#define TCP_RESOLV_ERROR (1 << 2)
-#define TCP_CONNECT_ERROR (1 << 3)
-#define TCP_CONNECT_SUCCESS (1 << 4)
-#define TCP_WRITE_TIMEOUT (1 << 5)
-#define TCP_SELECT_ERROR (1 << 6)
-#define TCP_CONNECT_FAILED (1 << 7)
-#define TCP_SEND_ERROR (1 << 8)
-#define TCP_READ_TIMEOUT (1 << 9)
-
-/* Upper Layer - HTTP predefined ret codes */
-#define HTTP_GET_SUCCESS (1 << 10)
-
-/* Upper Layer - SSL predefined ret codes */
-#define SSL_WRITE_ERROR (1 << 11)
-#define SSL_INCOMPLETE_WRITE (1 << 12)
-#define SSL_READ_ERROR (1 << 13)
-#define SSL_SHUTDOWN_FAILED (1 << 14)
-#define SSL_GET_SUCCESS (1 << 15)
-
-/* Prototypes */
-extern int tcp_connect(int fd, char *host, int port);
-extern int tcp_send(int fd, char *request, int len);
-extern int tcp_read_to(int fd);
-extern int tcp_sock(void);
-
-#endif
+++ /dev/null
-/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
- *
- * Part: Common SSL functions.
- *
- * Version: $Id: common.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
- *
- * Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * 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 "common.h"
-
-static BIO *bio_err = 0;
-static char *pass;
-
-/* A simple error and exit routine*/
-int
-err_exit(char *string)
-{
- fprintf(stderr, "%s\n", string);
- exit(0);
-}
-
-/* Print SSL errors and exit*/
-int
-berr_exit(char *string)
-{
- BIO_printf(bio_err, "%s\n", string);
- ERR_print_errors(bio_err);
- exit(0);
-}
-
-/*The password code is not thread safe*/
-static int
-password_cb(char *buf, int num, int rwflag, void *userdata)
-{
- if (num < strlen(pass) + 1)
- return (0);
-
- strcpy(buf, pass);
- return (strlen(pass));
-}
-
-static void
-sigpipe_handle(int x)
-{
-}
-
-/* SSL context initializer */
-SSL_CTX *
-initialize_ctx(char *keyfile, char *password, char *cafile)
-{
- SSL_METHOD *meth;
- SSL_CTX *ctx;
-
- if (!bio_err) {
- /* Global system initialization */
- SSL_library_init();
- SSL_load_error_strings();
-
- /* An error write context */
- bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
- }
-
- /* Set up a SIGPIPE handler */
- signal(SIGPIPE, sigpipe_handle);
-
- /* Create our context */
- meth = SSLv23_method();
- ctx = SSL_CTX_new(meth);
-
- /* Load our keys and certificates */
- if (keyfile)
- if (!(SSL_CTX_use_certificate_chain_file(ctx, keyfile)))
- berr_exit("Can't read certificate file");
-
- if (password) {
- pass = password;
- SSL_CTX_set_default_passwd_cb(ctx, password_cb);
- }
-
- if (keyfile)
- if (!
- (SSL_CTX_use_PrivateKey_file
- (ctx, keyfile, SSL_FILETYPE_PEM)))
- berr_exit("Can't read key file");
-
- /* Load the CAs we trust */
- if (cafile)
- if (!(SSL_CTX_load_verify_locations(ctx, cafile, 0)))
- berr_exit("Can't read CA list");
-#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
- SSL_CTX_set_verify_depth(ctx, 1);
-#endif
-
- return ctx;
-}
-
-void
-destroy_ctx(SSL_CTX * ctx)
-{
- SSL_CTX_free(ctx);
-}
+++ /dev/null
-/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
- *
- * Part: common.c include file.
- *
- * Version: $Id: common.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
- *
- * Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * 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 _COMMON_H
-#define _COMMON_H
-
-/* System includes */
-#include <string.h>
-#include <signal.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-
-/* prototypes */
-extern int berr_exit(char *string);
-extern int err_exit(char *string);
-extern SSL_CTX *initialize_ctx(char *keyfile, char *password, char *cafile);
-extern void destroy_ctx(SSL_CTX * ctx);
-
-#ifndef ALLOW_OLD_VERSIONS
-#if(OPENSSL_VERSION_NUMBER < 0x00905100L)
-#error "Must use OpenSSL 0.9.6 or later"
-#endif
-#endif
-
-#endif
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: HTTP asynchronous engine.
+ *
+ * Version: $Id: http.c,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 <errno.h>
+#include <openssl/err.h>
+#include "memory.h"
+#include "http.h"
+#include "layer4.h"
+#include "main.h"
+#include "utils.h"
+#include "html.h"
+#include "timer.h"
+
+/* extern variables */
+extern REQ *req;
+
+/*
+ * The global design of this checker is the following :
+ *
+ * - All the actions are done asynchronously.
+ * - All the actions handle timeout connection.
+ * - All the actions handle error from low layer to upper
+ * layers.
+ *
+ * The global synopsis of the inter-thread-call is :
+ *
+ * http_request_thread (send SSL GET request)
+ * v
+ * http_response_thread (initialize read stream step)
+ * / \
+ * / \
+ * v v
+ * http_read_thread ssl_read_thread (perform HTTP|SSL stream)
+ * v v
+ * ------------------------------
+ * finalize / epilog
+ */
+
+/* free allocated pieces */
+static void free_all(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+
+ DBG("Total read size read = %d Bytes, fd:%d\n",
+ sock->total_size, sock->fd);
+
+ if (sock->buffer)
+ FREE(sock->buffer);
+
+ /*
+ * Decrement the current global get number.
+ * => free the reserved thread
+ */
+ req->response_time = timer_tol(timer_now());
+ thread_add_terminate_event(thread->master);
+}
+
+/* Simple epilog functions. */
+int
+epilog(thread * thread)
+{
+ DBG("Timeout on URL : [%s]\n", req->url);
+ free_all(thread);
+ return 0;
+}
+
+/* Simple finalization function */
+int
+finalize(thread *thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ unsigned char digest[16];
+ int i;
+
+ printf("\n");
+ /* Compute final MD5 digest */
+ MD5_Final(digest, &sock->context);
+ printf(HTML_MD5);
+ print_buffer(16, digest);
+
+ printf(HTML_MD5_FINAL);
+ for (i = 0; i < 16; i++)
+ printf("%02x", digest[i]);
+ printf("\n\n");
+
+ DBG("Finalize : [%s]\n", req->url);
+ free_all(thread);
+ return 0;
+}
+
+/* Process incoming stream */
+int http_process_stream(SOCK *sock, int r)
+{
+ sock->size += r;
+ sock->total_size += r;
+
+ if (!sock->extracted) {
+ printf(HTTP_HEADER_HEXA);
+ if ((sock->extracted =
+ extract_html(sock->buffer, sock->size))) {
+ print_buffer(sock->extracted - sock->buffer, sock->buffer);
+ printf(HTTP_HEADER_ASCII);
+ for (r = 0; r < sock->extracted - sock->buffer; r++)
+ printf("%c", sock->buffer[r]);
+ printf("\n");
+
+ printf(HTML_HEADER_HEXA);
+ r = sock->size - (sock->extracted - sock->buffer);
+ if (r) {
+ print_buffer(r, sock->extracted);
+ memcpy(sock->buffer, sock->extracted, r);
+ MD5_Update(&sock->context, sock->buffer,
+ r);
+ r = 0;
+ }
+ sock->size = r;
+ } else {
+ /* minimize buffer using no 2*CR/LF found yet */
+ if (sock->size > 3) {
+ memcpy(sock->buffer,
+ sock->buffer + sock->size - 3, 3);
+ sock->size = 3;
+ }
+ }
+ } else if (sock->size) {
+ print_buffer(r, sock->buffer);
+ MD5_Update(&sock->context, sock->buffer,
+ sock->size);
+ sock->size = 0;
+ }
+
+ return 0;
+}
+
+/* Asynchronous HTTP stream reader */
+int
+http_read_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ int r = 0;
+
+ /* Handle read timeout */
+ if (thread->type == THREAD_READ_TIMEOUT)
+ return epilog(thread);
+
+ /* read the HTTP stream */
+ memset(sock->buffer, 0, MAX_BUFFER_LENGTH);
+ r = read(thread->u.fd, sock->buffer, MAX_BUFFER_LENGTH);
+
+ DBG(" [l:%d,fd:%d]\n", r, sock->fd);
+
+ if (r == -1 || r == 0) { /* -1:error , 0:EOF */
+ if (r == -1) {
+ /* We have encourred a real read error */
+ DBG("Read error with server [%s:%d]: %s\n",
+ inet_ntop2(req->addr_ip), ntohs(req->addr_port),
+ strerror(errno));
+ return epilog(thread);
+ }
+
+ /* All the HTTP stream has been parsed */
+ finalize(thread);
+ } else {
+ /* Handle the response stream */
+ http_process_stream(sock, r);
+
+ /*
+ * Register next http stream reader.
+ * Register itself to not perturbe global I/O multiplexer.
+ */
+ thread_add_read(thread->master, http_read_thread, sock,
+ thread->u.fd, HTTP_CNX_TIMEOUT);
+ }
+
+ return 0;
+}
+
+/*
+ * Read get result from the remote web server.
+ * Apply trigger check to this result.
+ */
+int
+http_response_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+
+ /* Handle read timeout */
+ if (thread->type == THREAD_READ_TIMEOUT)
+ return epilog(thread);
+
+ /* Allocate & clean the get buffer */
+ sock->buffer = (char *) MALLOC(MAX_BUFFER_LENGTH);
+
+ /* Initalize the MD5 context */
+ MD5_Init(&sock->context);
+
+ /* Register asynchronous http/ssl read thread */
+ if (req->ssl)
+ thread_add_read(thread->master, ssl_read_thread, sock,
+ thread->u.fd, HTTP_CNX_TIMEOUT);
+ else
+ thread_add_read(thread->master, http_read_thread, sock,
+ thread->u.fd, HTTP_CNX_TIMEOUT);
+ return 0;
+}
+
+/* remote Web server is connected, send it the get url query. */
+int
+http_request_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ char *str_request;
+ int ret = 0;
+
+ /* Handle read timeout */
+ if (thread->type == THREAD_WRITE_TIMEOUT)
+ return epilog(thread);
+
+ /* Allocate & clean the GET string */
+ str_request = (char *) MALLOC(GET_REQUEST_BUFFER_LENGTH);
+ memset(str_request, 0, GET_REQUEST_BUFFER_LENGTH);
+
+ snprintf(str_request, GET_REQUEST_BUFFER_LENGTH, REQUEST_TEMPLATE,
+ req->url,
+ (req->vhost) ? req->vhost : inet_ntop2(req->addr_ip)
+ , ntohs(req->addr_port));
+
+ /* Send the GET request to remote Web server */
+ DBG("Sending GET request [%s] on fd:%d\n",
+ req->url, sock->fd);
+ if (req->ssl)
+ ret =
+ ssl_send_request(sock->ssl, str_request,
+ strlen(str_request));
+ else
+ ret =
+ (send(sock->fd, str_request, strlen(str_request), 0) !=
+ -1) ? 1 : 0;
+
+ FREE(str_request);
+
+ if (!ret) {
+ fprintf(stderr, "Cannot send get request to [%s:%d].\n",
+ inet_ntop2(req->addr_ip)
+ , ntohs(req->addr_port));
+ return epilog(thread);
+ }
+
+ /* Register read timeouted thread */
+ thread_add_read(thread->master, http_response_thread, sock,
+ sock->fd, HTTP_CNX_TIMEOUT);
+ return 1;
+}
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: http.c include file.
+ *
+ * Version: $Id: http.h,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _HTTP_H
+#define _HTTP_H
+
+/* system includes */
+#include <stdio.h>
+#include <openssl/ssl.h>
+
+/* local includes */
+#include "scheduler.h"
+#include "sock.h"
+
+/* global defs */
+#define GET_REQUEST_BUFFER_LENGTH 1024
+#define GET_BUFFER_LENGTH 2048
+#define MAX_BUFFER_LENGTH 4096
+#define HTTP_CNX_TIMEOUT 5
+#define PROTO_HTTP 0x01
+#define PROTO_SSL 0x02
+
+/* GET processing command */
+#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
+ "User-Agent: GenHash (Linux powered)\r\n" \
+ "Host: %s:%d\r\n\r\n"
+
+/* Output delimiters */
+#define DELIM_BEGIN "-----------------------["
+#define DELIM_END "]-----------------------\n"
+#define HTTP_HEADER_HEXA DELIM_BEGIN" HTTP Header Buffer "DELIM_END
+#define HTTP_HEADER_ASCII DELIM_BEGIN" HTTP Header Ascii Buffer "DELIM_END
+#define HTML_HEADER_HEXA DELIM_BEGIN" HTML Buffer "DELIM_END
+#define HTML_MD5 DELIM_BEGIN" HTML MD5 resulting "DELIM_END
+#define HTML_MD5_FINAL DELIM_BEGIN" HTML MD5 final resulting "DELIM_END
+
+/* Define prototypes */
+extern int epilog(thread *thread);
+extern int finalize(thread *thread);
+extern int http_process_stream(SOCK *sock, int r);
+extern int http_request_thread(thread * thread);
+
+#endif
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: Layer4 asynchronous primitives.
+ *
+ * Version: $Id: layer4.c,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 "layer4.h"
+#include "utils.h"
+#include "main.h"
+#include "sock.h"
+#include "http.h"
+#include "ssl.h"
+
+enum connect_result
+tcp_connect(int fd, uint32_t addr_ip, uint16_t addr_port)
+{
+ struct linger li = { 0 };
+ int long_inet;
+ struct sockaddr_in adr_serv;
+ int ret;
+ int val;
+
+ /* free the tcp port after closing the socket descriptor */
+ li.l_onoff = 1;
+ li.l_linger = 0;
+ setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &li,
+ sizeof (struct linger));
+
+ long_inet = sizeof (struct sockaddr_in);
+ memset(&adr_serv, 0, long_inet);
+ adr_serv.sin_family = AF_INET;
+ adr_serv.sin_port = addr_port;
+ adr_serv.sin_addr.s_addr = addr_ip;
+
+ /* Make socket non-block. */
+ val = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, val | O_NONBLOCK);
+
+ /* Call connect function. */
+ ret = connect(fd, (struct sockaddr *) &adr_serv, long_inet);
+
+ /* Immediate success */
+ if (ret == 0) {
+ fcntl(fd, F_SETFL, val);
+ return connect_success;
+ }
+
+ /* If connect is in progress then return 1 else it's real error. */
+ if (ret < 0) {
+ if (errno != EINPROGRESS)
+ return connect_error;
+ }
+
+ /* restore previous fd args */
+ fcntl(fd, F_SETFL, val);
+ return connect_in_progress;
+}
+
+enum connect_result
+tcp_socket_state(int fd, thread * thread, uint32_t addr_ip, uint16_t addr_port,
+ int (*func) (struct _thread *))
+{
+ int status;
+ int slen;
+ int ret = 0;
+ TIMEVAL timer_min;
+
+ /* Handle connection timeout */
+ if (thread->type == THREAD_WRITE_TIMEOUT) {
+ DBG("TCP connection timeout to [%s:%d].\n",
+ inet_ntop2(addr_ip), ntohs(addr_port));
+ close(thread->u.fd);
+ return connect_timeout;
+ }
+
+ /* Check file descriptor */
+ slen = sizeof (status);
+ if (getsockopt
+ (thread->u.fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen) < 0)
+ ret = errno;
+
+ /* Connection failed !!! */
+ if (ret) {
+ DBG("TCP connection failed to [%s:%d].\n",
+ inet_ntop2(addr_ip), ntohs(addr_port));
+ close(thread->u.fd);
+ return connect_error;
+ }
+
+ /* If status = 0, TCP connection to remote host is established.
+ * Otherwise register checker thread to handle connection in progress,
+ * and other error code until connection is established.
+ * Recompute the write timeout (or pending connection).
+ */
+ if (status != 0) {
+ DBG("TCP connection to [%s:%d] still IN_PROGRESS.\n",
+ inet_ntop2(addr_ip), ntohs(addr_port));
+
+ timer_min = timer_sub_now(thread->sands);
+
+ if (TIMER_SEC(timer_min) <= 0)
+ thread_add_write(thread->master, func,
+ THREAD_ARG(thread)
+ , thread->u.fd, 0);
+ else
+ thread_add_write(thread->master, func,
+ THREAD_ARG(thread)
+ , thread->u.fd, TIMER_SEC(timer_min));
+ return connect_in_progress;
+ }
+
+ return connect_success;
+}
+
+void
+tcp_connection_state(int fd, enum connect_result status, thread * thread,
+ int (*func) (struct _thread *)
+ , int timeout)
+{
+ switch (status) {
+ case connect_error:
+ close(fd);
+ break;
+
+ case connect_success:
+ thread_add_write(thread->master, func, THREAD_ARG(thread),
+ fd, timeout);
+ break;
+
+ /* Checking non-blocking connect, we wait until socket is writable */
+ case connect_in_progress:
+ thread_add_write(thread->master, func, THREAD_ARG(thread),
+ fd, timeout);
+ break;
+
+ default:
+ break;
+ }
+}
+
+int
+tcp_check_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ int ret = 1;
+
+ sock->status = tcp_socket_state(thread->u.fd, thread, req->addr_ip
+ , req->addr_port, tcp_check_thread);
+ switch (sock->status) {
+ case connect_error:
+ DBG("Error connecting server [%s:%d].\n",
+ inet_ntop2(req->addr_ip), ntohs(req->addr_port));
+ thread_add_terminate_event(thread->master);
+ return -1;
+ break;
+
+ case connect_timeout:
+ DBG("Timeout connecting server [%s:%d].\n",
+ inet_ntop2(req->addr_ip), ntohs(req->addr_port));
+ thread_add_terminate_event(thread->master);
+ return -1;
+ break;
+
+ case connect_success:{
+ if (req->ssl)
+ ret = ssl_connect(thread);
+
+ if (ret) {
+ /* Remote WEB server is connected.
+ * Unlock eventual locked socket.
+ */
+ sock->lock = 0;
+ thread_add_event(thread->master,
+ http_request_thread,
+ sock, 0);
+ } else {
+ DBG("Connection trouble to: [%s:%d].\n",
+ inet_ntop2(req->addr_ip),
+ ntohs(req->addr_port));
+ if (req->ssl)
+ ssl_printerr(SSL_get_error
+ (sock->ssl, ret));
+ sock->status = connect_error;
+ return -1;
+ }
+ }
+ break;
+ }
+
+ return 1;
+}
+
+int
+tcp_connect_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+
+ if ((sock->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ DBG("WEB connection fail to create socket.\n");
+ return 0;
+ }
+
+ sock->status = tcp_connect(sock->fd, req->addr_ip, req->addr_port);
+
+ /* handle tcp connection status & register check worker thread */
+ tcp_connection_state(sock->fd, sock->status, thread, tcp_check_thread,
+ HTTP_CNX_TIMEOUT);
+ return 0;
+}
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: layer4.c include file.
+ *
+ * Version: $Id: layer4.h,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _LAYER4_H
+#define _LAYER4_H
+
+/* system includes */
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* local includes */
+#include "scheduler.h"
+
+enum connect_result {
+ connect_error,
+ connect_in_progress,
+ connect_timeout,
+ connect_success
+};
+
+/* Prototypes defs */
+extern enum connect_result
+tcp_connect(int fd, uint32_t, uint16_t);
+
+extern enum connect_result
+tcp_socket_state(int, thread *, uint32_t, uint16_t,
+ int (*func) (struct _thread *));
+
+extern void
+tcp_connection_state(int, enum connect_result
+ , thread *, int (*func) (struct _thread *)
+ , int);
+
+extern int
+tcp_connect_thread(thread *);
+
+#endif
-/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
- *
- * Part: Main part performing get request and MD5SUM over content.
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: Main entry point.
*
- * Version: $Id: main.c,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ * Version: $Id: main.c,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 2 of the License, or (at your option) any later version.
*/
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include "main.h"
-#include "common.h"
-#include "client.h"
-
-/* Dump a buffer (ASCII or Binary) */
-static void
-print_buffer(int count, char *buff)
-{
- int i, j, c;
- int printnext = 1;
-
- if (count % 16)
- c = count + (16 - count % 16);
- else
- c = count;
+#include "utils.h"
+#include "sock.h"
- 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;
- }
- }
- }
-}
-
-/* Allocate & clean a buffer */
-static char *
-xmalloc(const int size)
-{
- char *buffer;
-
- buffer = (char *) malloc(size);
- if (!buffer)
- return NULL;
- memset(buffer, 0, size);
-
- return buffer;
-}
+/* global var */
+thread_master *master = NULL;
+SOCK *sock = NULL;
-/* Return the html header from a global HTTP buffer */
-static char *
-extract_html(char *buffer, int size_buffer)
+/* Terminate handler */
+void
+sigend(int sig)
{
- char *end = buffer + size_buffer;
-
- while (buffer < end && !(*buffer++ == '\n' &&
- (*buffer == '\n'
- || (*buffer++ == '\r' && *buffer == '\n')))) ;
-
- if (*buffer == '\n')
- return buffer + 1;
- return NULL;
+ /* register the terminate thread */
+ thread_add_terminate_event(master);
}
-/* Build the GET request */
-static char *
-build_request(REQ * req)
+/* signal wrapper */
+void *
+signal_set(int signo, void (*func) (int))
{
- char *request;
- char *vhost;
- int request_len = 0;
-
- request_len = strlen(REQUEST_TEMPLATE) + strlen(req->host) + strlen(req->url) + 5 + /* characters for port */
- 1; /* null terminator */
- request = xmalloc(request_len);
- if (!request)
- return NULL;
-
- vhost = req->host;
- if (req->virtualhost)
- vhost = req->virtualhost;
- snprintf(request, request_len, REQUEST_TEMPLATE, req->url, vhost,
- req->port);
- return request;
+ int ret;
+ struct sigaction sig;
+ struct sigaction osig;
+
+ sig.sa_handler = func;
+ sigemptyset(&sig.sa_mask);
+ sig.sa_flags = 0;
+#ifdef SA_RESTART
+ sig.sa_flags |= SA_RESTART;
+#endif /* SA_RESTART */
+
+ ret = sigaction(signo, &sig, &osig);
+
+ if (ret < 0)
+ return (SIG_ERR);
+ else
+ return (osig.sa_handler);
}
-static int
-https_request(SSL * ssl, REQ * req)
-{
- char *request = NULL;
- int r, i, e = 0;
- int request_len;
- char *extracted;
- unsigned char digest[16];
- MD5_CTX context;
-
- /* Build the SSL request */
- request = build_request(req);
- if (!request)
- return OUT_OF_MEMORY;
- request_len = strlen(request);
-
- /* Send the SSL request */
- r = SSL_write(ssl, request, request_len);
- if (SSL_ERROR_NONE != SSL_get_error(ssl, r)) {
- free(request);
- return SSL_WRITE_ERROR;
- }
-
- /* Test for eventual imcomplete SSL write */
- if (request_len != r) {
- free(request);
- return SSL_INCOMPLETE_WRITE;
- }
-
- /* Init MD5 context */
- MD5_Init(&context);
- extracted = NULL;
- req->len = 0;
- e = 0;
-
- /*
- * Now read the server's response, assuming
- * that it's terminated by a close.
- *
- * FIXME: Create a function to read data from remote
- * server instead of code duplication.
- */
- printf(HTTP_HEADER_HEXA);
-
- while (!e) {
- r = SSL_read(ssl, req->buffer + req->len, req->max - req->len);
- e = SSL_get_error(ssl, r);
- if (e != SSL_ERROR_NONE)
- break;
- if (r > 0 && e == 0) {
- req->len += r;
- /* Only header yet ? */
- if (!extracted) {
- /* Found something more than header ? */
- if ((extracted =
- extract_html(req->buffer, req->len))) {
- r = req->len - (extracted -
- req->buffer);
- if (r) {
- print_buffer(r, req->buffer);
- printf(HTTP_HEADER_ASCII);
- for (i = 0;
- i <
- extracted - req->buffer;
- i++)
- printf("%c",
- req->buffer[i]);
- printf("\n");
- printf(HTML_HEADER_HEXA);
- memcpy(req->buffer, extracted,
- r);
- MD5_Update(&context,
- req->buffer, r);
- r = 0;
- }
- req->len = r;
- } else {
- if (req->len > 3) {
- print_buffer(req->len - 3,
- req->buffer);
- printf(HTTP_HEADER_ASCII);
- for (i = 0; i < req->len - 3;
- i++)
- printf("%c",
- req->buffer[i]);
- printf("\n");
- printf(HTML_HEADER_HEXA);
- memcpy(req->buffer,
- req->buffer + req->len -
- 3, 3);
- req->len = 3;
- }
- }
- } else {
- if (req->len) {
- print_buffer(req->len, req->buffer);
- MD5_Update(&context, req->buffer,
- req->len);
- req->len = 0;
- }
- }
- }
- }
-
- /* Error handling */
- if (e != SSL_ERROR_ZERO_RETURN && e != SSL_ERROR_SYSCALL) {
- free(request);
- return SSL_READ_ERROR;
- }
-
- if (e == SSL_ERROR_ZERO_RETURN)
- if (SSL_shutdown(ssl) != 1) {
- free(request);
- return SSL_SHUTDOWN_FAILED;
- }
-
- if (e != SSL_ERROR_SYSCALL)
- SSL_free(ssl);
-
- MD5_Final(digest, &context);
- printf(HTML_MD5);
- print_buffer(16, digest);
-
- printf(HTML_MD5_FINAL);
- for (r = 0; r < 16; r++)
- printf("%02x", digest[r]);
- printf("\n\n");
-
- free(request);
- return SSL_GET_SUCCESS;
-}
-
-/*
- * Connect a remote SSL server and generate a MD5SUM
- * Upon the remote HTML content returned.
- */
-static int
-genhash_ssl(REQ * req)
-{
- SSL_CTX *ctx;
- SSL *ssl;
- BIO *sbio;
- int retcode = 0;
-
- /* SSL context initialization */
- ctx = initialize_ctx(req->keyfile, req->password, req->cafile);
-
- /* TCP socket creation */
- req->fd = tcp_sock();
- if (req->fd == -1) {
- destroy_ctx(ctx);
- return TCP_BIND_ERROR;
- }
-
- /* TCP connect remote host */
- retcode = tcp_connect(req->fd, req->host, req->port);
- if (retcode != TCP_CONNECT_SUCCESS)
- goto end;
-
- /* Create the SSL context */
- ssl = SSL_new(ctx);
- sbio = BIO_new_socket(req->fd, BIO_NOCLOSE);
- SSL_set_bio(ssl, sbio, sbio);
-
- /* Connect remote SSL server */
- if (SSL_connect(ssl) <= 0)
- return -2;
-
- /* Proceed the SSL server reply */
- retcode = https_request(ssl, req);
-
- end:
- /* Shutdown the socket */
- destroy_ctx(ctx);
- close(req->fd);
- return (retcode);
-}
-
-/*
- * Connect a remote HTTP server and generate a MD5SUM
- * Upon the remote HTML content returned.
- */
-static int
-genhash_http(REQ * req)
+/* Initialize signal handler */
+void
+signal_init(void)
{
- int request_len = 0;
- char *request = NULL;
- char *buffertmp = NULL;
- int retcode = 0;
- int r;
- char *extracted;
- unsigned char digest[16];
- MD5_CTX context;
-
- /* Temporary get buffer allocation */
- buffertmp = xmalloc(RCV_BUFFER_LENGTH);
- if (!buffertmp) {
- free(request);
- return OUT_OF_MEMORY;
- }
-
- /* Build the HTTP request */
- request = build_request(req);
- if (!request) {
- free(buffertmp);
- return OUT_OF_MEMORY;
- }
- request_len = strlen(request);
-
- /* TCP socket creation */
- req->fd = tcp_sock();
- if (req->fd == -1) {
- free(request);
- free(buffertmp);
- return TCP_BIND_ERROR;
- }
-
- /* TCP connect remote host */
- retcode = tcp_connect(req->fd, req->host, req->port);
- if (retcode != TCP_CONNECT_SUCCESS)
- goto error;
-
- /* Send the HTTP request */
- retcode = tcp_send(req->fd, request, request_len);
- if (retcode == TCP_SEND_ERROR)
- goto error;
-
- /* Proceed the HTTP server reply */
- retcode = tcp_read_to(req->fd);
- if (retcode == TCP_READ_TIMEOUT)
- goto error;
-
- MD5_Init(&context);
- extracted = NULL;
- req->len = 0;
-
- /*
- * Now read the server's response.
- *
- * FIXME: Create a function to read data from remote
- * server instead of code duplication.
- */
- printf(HTTP_HEADER_HEXA);
- while (1) {
- r = read(req->fd, buffertmp, RCV_BUFFER_LENGTH);
- if (r == -1 || r == 0)
- break;
- memcpy(req->buffer + req->len, buffertmp, r);
- req->len += r;
- if (!extracted &&
- (extracted = extract_html(req->buffer, req->len))) {
- print_buffer(extracted - req->buffer, req->buffer);
- printf(HTTP_HEADER_ASCII);
- for (r = 0; r < extracted - req->buffer; r++)
- printf("%c", req->buffer[r]);
- printf("\n");
-
- printf(HTML_HEADER_HEXA);
- r = req->len - (extracted - req->buffer);
- if (r)
- memcpy(req->buffer, extracted, r);
- req->len = r;
- }
-
- if (extracted && req->len) {
- print_buffer(req->len, req->buffer);
- MD5_Update(&context, req->buffer, req->len);
- req->len = 0;
- }
- }
-
- MD5_Final(digest, &context);
- printf(HTML_MD5);
- print_buffer(16, digest);
-
- printf(HTML_MD5_FINAL);
- for (r = 0; r < 16; r++)
- printf("%02x", digest[r]);
- printf("\n\n");
-
- /* All is fine just return a success code */
- retcode = HTTP_GET_SUCCESS;
-
- error:
- close(req->fd);
- free(request);
- free(buffertmp);
- return (retcode);
+ signal_set(SIGHUP, sigend);
+ signal_set(SIGINT, sigend);
+ signal_set(SIGTERM, sigend);
+ signal_set(SIGKILL, sigend);
}
-/* Error return function */
-static void
-print_error(int err)
-{
- switch (err) {
- /* System errors */
- case OUT_OF_MEMORY:
- err_exit("Out Of Memery");
- break;
-
- /* TCP errors */
- case TCP_BIND_ERROR:
- err_exit("TCP Bind error");
- break;
- case TCP_RESOLV_ERROR:
- err_exit("TCP Resolv error");
- break;
- case TCP_CONNECT_ERROR:
- err_exit("TCP Connect error");
- break;
- case TCP_WRITE_TIMEOUT:
- err_exit("TCP Write TimeOut");
- break;
- case TCP_READ_TIMEOUT:
- err_exit("TCP Read error");
- break;
- case TCP_SELECT_ERROR:
- err_exit("TCP Select error");
- break;
- case TCP_CONNECT_FAILED:
- err_exit("TCP Connectin failed");
- break;
- case TCP_SEND_ERROR:
- err_exit("TCP Send error");
- break;
-
- /* SSL errors */
- case SSL_WRITE_ERROR:
- err_exit("SSL Write error");
- break;
- case SSL_INCOMPLETE_WRITE:
- err_exit("SSL Incomplete write");
- break;
- case SSL_READ_ERROR:
- err_exit("SSL Read error");
- break;
- case SSL_SHUTDOWN_FAILED:
- err_exit("SSL Shutdown failed");
- break;
- }
-}
/* Usage function */
static void
usage(const char *prog)
{
- fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+ fprintf(stderr, VERSION_STRING);
fprintf(stderr,
"Usage:\n"
" %s -s server-address -p port -u url\n"
- " %s -S -K priv-key-file -P pem-password -s server-address -p port -u url\n"
- " %s -S -K priv-key-file -P pem-password -C cert-file -s server-address -p port -u url\n"
- " %s -h\n" " %s -v\n\n", prog, prog, prog, prog, prog);
+ " %s -S -s server-address -p port -u url\n"
+ " %s -h\n" " %s -r\n\n", prog, prog, prog, prog);
fprintf(stderr,
"Commands:\n"
"Either long or short options are allowed.\n"
" %s --server -s Use the specified remote server address.\n"
" %s --port -p Use the specified remote server port.\n"
" %s --url -u Use the specified remote server url.\n"
- " %s --use-private-key -K Use the specified SSL private key.\n"
- " %s --use-password -P Use the specified SSL private key password.\n"
- " %s --use-virtualhost -V Use the specified VirtualHost GET query.\n"
- " %s --use-certificate -C Use the specified SSL Certificate file.\n"
+ " %s --use-virtualhost -V Use the specified virtualhost in GET query.\n"
+ " %s --verbose -v Use verbose mode output.\n"
" %s --help -h Display this short inlined help screen.\n"
- " %s --version -v Display the version number\n",
- prog, prog, prog, prog, prog, prog, prog, prog, prog, prog);
+ " %s --release -r Display the release number\n",
+ prog, prog, prog, prog, prog, prog, prog, prog);
}
/* Command line parser */
int c;
struct poptOption options_table[] = {
- {"version", 'v', POPT_ARG_NONE, NULL, 'v'},
+ {"release", 'r', POPT_ARG_NONE, NULL, 'r'},
{"help", 'h', POPT_ARG_NONE, NULL, 'h'},
+ {"verbose", 'v', POPT_ARG_NONE, NULL, 'v'},
{"use-ssl", 'S', POPT_ARG_NONE, NULL, 'S'},
{"server", 's', POPT_ARG_STRING, &optarg, 's'},
{"port", 'p', POPT_ARG_STRING, &optarg, 'p'},
{"url", 'u', POPT_ARG_STRING, &optarg, 'u'},
- {"use-private-key", 'K', POPT_ARG_STRING, &optarg, 'K'},
{"use-virtualhost", 'V', POPT_ARG_STRING, &optarg, 'V'},
- {"use-password", 'P', POPT_ARG_STRING, &optarg, 'P'},
- {"use-certificate", 'C', POPT_ARG_STRING, &optarg, 'C'},
{NULL, 0, 0, NULL, 0}
};
+ /* Parse the command line arguments */
context =
poptGetContext(PROG, argc, (const char **) argv, options_table, 0);
if ((c = poptGetNextOpt(context)) < 0) {
/* The first option car */
switch (c) {
- case 'v':
- fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+ case 'r':
+ fprintf(stderr, VERSION_STRING);
break;
case 'h':
usage(argv[0]);
break;
+ case 'v':
+ req->verbose = 1;
+ break;
case 'S':
req->ssl = 1;
break;
case 's':
- req->host = optarg;
+ inet_ston(optarg, &req->addr_ip);
+ break;
+ case 'V':
+ req->vhost = optarg;
break;
default:
usage(argv[0]);
/* the others */
while ((c = poptGetNextOpt(context)) >= 0) {
switch (c) {
+ case 'v':
+ req->verbose = 1;
+ break;
+ case 'S':
+ req->ssl = 1;
+ break;
case 's':
- req->host = optarg;
+ inet_ston(optarg, &req->addr_ip);
+ break;
+ case 'V':
+ req->vhost = optarg;
break;
case 'p':
- req->port = atoi(optarg);
+ req->addr_port = htons(atoi(optarg));
break;
case 'u':
req->url = optarg;
break;
- case 'K':
- req->keyfile = optarg;
- break;
- case 'P':
- req->password = optarg;
- break;
- case 'V':
- req->virtualhost = optarg;
- break;
- case 'C':
- req->cafile = optarg;
- break;
default:
usage(argv[0]);
return CMD_LINE_ERROR;
int
main(int argc, char **argv)
{
- REQ *req;
- char *buffer;
- int err = 0;
+ thread thread;
/* Allocate the room */
- req = (REQ *) xmalloc(sizeof (REQ));
- buffer = (char *) xmalloc(RCV_BUFFER_LENGTH);
+ req = (REQ *) MALLOC(sizeof (REQ));
/* Command line parser */
- if (!parse_cmdline(argc, argv, req))
+ if (!parse_cmdline(argc, argv, req)) {
+ FREE(req);
exit(0);
+ }
/* Check minimum configuration need */
- if (!req->host && !req->port && !req->url) {
+ if (!req->addr_ip && !req->addr_port && !req->url) {
+ FREE(req);
exit(0);
}
- /* finalize req initialisation */
- req->buffer = buffer;
- req->max = RCV_BUFFER_LENGTH;
+ /* Init the reference timer */
+ req->ref_time = timer_tol(timer_now());
+ DBG("Reference timer = %lu\n", req->ref_time);
- /* Now make our HTTP/SSL request */
- err = req->ssl ? genhash_ssl(req) : genhash_http(req);
- print_error(err);
+ /* Init SSL context */
+ init_ssl();
- free(req);
- return (1);
+ /* Signal handling initialization */
+ signal_init();
+
+ /* Create the master thread */
+ master = thread_make_master();
+
+ /* Register the GET request */
+ init_sock();
+
+ /*
+ * Processing the master thread queues,
+ * return and execute one ready thread.
+ * Run until error, used for debuging only.
+ */
+ while (thread_fetch(master, &thread))
+ thread_call(&thread);
+
+ /* Finalize output informations */
+ if (req->verbose)
+ printf("Global response time for [%s] =%lu\n",
+ req->url, req->response_time-req->ref_time);
+
+ /* exit cleanly */
+ SSL_CTX_free(req->ctx);
+ free_sock(sock);
+ FREE(req);
+ exit(0);
}
/*
- * Soft: Genhash compute MD5 digest from a HTTP get result. This
- * program is use to compute hash value that you will add
- * into the /etc/keepalived/keepalived.conf for HTTP_GET
- * & SSL_GET keepalive method.
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
*
* Part: main.c include file.
*
- * Version: $Id: main.h,v 0.4.9 2001/11/28 11:50:23 acassen Exp $
+ * Version: $Id: main.h,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
- * Jan Holmberg, <jan@artech.se>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#ifndef _MAIN_H
#define _MAIN_H
+/* global includes */
#include <stdlib.h>
#include <stdio.h>
+#include <stdint.h>
#include <string.h>
#include <errno.h>
-#include <openssl/md5.h>
#include <popt.h>
+#include <openssl/ssl.h>
+
+/* local includes */
+#include "memory.h"
+#include "timer.h"
+#include "http.h"
+#include "ssl.h"
+#include "list.h"
/* Build version */
#define PROG "genhash"
-#define VERSION "0.6.2 (06/14, 2002)"
-/* HTTP/HTTPS GET command */
-#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
- "User-Agent:KeepAliveClient\r\n" \
- "Host: %s:%d\r\n\r\n"
+#define VERSION_CODE 0x010000
+#define DATE_CODE 0x120b02
+
+#define GETMETER_VERSION(version) \
+ (version >> 16) & 0xFF, \
+ (version >> 8) & 0xFF, \
+ version & 0xFF
+
+#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)\n", \
+ GETMETER_VERSION(VERSION_CODE), \
+ GETMETER_VERSION(DATE_CODE)
/* HTTP/HTTPS request structure */
typedef struct {
- char *host;
- char *buffer;
- int error;
- int max;
- int len;
+ uint32_t addr_ip;
+ uint16_t addr_port;
char *url;
- unsigned short int port;
- int fd;
+ char *vhost;
+ int verbose;
int ssl;
- char *keyfile;
- char *password;
- char *virtualhost;
- char *cafile;
+ SSL_CTX *ctx;
+ SSL_METHOD *meth;
+ unsigned long ref_time;
+ unsigned long response_time;
} REQ;
-/* Output delimiters */
-#define DELIM_BEGIN "-----------------------["
-#define DELIM_END "]-----------------------\n"
-#define HTTP_HEADER_HEXA DELIM_BEGIN" HTTP Header Buffer "DELIM_END
-#define HTTP_HEADER_ASCII DELIM_BEGIN" HTTP Header Ascii Buffer "DELIM_END
-#define HTML_HEADER_HEXA DELIM_BEGIN" HTML Buffer "DELIM_END
-#define HTML_MD5 DELIM_BEGIN" HTML MD5 resulting "DELIM_END
-#define HTML_MD5_FINAL DELIM_BEGIN" HTML MD5 final resulting "DELIM_END
+/* Global variables */
+REQ *req; /* Cmd line arguments */
/* Data buffer length description */
-#define RCV_BUFFER_LENGTH 512
#define BUFSIZE 1024
/* Command line error handling */
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: Socket pool utility functions.
+ *
+ * Version: $Id: sock.c,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 <string.h>
+#include "memory.h"
+#include "utils.h"
+#include "list.h"
+#include "sock.h"
+#include "layer4.h"
+#include "ssl.h"
+#include "main.h"
+
+/* extern var */
+extern thread_master *master;
+extern SOCK *sock;
+
+/* Close the descriptor */
+static void close_sock(SOCK *sock)
+{
+ if (sock->ssl) {
+ SSL_shutdown(sock->ssl);
+ SSL_free(sock->ssl);
+ }
+ close(sock->fd);
+}
+
+/* Destroy the socket handler */
+void free_sock(SOCK *sock)
+{
+ DBG("Freeing fd:%d\n", sock->fd);
+
+ close_sock(sock);
+ FREE(sock);
+}
+
+/* Init socket handler */
+void init_sock(void)
+{
+ sock = (SOCK *)MALLOC(sizeof(SOCK));
+ memset(sock, 0, sizeof(SOCK));
+ thread_add_event(master, tcp_connect_thread,
+ sock, 0);
+}
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: sock.c include file.
+ *
+ * Version: $Id: sock.h,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _SOCK_H
+#define _SOCK_H
+
+/* system includes */
+#include <openssl/ssl.h>
+#include <openssl/md5.h>
+
+/* Engine socket pool element structure */
+typedef struct {
+ int fd;
+ SSL *ssl;
+ BIO *bio;
+ MD5_CTX context;
+ int status;
+ int lock;
+ char *buffer;
+ char *extracted;
+ int size;
+ int total_size;
+} SOCK;
+
+/* Prototypes */
+extern void free_sock(SOCK *sock);
+extern void init_sock(void);
+
+#endif
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: SSL engine. 'Semi' asyncrhonous stream handling.
+ *
+ * Version: $Id: ssl.c,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 <openssl/err.h>
+#include "main.h"
+#include "sock.h"
+#include "http.h"
+#include "ssl.h"
+#include "utils.h"
+#include "html.h"
+
+/* extern variables */
+extern REQ *req;
+
+/*
+ * Initialize the SSL context, with or without specific
+ * configuration files.
+ */
+static BIO *bio_err = 0;
+void
+init_ssl(void)
+{
+ /* Library initialization */
+ SSL_library_init();
+
+ SSL_load_error_strings();
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ /* Initialize SSL context for SSL v2/3 */
+ req->meth = SSLv23_method();
+ req->ctx = SSL_CTX_new(req->meth);
+
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+ SSL_CTX_set_verify_depth(req->ctx, 1);
+#endif
+}
+
+/* Display SSL error to readable string */
+int
+ssl_printerr(int err)
+{
+ unsigned long extended_error = 0;
+ char *ssl_strerr;
+
+ switch (err) {
+ case SSL_ERROR_ZERO_RETURN:
+ fprintf(stderr, " SSL error: (zero return)\n");
+ break;
+ case SSL_ERROR_WANT_READ:
+ fprintf(stderr, " SSL error: (read error)\n");
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ fprintf(stderr, " SSL error: (write error)\n");
+ break;
+ case SSL_ERROR_WANT_CONNECT:
+ fprintf(stderr, " SSL error: (connect error)\n");
+ break;
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ fprintf(stderr, " SSL error: (X509 lookup error)\n");
+ break;
+ case SSL_ERROR_SYSCALL:
+ fprintf(stderr, " SSL error: (syscall error)\n");
+ break;
+ case SSL_ERROR_SSL:{
+ ssl_strerr = (char *) MALLOC(500);
+
+ extended_error = ERR_get_error();
+ ERR_error_string(extended_error, ssl_strerr);
+ fprintf(stderr, " SSL error: (%s)\n", ssl_strerr);
+ FREE(ssl_strerr);
+ break;
+ }
+ }
+ return 0;
+}
+
+int
+ssl_connect(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ int ret;
+
+ sock->ssl = SSL_new(req->ctx);
+ sock->bio = BIO_new_socket(sock->fd, BIO_NOCLOSE);
+ BIO_set_nbio(sock->bio, 1); /* Set the Non-Blocking flag */
+ SSL_set_bio(sock->ssl, sock->bio, sock->bio);
+ ret = SSL_connect(sock->ssl);
+
+ DBG(" SSL_connect return code = %d on fd:%d\n",
+ ret, thread->u.fd);
+ ssl_printerr(SSL_get_error(sock->ssl, ret));
+
+ return (ret > 0) ? 1 : 0;
+}
+
+int
+ssl_send_request(SSL * ssl, char *str_request, int request_len)
+{
+ int err, r = 0;
+
+ while (1) {
+ err = 1;
+ r = SSL_write(ssl, str_request, request_len);
+ if (SSL_ERROR_NONE != SSL_get_error(ssl, r))
+ break;
+ err++;
+ if (request_len != r)
+ break;
+ err++;
+ break;
+ }
+
+ return (err == 3) ? 1 : 0;
+}
+
+/* Asynchronous SSL stream reader */
+int
+ssl_read_thread(thread * thread)
+{
+ SOCK *sock = THREAD_ARG(thread);
+ int r = 0;
+ int error;
+
+ /* Handle read timeout */
+ if (thread->type == THREAD_READ_TIMEOUT)
+ return epilog(thread);
+
+ /*
+ * The design implemented here is a workaround for use
+ * with OpenSSL. This goto loop is a 'read until not
+ * end of stream'. But this break a little our global
+ * I/O multiplexer thread framework because it enter
+ * a synchronous read process for each GET reply.
+ * Sound a little nasty !.
+ *
+ * Why OpenSSL doesn t handle underlying fd. This
+ * break the I/O (select()) approach !...
+ * If you read this and know the answer, please reply
+ * I am probably missing something... :)
+ * My test show that sometime it return from select,
+ * and sometime not...
+ */
+
+read_stream:
+
+ /* read the SSL stream */
+ memset(sock->buffer, 0, MAX_BUFFER_LENGTH);
+ r = SSL_read(sock->ssl, sock->buffer, MAX_BUFFER_LENGTH);
+ error = SSL_get_error(sock->ssl, r);
+
+ DBG(" [l:%d,fd:%d]\n", r, sock->fd);
+
+ if (error) {
+ /* All the SSL streal has been parsed */
+ /* Handle response stream */
+ if (error != SSL_ERROR_NONE)
+ return finalize(thread);
+ } else if (r > 0 && error == 0) {
+
+ /* Handle the response stream */
+ http_process_stream(sock, r);
+
+ /*
+ * Register next ssl stream reader.
+ * Register itself to not perturbe global I/O multiplexer.
+ */
+ goto read_stream;
+ }
+
+ return 0;
+}
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJBVTET
-MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMB4XDTAxMTEyODE1MzcwMFoXDTAxMTIyODE1MzcwMFowRTELMAkGA1UE
-BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
-ZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqaHao73f
-HpyErd5yhBcY9MS0oN0uHFtSXsz63VXjfEwhl/7bgaw+9qR1a/iY8lW7NL7yON+9
-6o1wToTV/8gDs19rlUY+tpFiIsJzHUO2Xknnyp87dUPOU+bNu+r525DVnTvf4uxV
-6H56CPqqGDYKpG1dyjDtdiTgayIcehQNsiECAwEAAaOBnzCBnDAdBgNVHQ4EFgQU
-E3xmxdjFNxXJLa/NlzpeQtqwNZcwbQYDVR0jBGYwZIAUE3xmxdjFNxXJLa/Nlzpe
-QtqwNZehSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
-HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB
-/zANBgkqhkiG9w0BAQQFAAOBgQCMAF/IJrmL7wSdY/YWjbj8+PKzIMzJmz6w6c8V
-LhbLHYreMurG5830Ljnd1udm7o7g+16qLNfq0rEwrWhnxDnC1Id8nHXxhUHO6IEg
-YDPBWMte7zOC7skgDzvJc585HiMNxXEuX1pwnBvHv+qqu36TtVZSXeOKZcOOmkwE
-eY40Bg==
------END CERTIFICATE-----
+++ /dev/null
------BEGIN CERTIFICATE REQUEST-----
-MIIBhDCB7gIBADBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEh
-MB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCpodqjvd8enISt3nKEFxj0xLSg3S4cW1JezPrdVeN8TCGX
-/tuBrD72pHVr+JjyVbs0vvI4373qjXBOhNX/yAOzX2uVRj62kWIiwnMdQ7ZeSefK
-nzt1Q85T5s276vnbkNWdO9/i7FXofnoI+qoYNgqkbV3KMO12JOBrIhx6FA2yIQID
-AQABoAAwDQYJKoZIhvcNAQEEBQADgYEAJr5QWBjpWL1qsrHaNAP+qP17IAUWuZsz
-Zdy72zGnQcsrk3mn6b1z9OS7WOPKcKkSq2q1+DlQS7vfhPaYRM1g/sqOMbnPv+MJ
-CCvHvBcI+nKBjUS7WofEuZSvVzo8bdwoVyYLdQWKFi6w3Z+O8D3YxRlvXseWWOkI
-lj4W75ypRVU=
------END CERTIFICATE REQUEST-----
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: ssl.c include file.
+ *
+ * Version: $Id: ssl.h,v 1.0.0 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _SSL_H
+#define _SSL_H
+
+#include <openssl/ssl.h>
+
+/* Prototypes */
+extern void init_ssl(void);
+extern int ssl_connect(thread * thread);
+extern int ssl_printerr(int err);
+extern int ssl_send_request(SSL * ssl, char *str_request, int request_len);
+extern int ssl_read_thread(thread * thread);
+
+#endif
+++ /dev/null
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,45FBDBEBCB52B1ED
-
-q6RONp0/s4kRRhz1n//irIU+QIed+F0Vu7ijixGARCJkkp+ZoXbGqOYwLJXjJXtH
-iC08SodwhFZLdLgCTttTn6IZvKR6Ye0K6or0JvSLQ+3+qdDy7GmgEnctPhE7j4Nk
-ptZejNPjjauh5tpu/rrIIq14ApE0zDuJpx97co4/i7VrGpB/HVVtJ61As3ry4aRL
-T8WvuQEIM5TLKC8tSxPb8rQKM5soY2IHd+GmMgYkiNg+Vcg6I7N34EQkse0CHNxA
-PUl2kPwP9kg981mR/xks22oNNM5AAkTuWXB8R3zDuyaVdYcpbSEiOeOBMPFo43CR
-yFsYRVOer9Dp97KSkYQ3VOwoYil2m6ddrpYBr9qDZ/PF9VBhdrJT37rA73+1V6AO
-YFkQvbWiL/SUsvByXFHes68Y09fCHkbCkbtY3tNvTK8Z37iI6ZuTPdBIYblTRYil
-51RDJkrCuUyLx3dzkPxQqq1nkBRx9QLz2DaY0xRc9PEgM01C/Q5T/7mwosSsE/zZ
-5oJB3upN8/1kmy+gTLLoE5kSyEZup8NsEHEqhU1z2z+t6DKOnFR8eg0YXdItIfHP
-y7QNKmFaSghtkNPQUrXz/s4Bh/9bEAicIOjj6Om2uVKG0vXEa+0b+Qz8sUcHvFB+
-IX2NJUCmFQgjFt6a3IYo6P0ajLy1g/ES+nPWwjYAMVXe0RHrB+Q0pwib9koWGvZN
-4N2xti19DEdKBNMgWRo7SBzTNtkv5Eo6btLw4M9oeqonC1YJfGThFUSssyC5ZCcY
-H+QeYs48mWoQwXwAufOr8CwALLmeAGhgBiIy6dcbvHpO7IQzTRRcIA==
------END RSA PRIVATE KEY-----
+++ /dev/null
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,45FBDBEBCB52B1ED
-
-q6RONp0/s4kRRhz1n//irIU+QIed+F0Vu7ijixGARCJkkp+ZoXbGqOYwLJXjJXtH
-iC08SodwhFZLdLgCTttTn6IZvKR6Ye0K6or0JvSLQ+3+qdDy7GmgEnctPhE7j4Nk
-ptZejNPjjauh5tpu/rrIIq14ApE0zDuJpx97co4/i7VrGpB/HVVtJ61As3ry4aRL
-T8WvuQEIM5TLKC8tSxPb8rQKM5soY2IHd+GmMgYkiNg+Vcg6I7N34EQkse0CHNxA
-PUl2kPwP9kg981mR/xks22oNNM5AAkTuWXB8R3zDuyaVdYcpbSEiOeOBMPFo43CR
-yFsYRVOer9Dp97KSkYQ3VOwoYil2m6ddrpYBr9qDZ/PF9VBhdrJT37rA73+1V6AO
-YFkQvbWiL/SUsvByXFHes68Y09fCHkbCkbtY3tNvTK8Z37iI6ZuTPdBIYblTRYil
-51RDJkrCuUyLx3dzkPxQqq1nkBRx9QLz2DaY0xRc9PEgM01C/Q5T/7mwosSsE/zZ
-5oJB3upN8/1kmy+gTLLoE5kSyEZup8NsEHEqhU1z2z+t6DKOnFR8eg0YXdItIfHP
-y7QNKmFaSghtkNPQUrXz/s4Bh/9bEAicIOjj6Om2uVKG0vXEa+0b+Qz8sUcHvFB+
-IX2NJUCmFQgjFt6a3IYo6P0ajLy1g/ES+nPWwjYAMVXe0RHrB+Q0pwib9koWGvZN
-4N2xti19DEdKBNMgWRo7SBzTNtkv5Eo6btLw4M9oeqonC1YJfGThFUSssyC5ZCcY
-H+QeYs48mWoQwXwAufOr8CwALLmeAGhgBiIy6dcbvHpO7IQzTRRcIA==
------END RSA PRIVATE KEY-----
------BEGIN CERTIFICATE-----
-MIICoDCCAgmgAwIBAgIBADANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJBVTET
-MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
-dHkgTHRkMB4XDTAxMTEyODE1MzcwMFoXDTAxMTIyODE1MzcwMFowRTELMAkGA1UE
-BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
-ZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqaHao73f
-HpyErd5yhBcY9MS0oN0uHFtSXsz63VXjfEwhl/7bgaw+9qR1a/iY8lW7NL7yON+9
-6o1wToTV/8gDs19rlUY+tpFiIsJzHUO2Xknnyp87dUPOU+bNu+r525DVnTvf4uxV
-6H56CPqqGDYKpG1dyjDtdiTgayIcehQNsiECAwEAAaOBnzCBnDAdBgNVHQ4EFgQU
-E3xmxdjFNxXJLa/NlzpeQtqwNZcwbQYDVR0jBGYwZIAUE3xmxdjFNxXJLa/Nlzpe
-QtqwNZehSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
-HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCAQAwDAYDVR0TBAUwAwEB
-/zANBgkqhkiG9w0BAQQFAAOBgQCMAF/IJrmL7wSdY/YWjbj8+PKzIMzJmz6w6c8V
-LhbLHYreMurG5830Ljnd1udm7o7g+16qLNfq0rEwrWhnxDnC1Id8nHXxhUHO6IEg
-YDPBWMte7zOC7skgDzvJc585HiMNxXEuX1pwnBvHv+qqu36TtVZSXeOKZcOOmkwE
-eY40Bg==
------END CERTIFICATE-----
Summary: Generic HA monitor build upon VRRP and services poller, strongly recommanded for LVS HA.
Name: keepalived
Packager: Christophe Varoqui, <christophe.varoqui@free.fr>
-Version: 0.7.1
+Version: 0.7.6
Release: 1
-Source: http://www.keepalived.org/software/keepalived-0.7.1.tar.gz
+Source: http://www.keepalived.org/software/keepalived-0.7.6.tar.gz
Copyright: GPL
Group: Utilities/File
BuildRoot: /tmp/%{name}-%{version}.build
%prep
rm -rf %{buildroot}
-%setup -n keepalived-0.7.1
+%setup -n keepalived-0.7.6
%build
./configure --prefix=%{buildroot} --exec-prefix=%{buildroot} --sysconfdir=%{buildroot}/etc
for i in $(SUBDIRS); do \
$(MAKE) -C $$i || exit 1; done && \
echo "Building $(BIN)/$(EXEC)" && \
- $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) `find $(SUBDIRS) -name '*.[oa]'`
+ $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) `find $(SUBDIRS) ../lib -name '*.[oa]'`
strip $(BIN)/$(EXEC)
@echo ""
@echo "Make complete"
# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
CC = @CC@
-INCLUDES = -I../include
+INCLUDES = -I../include -I../../lib
CFLAGS = @CFLAGS@ $(INCLUDES) \
-Wall -Wunused -Wstrict-prototypes
DEFS = -D@KERN@ -D@IPVS_SUPPORT@ -D@VRRP_SUPPORT@ @DFLAGS@
COMPILE = $(CC) $(CFLAGS) $(DEFS)
-OBJS = main.o memory.o daemon.o pidfile.o utils.o timer.o \
- scheduler.o vector.o list.o data.o parser.o layer4.o \
- smtp.o
+OBJS = main.o daemon.o pidfile.o data.o parser.o layer4.o smtp.o
HEADERS = $(OBJS:.o=.h)
.c.o:
main.o: main.c ../include/main.h
-memory.o: memory.c ../include/memory.h
daemon.o: daemon.c ../include/daemon.h
pidfile.o: pidfile.c ../include/pidfile.h
-utils.o: utils.c ../include/utils.h
-timer.o: timer.c ../include/timer.h
-scheduler.o: scheduler.c ../include/scheduler.h ../include/memory.h \
- ../include/utils.h
-vector.o: vector.c ../include/vector.h ../include/memory.h
-list.o: list.c ../include/list.h ../include/memory.h
-data.o: data.c ../include/data.h ../include/memory.h ../include/utils.h \
+data.o: data.c ../include/data.h ../../lib/memory.h ../../lib/utils.h \
../include/check_api.h ../include/vrrp.h ../include/vrrp_sync.h
-parser.o: parser.c ../include/parser.h ../include/memory.h ../include/vrrp.h \
+parser.o: parser.c ../include/parser.h ../../lib/memory.h ../include/vrrp.h \
../include/vrrp_if.h ../include/check_api.h
-layer4.o: layer4.c ../include/layer4.h ../include/check_api.h ../include/utils.h
-smtp.o: smtp.c ../include/smtp.h ../include/memory.h ../include/list.h \
- ../include/utils.h
+layer4.o: layer4.c ../include/layer4.h ../include/check_api.h ../../lib/utils.h
+smtp.o: smtp.c ../include/smtp.h ../../lib/memory.h ../../lib/list.h \
+ ../../lib/utils.h
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: main.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: data.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: data.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Layer4 checkers handling. Register worker threads &
* upper layer checkers.
*
- * Version: $Id: layer4.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: layer4.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: main.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
main(int argc, char **argv)
{
/* Init debugging level */
+ mem_allocated = 0;
debug = 0;
/*
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: parser.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: parser.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile utility.
*
- * Version: $Id: pidfile.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: pidfile.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* using the smtp protocol according to the RFC 821. A non blocking
* timeouted connection is used to handle smtp protocol.
*
- * Version: $Id: smtp.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: smtp.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
CI_LINUX_OBJ = check_ci.o
CIFLAGS = -D$(CI_LINUX)
endif
-INCLUDES = -I../include
+INCLUDES = -I../include -I../../lib
CFLAGS = @CFLAGS@ $(INCLUDES) \
-Wall -Wunused -Wstrict-prototypes
DEFS = -D$(KERNEL) -D@IPVS_SUPPORT@ -D@IPVS_SYNCD@ -D@VRRP_SUPPORT@ @DFLAGS@ $(CIFLAGS)
rm -f Makefile
check_api.o: check_api.c ../include/check_api.h ../include/parser.h \
- ../include/memory.h ../include/utils.h ../include/check_misc.h \
+ ../../lib/memory.h ../../lib/utils.h ../include/check_misc.h \
../include/check_tcp.h ../include/check_http.h ../include/check_ssl.h
check_tcp.o: check_tcp.c ../include/check_tcp.h ../include/check_api.h \
- ../include/memory.h ../include/ipwrapper.h ../include/layer4.h \
- ../include/smtp.h ../include/utils.h ../include/parser.h
+ ../../lib/memory.h ../include/ipwrapper.h ../include/layer4.h \
+ ../include/smtp.h ../../lib/utils.h ../include/parser.h
check_http.o: check_http.c ../include/check_http.h ../include/check_ssl.h \
- ../include/check_api.h ../include/memory.h ../include/parser.h \
- ../include/utils.h
+ ../include/check_api.h ../../lib/memory.h ../include/parser.h \
+ ../../lib/utils.h
check_ssl.o: check_ssl.c ../include/check_ssl.h ../include/check_api.h \
- ../include/memory.h ../include/parser.h ../include/smtp.h \
- ../include/utils.h
+ ../../lib/memory.h ../include/parser.h ../include/smtp.h \
+ ../../lib/utils.h
check_misc.o: check_misc.c ../include/check_misc.h ../include/check_api.h \
- ../include/memory.h ../include/ipwrapper.h ../include/smtp.h \
- ../include/utils.h ../include/parser.h ../include/daemon.h
-ipwrapper.o: ipwrapper.c ../include/ipwrapper.h ../include/utils.h
-ipvswrapper.o: ipvswrapper.c ../include/ipvswrapper.h ../include/utils.h \
- ../include/memory.h
+ ../../lib/memory.h ../include/ipwrapper.h ../include/smtp.h \
+ ../../lib/utils.h ../include/parser.h ../include/daemon.h
+ipwrapper.o: ipwrapper.c ../include/ipwrapper.h ../../lib/utils.h
+ipvswrapper.o: ipvswrapper.c ../include/ipvswrapper.h ../../lib/utils.h \
+ ../../lib/memory.h
*
* Part: Checkers registration.
*
- * Version: $Id: check_api.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_api.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: CI-LINUX checker. Integration to Compaq Cluster Infrastructure.
*
- * Version: $Id: check_ci.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_ci.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Aneesh Kumar K.V, <aneesh.kumar@digital.com>
*
* Part: WEB CHECK. Common HTTP/SSL checker primitives.
*
- * Version: $Id: check_http.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_http.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include "memory.h"
#include "parser.h"
#include "utils.h"
+#include "html.h"
int http_connect_thread(thread *);
dump_url(void *data)
{
url *url = data;
- syslog(LOG_INFO, " Checked url = %s, digest = %s", url->path,
- url->digest);
+ syslog(LOG_INFO, " Checked url = %s", url->path);
+ if (url->digest)
+ syslog(LOG_INFO, " digest = %s",
+ url->digest);
+ if (url->status_code)
+ syslog(LOG_INFO, " HTTP Status Code = %d",
+ url->status_code);
}
void
}
void
+status_code_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ url *url = LIST_TAIL_DATA(http_get_chk->url);
+
+ url->status_code = CHECKER_VALUE_INT(strvec);
+}
+
+void
install_http_check_keyword(void)
{
install_keyword("HTTP_GET", &http_get_handler);
install_sublevel();
install_keyword("path", &path_handler);
install_keyword("digest", &digest_handler);
+ install_keyword("status_code", &status_code_handler);
install_sublevel_end();
install_sublevel_end();
}
install_sublevel();
install_keyword("path", &path_handler);
install_keyword("digest", &digest_handler);
+ install_keyword("status_code", &status_code_handler);
install_sublevel_end();
install_sublevel_end();
}
if (req->buffer)
FREE(req->buffer);
FREE(req);
+ http_arg->req = NULL;
close(thread->u.fd);
}
return 0;
}
-/* HTML stream parser primitives */
-/* simple function returning a pointer to the html buffer begin */
-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;
-}
-
/* return the url pointer of the current url iterator */
url *
fetch_next_url(http_get_checker * http_get_check)
{
checker *checker = THREAD_ARG(thread);
http_get_checker *http_get_check = CHECKER_ARG(checker);
-#ifdef _DEBUG_
- uint16_t addr_port = get_service_port(checker);
http_arg *http_arg = HTTP_ARG(http_get_check);
-#endif
+ REQ *req = HTTP_REQ(http_arg);
+ uint16_t addr_port = get_service_port(checker);
int r, di = 0;
unsigned char *digest_tmp;
- url *fetched_url;
+ url *fetched_url = fetch_next_url(http_get_check);
- if (empty_buffer) {
+ /* First check if remote webserver returned data */
+ if (empty_buffer)
return timeout_epilog(thread, "=> CHECK failed on service"
" : empty buffer received <=\n\n",
"Read, no data received from ");
- } else {
+
+ /* Next check the HTTP status code */
+ if (fetched_url->status_code) {
+ if (req->status_code != fetched_url->status_code) {
+ /* check if server is currently alive */
+ if (ISALIVE(checker->rs)) {
+ syslog(LOG_INFO,
+ "HTTP status code error to [%s:%d] url[%s]"
+ ", status_code [%d].",
+ inet_ntop2(CHECKER_RIP(checker)),
+ ntohs(addr_port), fetched_url->path,
+ req->status_code);
+ smtp_alert(thread->master, checker->rs, NULL,
+ "DOWN",
+ "=> CHECK failed on service"
+ " : HTTP status code mismatch <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
+ }
+ return epilog(thread, 1, 0, 0);
+ }
+ }
+
+ /* Continue with MD5SUM */
+ if (fetched_url->digest) {
/* Compute MD5SUM */
digest_tmp = (char *) MALLOC(MD5_BUFFER_LENGTH + 1);
for (di = 0; di < 16; di++)
sprintf(digest_tmp + 2 * di, "%02x", digest[di]);
- fetched_url = fetch_next_url(http_get_check);
-
DBG("MD5SUM to [%s:%d] url(%d) = [%s].",
inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port),
http_arg->url_it + 1, digest_tmp);
r = strcmp(fetched_url->digest, digest_tmp);
- FREE(digest_tmp);
if (r) {
- DBG("MD5 digest error to [%s:%d] url(%d)"
- ", expecting MD5SUM [%s].",
- inet_ntop2(CHECKER_RIP(checker)),
- ntohs(addr_port), http_arg->url_it + 1,
- fetched_url->digest);
-
/* check if server is currently alive */
if (ISALIVE(checker->rs)) {
+ syslog(LOG_INFO,
+ "MD5 digest error to [%s:%d] url[%s]"
+ ", MD5SUM [%s].",
+ inet_ntop2(CHECKER_RIP(checker)),
+ ntohs(addr_port), fetched_url->path,
+ digest_tmp);
smtp_alert(thread->master, checker->rs, NULL,
"DOWN",
"=> CHECK failed on service"
" : MD5 digest mismatch <=\n\n");
- perform_svr_state(DOWN, checker->vs,
- checker->rs);
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
+ FREE(digest_tmp);
return epilog(thread, 1, 0, 0);
} else {
DBG("MD5 digest success to [%s:%d] url(%d).",
inet_ntop2(CHECKER_RIP(checker)), ntohs(addr_port),
http_arg->url_it + 1);
+ FREE(digest_tmp);
return epilog(thread, 1, 1, 0) + 1;
}
}
+
return epilog(thread, 1, 0, 0) + 1;
}
+/* Handle response stream performing MD5 updates */
+int
+http_process_response(REQ *req, int r)
+{
+ req->len += r;
+ if (!req->extracted) {
+ if ((req->extracted =
+ extract_html(req->buffer, req->len))) {
+ req->status_code = extract_status_code(req->buffer, req->len);
+ r = req->len - (req->extracted - req->buffer);
+ if (r) {
+ memcpy(req->buffer, req->extracted, r);
+ MD5_Update(&req->context, req->buffer,
+ r);
+ r = 0;
+ }
+ req->len = r;
+ } else {
+ /* minimize buffer using no 2*CR/LF found yet */
+ if (req->len > 3) {
+ memcpy(req->buffer,
+ req->buffer + req->len - 3, 3);
+ req->len = 3;
+ }
+ }
+ } else if (req->len) {
+ MD5_Update(&req->context, req->buffer,
+ req->len);
+ req->len = 0;
+ }
+
+ return 0;
+}
+
/* Asynchronous HTTP stream reader */
int
http_read_thread(thread * thread)
} else {
- req->len += r;
- if (!req->extracted) {
- if ((req->extracted =
- extract_html(req->buffer, req->len))) {
- r = req->len - (req->extracted - req->buffer);
- if (r) {
- memcpy(req->buffer, req->extracted, r);
- MD5_Update(&req->context, req->buffer,
- r);
- r = 0;
- }
- req->len = r;
- } else {
- /* minimize buffer using no 2*CR/LF found yet */
- if (req->len > 3) {
- memcpy(req->buffer,
- req->buffer + req->len - 3, 3);
- req->len = 3;
- }
- }
- } else {
- if (req->len) {
- MD5_Update(&req->context, req->buffer,
- req->len);
- req->len = 0;
- }
- }
+ /* Handle response stream */
+ http_process_response(req, r);
/*
* Register next http stream reader.
checker *checker = THREAD_ARG(thread);
http_get_checker *http_get_check = CHECKER_ARG(checker);
uint16_t addr_port = get_service_port(checker);
-#ifdef _DEBUG_
http_arg *http_arg = HTTP_ARG(http_get_check);
+#ifdef _DEBUG_
REQ *req = HTTP_REQ(http_arg);
#endif
int ret = 1;
break;
case connect_success:{
+ /* Allocate & clean request struct */
+ http_arg->req = (REQ *) MALLOC(sizeof (REQ));
+
if (http_get_check->proto == PROTO_SSL)
ret = ssl_connect(thread);
return epilog(thread, 1, 0, 0) + 1;
}
- /* Allocate & clean request struct */
- http_arg->req = (REQ *) MALLOC(sizeof (REQ));
-
+ /* Create the socket */
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
DBG("WEB connection fail to create socket.");
return 0;
* Part: MISC CHECK. Perform a system call to run an extra
* system prog or script.
*
- * Version: $Id: check_misc.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_misc.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
* url, compute a MD5 over this result and match it to the
* expected value.
*
- * Version: $Id: check_ssl.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_ssl.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include "parser.h"
#include "smtp.h"
#include "utils.h"
+#include "html.h"
extern data *conf_data;
} else if (r > 0 && req->error == 0) {
- req->len += r;
- if (!req->extracted) {
- if ((req->extracted =
- extract_html(req->buffer, req->len))) {
- r = req->len - (req->extracted - req->buffer);
- if (r) {
- memcpy(req->buffer, req->extracted, r);
- MD5_Update(&req->context, req->buffer,
- r);
- r = 0;
- }
- req->len = r;
- } else {
- /* minimize buffer using no 2*CR/LF found yet */
- if (req->len > 3) {
- memcpy(req->buffer,
- req->buffer + req->len - 3, 3);
- req->len = 3;
- }
- }
- } else {
- if (req->len) {
- MD5_Update(&req->context, req->buffer,
- req->len);
- req->len = 0;
- }
- }
+ /* Handle response stream */
+ http_process_response(req, r);
/*
* Register next ssl stream reader.
*
* Part: TCP checker.
*
- * Version: $Id: check_tcp.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_tcp.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* library to add/remove server MASQ rules to the kernel
* firewall framework.
*
- * Version: $Id: ipfwwrapper.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: ipfwwrapper.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: IPVS Kernel wrapper. Use setsockopt call to add/remove
* server to/from the loadbalanced server pool.
*
- * Version: $Id: ipvswrapper.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: ipvswrapper.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Manipulation functions for IPVS & IPFW wrappers.
*
- * Version: $id: ipwrapper.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $id: ipwrapper.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Checkers arguments structures definitions.
*
- * Version: $Id: check_api.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_api.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_ci.c include file.
*
- * Version: $Id: check_ci.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_ci.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Aneesh Kumar K.V, <aneesh.kumar@digital.com>
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_http.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
char *buffer;
char *extracted;
int error;
+ int status_code;
int len;
SSL *ssl;
BIO *bio;
typedef struct _url {
char *path;
char *digest;
+ int status_code;
} url;
typedef struct _http_get_checker {
int proto;
extern void install_http_check_keyword(void);
extern int epilog(thread * thread, int metod, int t, int c);
extern int timeout_epilog(thread * thread, char *smtp_msg, char *debug_msg);
-extern char *extract_html(char *buffer, int size_buffer);
extern url *fetch_next_url(http_get_checker * http_get_check);
+extern int http_process_response(REQ *req, int r);
extern int http_handle_response(thread * thread, unsigned char digest[16]
, int empty_buffer);
#endif
*
* Part: check_misc.c include file.
*
- * Version: $Id: check_misc.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_misc.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_http.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: check_tcp.c include file.
*
- * Version: $Id: check_tcp.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: check_tcp.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Daemon process handling.
*
- * Version: $Id: daemon.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: daemon.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: data.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: data.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipfwwrapper.c include file.
*
- * Version: $Id: ipfwwrapper.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: ipfwwrapper.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipvswrapper.c include file.
*
- * Version: $Id: ipvswrapper.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: ipvswrapper.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipwrapper.c include file.
*
- * Version: $Id: ipwrapper.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: ipwrapper.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: layer4.c include file.
*
- * Version: $Id: layer4.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: layer4.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program include file.
*
- * Version: $Id: main.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: main.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
char *conf_file = NULL; /* Configuration file */
int reload = 0; /* Global reloading flag */
unsigned int debug; /* Debugging flags */
-unsigned long mem_allocated = 0; /* Total memory used in Bytes */
data *conf_data; /* Global configuration data */
data *old_data; /* Used during reload process */
/* Build version */
#define PROG "Keepalived"
-#define VERSION_CODE 0x000701
-#define DATE_CODE 0x110902
+#define VERSION_CODE 0x000706
+#define DATE_CODE 0x140A02
#define KEEPALIVED_VERSION(version) \
(version >> 16) & 0xFF, \
*
* Part: cfreader.c include file.
*
- * Version: $Id: parser.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: parser.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile.c include file.
*
- * Version: $Id: pidfile.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: pidfile.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: smtp.c include file.
*
- * Version: $Id: smtp.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: smtp.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp.c program include file.
*
- * Version: $Id: vrrp.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#define _VRRP_H
/* system include */
-#include <net/ethernet.h>
-#include <netinet/ip.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
#include <unistd.h>
/* local include */
* VRRP adverts
*/
int adver_int; /* delay between advertisements(in sec) */
- char hwaddr[6]; /* VMAC -- rfc2338.7.3 */
int preempt; /* true if a higher prio preempt a lower one */
int state; /* internal state (init/backup/master) */
int init_state; /* the initial state of the instance */
--- /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: vrrp_arp.c include file.
+ *
+ * Version: $Id: vrrp_arp.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _VRRP_ARP_H
+#define _VRRP_ARP_H
+
+/* system includes */
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+
+/* local includes */
+#include "vrrp.h"
+
+/* local definitions */
+#define ETHERNET_HW_LEN 6
+#define IPPROTO_ADDR_LEN 4
+
+/* types definition */
+typedef struct _m_arphdr {
+ unsigned short int ar_hrd; /* Format of hardware address. */
+ unsigned short int ar_pro; /* Format of protocol address. */
+ unsigned char ar_hln; /* Length of hardware address. */
+ unsigned char ar_pln; /* Length of protocol address. */
+ unsigned short int ar_op; /* ARP opcode (command). */
+
+ /* Ethernet looks like this : This bit is variable sized however... */
+ unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */
+ unsigned char __ar_sip[4]; /* Sender IP address. */
+ unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */
+ unsigned char __ar_tip[4]; /* Target IP address. */
+} m_arphdr;
+
+/* prototypes */
+extern int send_gratuitous_arp(vrrp_rt * vrrp, int addr);
+
+#endif
*
* Part: vrrp_if.c include file.
*
- * Version: $Id: vrrp_if.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_if.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
extern void init_interface_queue(void);
extern void free_interface_queue(void);
extern void dump_if(void *data);
+extern int if_join_vrrp_group(int sd, interface *ifp, int proto);
+extern void if_leave_vrrp_group(int sd, interface *ifp);
+extern int if_setsockopt_bindtodevice(int sd, interface *ifp);
+extern int if_setsockopt_hdrincl(int sd);
+extern int if_setsockopt_mcast_loop(int sd);
#endif
*
* Part: vrrp_ipaddress.c include file.
*
- * Version: $Id: vrrp_ipaddress.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_ipsecah.c include file.
*
- * Version: $Id: vrrp_ipsecah.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_netlink.c include file.
*
- * Version: $Id: vrrp_netlink.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_netlink.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_notify.c include file.
*
- * Version: $Id: vrrp_notify.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_notify.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_scheduler.c include file.
*
- * Version: $Id: vrrp_scheduler.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_scheduler.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_sync.c include file.
*
- * Version: $Id: vrrp_sync.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_sync.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
lvs_id LVS_DEVEL
}
-!SSL {
-! password password
-! ca /etc/keepalived/root.pem
-! certificate /etc/keepalived/dh1024.pem
-! key /etc/keepalived/client.pem
-!}
-
vrrp_instance VI_1 {
state MASTER
interface eth0
delay_loop 6
lb_algo rr
lb_kind NAT
- nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
delay_loop 6
lb_algo rr
lb_kind NAT
- nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
--- /dev/null
+! Configuration File for keepalived
+
+global_defs {
+ notification_email {
+ acassen
+ }
+ notification_email_from Alexandre.Cassen@firewall.loc
+ smtp_server 192.168.200.1
+ smtp_connect_timeout 30
+ lvs_id LVS_DEVEL
+}
+
+virtual_server 192.168.200.100 443 {
+ delay_loop 6
+ lb_algo rr
+ lb_kind NAT
+ persistence_timeout 50
+ protocol TCP
+
+ real_server 192.168.201.100 443 {
+ weight 1
+ SSL_GET {
+ url {
+ path /
+ status_code 200 # Can only specify a HTTP status_code
+ }
+ url {
+ path /mrtg/
+ digest 9b3a0c85a887a256d6939da88aabd8cd
+ status_code 200 # Can mix digest and status_code
+ }
+ connect_timeout 3
+ nb_get_retry 3
+ delay_before_retry 3
+ }
+ }
+}
# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
CC = @CC@
-INCLUDES = -I../include
+INCLUDES = -I../include -I../../lib
CFLAGS = @CFLAGS@ $(INCLUDES) \
-Wall -Wunused -Wstrict-prototypes
DEFS = -D@KERN@ -D@IPVS_SUPPORT@ -D@IPVS_SYNCD@ @DFLAGS@
COMPILE = $(CC) $(CFLAGS) $(DEFS)
OBJS = vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o \
- vrrp_netlink.o vrrp_if.o vrrp_ipaddress.o vrrp_ipsecah.o
+ vrrp_netlink.o vrrp_arp.o vrrp_if.o vrrp_ipaddress.o vrrp_ipsecah.o
HEADERS = $(OBJS:.o=.h)
.c.o:
rm -f Makefile
vrrp.o: vrrp.c ../include/vrrp.h ../include/vrrp_scheduler.h \
- ../include/vrrp_notify.h ../include/ipvswrapper.h ../include/memory.h \
- ../include/list.h ../include/data.h
-vrrp_notify.o: vrrp_notify.c ../include/vrrp_notify.h ../include/memory.h
+ ../include/vrrp_notify.h ../include/ipvswrapper.h ../../lib/memory.h \
+ ../../lib/list.h ../include/data.h ../include/vrrp_arp.h
+vrrp_notify.o: vrrp_notify.c ../include/vrrp_notify.h ../../lib/memory.h
vrrp_scheduler.o: vrrp_scheduler.c ../include/vrrp_scheduler.h \
../include/vrrp_ipsecah.h ../include/vrrp_if.h ../include/vrrp.h \
../include/vrrp_sync.h ../include/vrrp_notify.h ../include/ipvswrapper.h \
- ../include/memory.h ../include/list.h ../include/data.h ../include/smtp.h
+ ../../lib/memory.h ../../lib/list.h ../include/data.h ../include/smtp.h
vrrp_sync.o: vrrp_sync.c ../include/vrrp_sync.h ../include/vrrp_if.h \
../include/vrrp_notify.h ../include/data.h
vrrp_netlink.o: vrrp_netlink.c ../include/vrrp_netlink.h ../include/check_api.h \
- ../include/vrrp_if.h ../include/memory.h ../include/scheduler.h \
- ../include/utils.h
+ ../include/vrrp_if.h ../../lib/memory.h ../../lib/scheduler.h \
+ ../../lib/utils.h
+vrrp_arp.o: vrrp_arp.c ../include/vrrp_arp.h
vrrp_if.o: vrrp_if.c ../include/vrrp_if.h ../include/vrrp_netlink.h \
- ../include/scheduler.h ../include/data.h ../include/memory.h \
- ../include/utils.h
+ ../../lib/scheduler.h ../include/data.h ../../lib/memory.h \
+ ../../lib/utils.h
vrrp_ipaddress.o: vrrp_ipaddress.c ../include/vrrp_ipaddress.h \
- ../include/vrrp_netlink.h ../include/utils.h
+ ../include/vrrp_netlink.h ../../lib/utils.h
vrrp_ipsecah.o: vrrp_ipsecah.c ../include/vrrp_ipsecah.h
* master fails, a backup server takes over.
* The original implementation has been made by jerome etienne.
*
- * Version: $Id: vrrp.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include <ctype.h>
+#include <sys/uio.h>
+#include "vrrp_arp.h"
#include "vrrp_scheduler.h"
#include "vrrp_notify.h"
#include "ipvswrapper.h"
return err;
}
-/* ARP header length */
-static int
-vrrp_dlt_len(vrrp_rt * rt)
-{
- return ETHER_HDR_LEN; /* hardcoded for ethernet */
-}
-
/* IP header length */
static int
vrrp_iphdr_len(vrrp_rt * vrrp)
/*
* then proceed with the sequence number to prevent against replay attack.
- * in inbound processing, we increment seq_number counter to audit
+ * For inbound processing, we increment seq_number counter to audit
* sender counter.
*/
vrrp->ipsecah_counter->seq_number++;
vrrp->ipsecah_counter->seq_number = ah->seq_number;
} else {
syslog(LOG_INFO,
- "IPSEC AH : sequence number %d already proceeded."
- " Packet droped", ah->seq_number);
+ "VRRP_Instance(%s) IPSEC-AH : sequence number %d"
+ " already proceeded. Packet dropped", vrrp->iname
+ , ah->seq_number);
return 1;
}
, digest);
if (memcmp(backup_auth_data, digest, HMAC_MD5_TRUNC) != 0) {
- syslog(LOG_INFO, "IPSEC AH : invalid IPSEC HMAC-MD5 value."
- " Due to fields mutation or bad password !");
+ syslog(LOG_INFO, "VRRP_Instance(%s) IPSEC-AH : invalid"
+ " IPSEC HMAC-MD5 value. Due to fields mutation"
+ " or bad password !", vrrp->iname);
return 1;
}
for (i = 0; i < vrrp->naddr; i++) {
bcopy(buffer + i * sizeof (uint32_t), &ipbuf,
sizeof (uint32_t));
- if (ipaddr == ntohl(ipbuf))
+// if (ipaddr == ntohl(ipbuf))
+ if (ipaddr == ipbuf)
return 1;
}
return VRRP_PACKET_OK;
}
-/* build ARP header */
-static void
-vrrp_build_arp(vrrp_rt * vrrp, char *buffer, int buflen)
-{
- /* hardcoded for ethernet */
- struct ether_header *eth = (struct ether_header *) buffer;
-
- /* destination address --rfc1122.6.4 */
- eth->ether_dhost[0] = 0x01;
- eth->ether_dhost[1] = 0x00;
- eth->ether_dhost[2] = 0x5E;
- eth->ether_dhost[3] = (INADDR_VRRP_GROUP >> 16) & 0x7F;
- eth->ether_dhost[4] = (INADDR_VRRP_GROUP >> 8) & 0xFF;
- eth->ether_dhost[5] = INADDR_VRRP_GROUP & 0xFF;
-
- /* source address -- rfc2338.7.3 */
- memcpy(eth->ether_shost, vrrp->hwaddr, sizeof (vrrp->hwaddr));
-
- /* type */
- eth->ether_type = htons(ETHERTYPE_IP);
-}
-
/* build IP header */
static void
vrrp_build_ip(vrrp_rt * vrrp, char *buffer, int buflen)
hd->adver_int = vrrp->adver_int / TIMER_HZ;
/* copy the ip addresses */
- for (i = 0; i < vrrp->naddr; i++) {
- iparr[i] = htonl(vrrp->vaddr[i].addr);
- }
+ for (i = 0; i < vrrp->naddr; i++)
+ iparr[i] = vrrp->vaddr[i].addr;
+// iparr[i] = htonl(vrrp->vaddr[i].addr);
/* copy the passwd if the authentication is VRRP_AH_PASS */
if (vrrp->auth_type == VRRP_AUTH_PASS) {
bufptr = buffer;
- /* build the ethernet header */
- vrrp_build_arp(vrrp, buffer, buflen);
-
/* build the ip header */
- buffer += vrrp_dlt_len(vrrp);
- buflen -= vrrp_dlt_len(vrrp);
vrrp_build_ip(vrrp, buffer, buflen);
/* build the vrrp header */
/* build the IPSEC AH header */
if (vrrp->auth_type == VRRP_AUTH_AH) {
- bufptr += vrrp_dlt_len(vrrp);
- buflen += vrrp_ipsecah_len() + vrrp_iphdr_len(vrrp);;
+ buflen += vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len();
vrrp_build_ipsecah(vrrp, bufptr, buflen);
}
}
static int
vrrp_send_pkt(vrrp_rt * vrrp, char *buffer, int buflen)
{
- struct sockaddr from;
- int len;
- int fd = socket(PF_PACKET, SOCK_PACKET, 0x300); /* 0x300 is magic */
-
- if (fd < 0) {
- syslog(LOG_INFO, "VRRP Error : socket creation");
- return -1;
- }
-
- /* build the address */
- memset(&from, 0, sizeof (from));
- strncpy(from.sa_data, IF_NAME(vrrp->ifp), sizeof(from.sa_data));
-
-//print_buffer(buflen, buffer);
+ struct sockaddr_in dst;
+ struct msghdr msg;
+ struct iovec iov;
+ int fd;
+ int ret;
- /* send the data */
- len = sendto(fd, buffer, buflen, 0, &from, sizeof (from));
+ /* Create and init socket descriptor */
+ fd = socket(AF_INET
+ , SOCK_RAW
+ , (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP);
+ if_setsockopt_hdrincl(fd);
+ if_setsockopt_bindtodevice(fd, vrrp->ifp);
+ if_setsockopt_mcast_loop(fd);
+
+ /* Sending path */
+ memset(&dst, 0, sizeof(dst));
+ dst.sin_family = AF_INET;
+ dst.sin_addr.s_addr = htonl(INADDR_VRRP_GROUP);
+ dst.sin_port = htons(0);
+
+ /* Build the message data */
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = &dst;
+ msg.msg_namelen = sizeof(dst);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ iov.iov_base = buffer;
+ iov.iov_len = buflen;
+
+ /* Send the packet */
+ ret = sendmsg(fd, &msg, MSG_DONTROUTE);
close(fd);
- return len;
+ return 0;
}
/* send VRRP advertissement */
char *buffer;
/* alloc the memory */
- buflen = vrrp_dlt_len(vrrp) + vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
+ buflen = vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
if (vrrp->auth_type == VRRP_AUTH_AH)
buflen += vrrp_ipsecah_len();
return VRRP_PACKET_NULL;
}
-/* send a gratuitous ARP packet */
-static int
-send_gratuitous_arp(vrrp_rt * vrrp, int addr)
-{
- struct m_arphdr {
- unsigned short int ar_hrd; /* Format of hardware address. */
- unsigned short int ar_pro; /* Format of protocol address. */
- unsigned char ar_hln; /* Length of hardware address. */
- unsigned char ar_pln; /* Length of protocol address. */
- unsigned short int ar_op; /* ARP opcode (command). */
-
- /* Ethernet looks like this : This bit is variable sized however... */
- unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */
- unsigned char __ar_sip[4]; /* Sender IP address. */
- unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */
- unsigned char __ar_tip[4]; /* Target IP address. */
- };
-
- char buf[sizeof (struct m_arphdr) + ETHER_HDR_LEN];
- char buflen = sizeof (struct m_arphdr) + ETHER_HDR_LEN;
- struct ether_header *eth = (struct ether_header *) buf;
- struct m_arphdr *arph = (struct m_arphdr *) (buf + vrrp_dlt_len(vrrp));
- char *hwaddr = IF_HWADDR(vrrp->ifp);
- int hwlen = ETH_ALEN;
-
- /* hardcoded for ethernet */
- memset(eth->ether_dhost, 0xFF, ETH_ALEN);
- memcpy(eth->ether_shost, hwaddr, hwlen);
- eth->ether_type = htons(ETHERTYPE_ARP);
-
- /* build the arp payload */
- memset(arph, 0, sizeof (*arph));
- arph->ar_hrd = htons(ARPHRD_ETHER);
- arph->ar_pro = htons(ETHERTYPE_IP);
- arph->ar_hln = 6;
- arph->ar_pln = 4;
- arph->ar_op = htons(ARPOP_REQUEST);
- memcpy(arph->__ar_sha, hwaddr, hwlen);
- memcpy(arph->__ar_sip, &addr, sizeof (addr));
- memcpy(arph->__ar_tip, &addr, sizeof (addr));
-
- return vrrp_send_pkt(vrrp, buf, buflen);
-}
-
/* Gratuitous ARP on each VIP */
void
vrrp_send_gratuitous_arp(vrrp_rt * vrrp)
int ret = 0;
struct iphdr *iph = (struct iphdr *) buf;
vrrp_pkt *hd = NULL;
+ ipsec_ah *ah;
/* return on link failure */
if (vrrp->wantstate == VRRP_STATE_GOTO_FAULT) {
/* We receive a lower prio adv we just refresh remote ARP cache */
syslog(LOG_INFO, "VRRP_Instance(%s) Received lower prio advert"
", forcing new election", vrrp->iname);
+ if (iph->protocol == IPPROTO_IPSEC_AH) {
+ ah = (ipsec_ah *) (buf + sizeof(struct iphdr));
+ syslog(LOG_INFO, "VRRP_Instance(%s) IPSEC-AH : Syncing seq_num"
+ " with received = %d", vrrp->iname, ah->seq_number);
+ vrrp->ipsecah_counter->seq_number = ah->seq_number + 1;
+ vrrp->ipsecah_counter->cycle = 0;
+ }
vrrp_send_adv(vrrp, vrrp->priority);
vrrp_send_gratuitous_arp(vrrp);
return 0;
int
open_vrrp_socket(const int proto, const int index)
{
- struct ip_mreqn req_add;
interface *ifp;
- int fd;
- int ret;
+ int fd = -1;
/* Retreive interface */
ifp = if_get_by_ifindex(index);
/* Simply return if interface is shut */
if (!IF_ISUP(ifp))
- return -1;
-
- /* open the socket */
- fd = socket(AF_INET, SOCK_RAW, proto);
+ return fd;
- if (fd < 0) {
- int err = errno;
- syslog(LOG_INFO,
- "cant open raw socket. errno=%d. (try to run it as root)",
- err);
- return -1;
- }
-
- /* -> inbound processing option
- * Specify the bound_dev_if.
- * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
- * sk->bound_dev_if themself ??? !!!
- * Needed for filter multicasted advert per interface.
- *
- * -- If you read this !!! and know the answer to the question
- * please feel free to answer me ! :)
- */
- ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, IF_NAME(ifp)
- , strlen(IF_NAME(ifp)) + 1);
- if (ret < 0) {
- int err = errno;
- syslog(LOG_INFO,
- "cant bind to device %s. errno=%d. (try to run it as root)",
- IF_NAME(ifp)
- , err);
- close(fd);
- return -1;
- }
+ /* open the socket */
+ fd = socket(AF_INET, SOCK_RAW, proto);
+ if (fd < 0) {
+ int err = errno;
+ syslog(LOG_INFO,
+ "cant open raw socket. errno=%d. (try to run it as root)",
+ err);
+ return -1;
+ }
- /* -> outbound processing option
- * join the multicast group.
- * binding the socket to the interface for outbound multicast
- * traffic.
- */
- memset(&req_add, 0, sizeof (req_add));
- req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
- req_add.imr_address.s_addr = IF_ADDR(ifp);
- req_add.imr_ifindex = IF_INDEX(ifp);
+ /* Join the VRRP MCAST group */
+ if_join_vrrp_group(fd, ifp, proto);
- /* -> Need to handle multicast convergance after takeover.
- * We retry until multicast is available on the interface.
- */
- ret =
- setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &req_add,
- sizeof (struct ip_mreqn));
- if (ret < 0) {
- syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%s (%d)",
- strerror(errno), errno);
- close(fd);
- return -1;
- }
+ /* Bind inbound stream */
+ if_setsockopt_bindtodevice(fd, ifp);
return fd;
}
void
close_vrrp_socket(vrrp_rt * vrrp)
{
- struct ip_mreqn req_add;
- int ret = 0;
-
- /* If fd is -1 then we add a membership trouble */
- if (vrrp->fd < 0)
- return;
-
- /* Leaving the VRRP multicast group */
- memset(&req_add, 0, sizeof (req_add));
- req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
- req_add.imr_address.s_addr = IF_ADDR(vrrp->ifp);
- req_add.imr_ifindex = IF_INDEX(vrrp->ifp);
- ret =
- setsockopt(vrrp->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *) &req_add, sizeof (struct ip_mreqn));
- if (ret < 0) {
- syslog(LOG_INFO, "cant do IP_DROP_MEMBERSHIP errno=%s (%d)",
- strerror(errno)
- , errno);
- return;
- }
-
- /* Finally close the desc */
- close(vrrp->fd);
+ if_leave_vrrp_group(vrrp->fd, vrrp->ifp);
}
int
static int
vrrp_complete_instance(vrrp_rt * vrrp)
{
- /* complete the VMAC address */
- vrrp->hwaddr[0] = 0x00;
- vrrp->hwaddr[1] = 0x00;
- vrrp->hwaddr[2] = 0x5E;
- vrrp->hwaddr[3] = 0x00;
- vrrp->hwaddr[4] = 0x01;
- vrrp->hwaddr[5] = vrrp->vrid;
-
vrrp->state = VRRP_STATE_INIT;
if (!vrrp->adver_int)
vrrp->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
--- /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: ARP primitives.
+ *
+ * Version: $Id: vrrp_arp.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+/* system includes */
+#include <linux/if_packet.h>
+
+/* local includes */
+#include "vrrp_arp.h"
+#include "memory.h"
+#include "utils.h"
+
+/* Send the gratuitous ARP message */
+static int send_arp(vrrp_rt *vrrp, char *buffer, int buflen)
+{
+ int fd;
+ int len;
+ struct sockaddr_ll sll;
+
+ /* Create the socket descriptor */
+ fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP));
+
+ /* Build the dst device */
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ strncpy(sll.sll_addr, IF_HWADDR(vrrp->ifp), sizeof(sll.sll_addr));
+ sll.sll_halen = ETHERNET_HW_LEN;
+ sll.sll_ifindex = IF_INDEX(vrrp->ifp);
+
+ /* Send packet */
+ len = sendto(fd, buffer, buflen, 0,(struct sockaddr *)&sll, sizeof(sll));
+
+ close(fd);
+ return len;
+}
+
+/* Build a gratuitous ARP message over a specific interface */
+int send_gratuitous_arp(vrrp_rt * vrrp, int addr)
+{
+ char buflen = sizeof(m_arphdr) + ETHER_HDR_LEN;
+ char *buf = (char *)MALLOC(buflen);
+ struct ether_header *eth = (struct ether_header *) buf;
+ m_arphdr *arph = (m_arphdr *) (buf + ETHER_HDR_LEN);
+ char *hwaddr = IF_HWADDR(vrrp->ifp);
+ int len;
+
+ /* Ethernet header */
+ memset(eth->ether_dhost, 0xFF, ETH_ALEN);
+ memcpy(eth->ether_shost, hwaddr, ETH_ALEN);
+ eth->ether_type = htons(ETHERTYPE_ARP);
+
+ /* ARP payload */
+ arph->ar_hrd = htons(ARPHRD_ETHER);
+ arph->ar_pro = htons(ETHERTYPE_IP);
+ arph->ar_hln = ETHERNET_HW_LEN;
+ arph->ar_pln = IPPROTO_ADDR_LEN;
+ arph->ar_op = htons(ARPOP_REQUEST);
+ memcpy(arph->__ar_sha, hwaddr, ETH_ALEN);
+ memcpy(arph->__ar_sip, &addr, sizeof (addr));
+ memcpy(arph->__ar_tip, &addr, sizeof (addr));
+
+ /* Send the ARP message */
+ len = send_arp(vrrp, buf, buflen);
+
+ FREE(buf);
+ return len;
+}
*
* Part: Interfaces manipulation.
*
- * Version: $Id: vrrp_if.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_if.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include "scheduler.h"
#include "data.h"
+#include "vrrp.h"
#include "vrrp_if.h"
#include "vrrp_netlink.h"
#include "memory.h"
/* Register NIC Heartbeat monitoring thread */
thread_add_timer(master, if_monitor_thread, NULL, POLLING_DELAY);
}
+
+int
+if_join_vrrp_group(int sd, interface *ifp, int proto)
+{
+ struct ip_mreqn req_add;
+ int ret;
+
+ /* -> outbound processing option
+ * join the multicast group.
+ * binding the socket to the interface for outbound multicast
+ * traffic.
+ */
+ memset(&req_add, 0, sizeof (req_add));
+ req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+ req_add.imr_address.s_addr = IF_ADDR(ifp);
+ req_add.imr_ifindex = IF_INDEX(ifp);
+
+ /* -> Need to handle multicast convergance after takeover.
+ * We retry until multicast is available on the interface.
+ */
+ ret = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *) &req_add, sizeof (struct ip_mreqn));
+ if (ret < 0) {
+ syslog(LOG_INFO, "cant do IP_ADD_MEMBERSHIP errno=%s (%d)",
+ strerror(errno), errno);
+ close(sd);
+ return -1;
+ }
+
+ return sd;
+}
+
+void
+if_leave_vrrp_group(int sd, interface *ifp)
+{
+ struct ip_mreqn req_add;
+ int ret = 0;
+
+ /* If fd is -1 then we add a membership trouble */
+ if (sd < 0)
+ return;
+
+ /* Leaving the VRRP multicast group */
+ memset(&req_add, 0, sizeof (req_add));
+ req_add.imr_multiaddr.s_addr = htonl(INADDR_VRRP_GROUP);
+ req_add.imr_address.s_addr = IF_ADDR(ifp);
+ req_add.imr_ifindex = IF_INDEX(ifp);
+ ret = setsockopt(sd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *) &req_add, sizeof (struct ip_mreqn));
+ if (ret < 0) {
+ syslog(LOG_INFO, "cant do IP_DROP_MEMBERSHIP errno=%s (%d)",
+ strerror(errno), errno);
+ return;
+ }
+
+ /* Finally close the desc */
+ close(sd);
+}
+
+int
+if_setsockopt_bindtodevice(int sd, interface *ifp)
+{
+ int ret;
+
+ if (sd < 0)
+ return sd;
+
+ /* -> inbound processing option
+ * Specify the bound_dev_if.
+ * why IP_ADD_MEMBERSHIP & IP_MULTICAST_IF doesnt set
+ * sk->bound_dev_if themself ??? !!!
+ * Needed for filter multicasted advert per interface.
+ *
+ * -- If you read this !!! and know the answer to the question
+ * please feel free to answer me ! :)
+ */
+ ret = setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, IF_NAME(ifp)
+ , strlen(IF_NAME(ifp)) + 1);
+ if (ret < 0) {
+ int err = errno;
+ syslog(LOG_INFO,
+ "cant bind to device %s. errno=%d. (try to run it as root)",
+ IF_NAME(ifp), err);
+ close(sd);
+ sd = -1;
+ }
+
+ return sd;
+}
+
+int
+if_setsockopt_hdrincl(int sd)
+{
+ int ret;
+ int on = 1;
+
+ /* Include IP header into RAW protocol packet */
+ ret = setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
+ if (ret < 0) {
+ int err = errno;
+ syslog(LOG_INFO, "cant set HDRINCL IP option. errno=%d.", err);
+ close(sd);
+ return -1;
+ }
+
+ return sd;
+}
+
+int
+if_setsockopt_mcast_loop(int sd)
+{
+ int ret;
+ unsigned char loop = 0;
+
+ /* Include IP header into RAW protocol packet */
+ ret = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
+ if (ret < 0) {
+ int err = errno;
+ syslog(LOG_INFO, "cant set MULTICAST_LOOP IP option. errno=%d.", err);
+ close(sd);
+ return -1;
+ }
+
+ return sd;
+}
*
* Part: NETLINK IPv4 address manipulation.
*
- * Version: $Id: vrrp_ipaddress.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* authentication data encryption using HMAC MD5 according to
* RFCs 2085 & 2104.
*
- * Version: $Id: vrrp_ipsecah.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK kernel command channel.
*
- * Version: $Id: vrrp_netlink.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_netlink.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: VRRP state transition notification scripts handling.
*
- * Version: $Id: vrrp_notify.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_notify.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Sheduling framework for vrrp code.
*
- * Version: $Id: vrrp_scheduler.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_scheduler.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
{ {NULL}, {NULL}, {NULL}, {NULL} },
{ {NULL}, {vrrp_sync_master_election}, {vrrp_sync_master}, {vrrp_sync_fault} },
{ {NULL}, {vrrp_sync_backup}, {NULL}, {vrrp_sync_fault} },
- { {NULL}, {NULL}, {NULL}, {vrrp_sync_fault} }
+ { {NULL}, {vrrp_sync_backup}, {vrrp_sync_master}, {vrrp_sync_fault} }
};
if (iph->protocol == IPPROTO_IPSEC_AH) {
ah = (ipsec_ah *) (vrrp_buffer + sizeof (struct iphdr));
if (ah->seq_number >= vrrp->ipsecah_counter->seq_number) {
- vrrp->ipsecah_counter->seq_number = ah->seq_number + 10;
+// vrrp->ipsecah_counter->seq_number = ah->seq_number + 10;
vrrp->ipsecah_counter->cycle = 0;
}
}
* with the remote IPSEC AH VRRP instance counter.
*/
if (iph->protocol == IPPROTO_IPSEC_AH) {
- syslog(LOG_INFO, "VRRP_Instance(%s) AH seq_num sync",
+ syslog(LOG_INFO, "VRRP_Instance(%s) IPSEC-AH : seq_num sync",
vrrp->iname);
ah = (ipsec_ah *) (vrrp_buffer + sizeof (struct iphdr));
- vrrp->ipsecah_counter->seq_number = ah->seq_number + 5;
+ vrrp->ipsecah_counter->seq_number = ah->seq_number + 1;
vrrp->ipsecah_counter->cycle = 0;
}
*
* Part: VRRP synchronization framework.
*
- * Version: $Id: vrrp_sync.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vrrp_sync.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
if (IF_ISUP(isync->ifp))
is_up++;
}
- return (is_up == VECTOR_SIZE(vgroup->iname)) ? 1 : 0;
+
+ if (is_up == VECTOR_SIZE(vgroup->iname)) {
+ syslog(LOG_INFO, "Kernel is reporting: Group(%s) UP"
+ , GROUP_NAME(vgroup));
+ return 1;
+ }
+ return 0;
}
/* Leaving fault state */
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
- if (GROUP_STATE(vrrp->sync) != VRRP_STATE_MAST)
- return;
-
syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to BACKUP state",
GROUP_NAME(vrrp->sync));
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
- if (GROUP_STATE(vrrp->sync) != VRRP_STATE_BACK)
- return;
-
syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to MASTER state",
GROUP_NAME(vrrp->sync));
--- /dev/null
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+CC = @CC@
+INCLUDES = -I.
+CFLAGS = @CFLAGS@ $(INCLUDES) \
+ -Wall -Wunused -Wstrict-prototypes
+DEFS = @DFLAGS@
+COMPILE = $(CC) $(CFLAGS) $(DEFS)
+
+OBJS = memory.o utils.o timer.o scheduler.o vector.o list.o html.o
+HEADERS = $(OBJS:.o=.h)
+
+.c.o:
+ $(COMPILE) -c $<
+
+all: $(OBJS)
+
+clean:
+ rm -f *.a *.o *~
+
+distclean: clean
+ rm -f Makefile
+
+
+memory.o: memory.c memory.h
+utils.o: utils.c utils.h
+timer.o: timer.c timer.h
+scheduler.o: scheduler.c scheduler.h memory.h utils.h
+vector.o: vector.c vector.h memory.h
+list.o: list.c list.h memory.h
+html.o: html.h memory.h
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: HTML stream parser utility functions.
+ *
+ * Version: $Id: html.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+#include "html.h"
+#include "memory.h"
+
+/* Return the http header content length */
+int extract_content_length(char *buffer, int size)
+{
+ char *clen = strstr(buffer, CONTENT_LENGTH);
+ char *content_buffer = NULL;
+ char *buf_len;
+ int inc = 0;
+ int i;
+
+ /* Allocate the room */
+ buf_len = (char *)MALLOC(40);
+
+ /* Pattern not found */
+ if (!clen)
+ return 0;
+
+ /* Content-Length extraction */
+ while (*(clen++) != ':');
+ content_buffer = clen;
+ while (*(clen++) != '\r' && *clen != '\n')
+ inc++;
+ for (i = 0; i < inc; i++)
+ strncat(buf_len, content_buffer+i, 1);
+ i = atoi(buf_len);
+ FREE(buf_len);
+ return i;
+}
+
+/*
+ * Return the http header error code. According
+ * to rfc2616.6.1 status code is between HTTP_Version
+ * and Reason_Phrase, separated by space caracter.
+ */
+int extract_status_code(char *buffer, int size)
+{
+ char *buf_code;
+ char *begin;
+ char *end = buffer + size;
+ int inc = 0;
+
+ /* Allocate the room */
+ buf_code = (char *)MALLOC(10);
+
+ /* Status-Code extraction */
+ while (buffer < end && *buffer++ != ' ') ;
+ begin = buffer;
+ while (buffer < end && *buffer++ != ' ')
+ inc++;
+ strncat(buf_code, begin, inc);
+ inc = atoi(buf_code);
+ FREE(buf_code);
+ return inc;
+}
+
+/* simple function returning a pointer to the html buffer begin */
+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;
+}
--- /dev/null
+/*
+ * Soft: Perform a GET query to a remote HTTP/HTTPS server.
+ * Set a timer to compute global remote server response
+ * time.
+ *
+ * Part: parser.c include file.
+ *
+ * Version: $Id: html.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
+ *
+ * Authors: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * 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 _HTML_H
+#define _HTML_H
+
+/* HTTP header tag */
+#define CONTENT_LENGTH "Content-Length:"
+
+/* Prototypes */
+extern int extract_content_length(char *buffer, int size);
+extern int extract_status_code(char *buffer, int size);
+extern char *extract_html(char *buffer, int size_buffer);
+
+#endif
*
* Part: List structure manipulation.
*
- * Version: $Id: list.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: list.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: list.c include file.
*
- * Version: $Id: list.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: list.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Memory management framework. This framework is used to
* find any memory leak.
*
- * Version: $Id: memory.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: memory.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: memory.c include file.
*
- * Version: $Id: memory.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: memory.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include <stdlib.h>
#include <string.h>
+/* Global var */
+unsigned long mem_allocated; /* Total memory used in Bytes */
+
/* extern types */
extern unsigned int debug;
extern unsigned long mem_allocated;
* the thread management routine (thread.c) present in the
* very nice zebra project (http://www.zebra.org).
*
- * Version: $Id: scheduler.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: scheduler.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: scheduler.c include file.
*
- * Version: $Id: scheduler.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: scheduler.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Timer manipulations.
*
- * Version: $Id: timer.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: timer.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* 2 of the License, or (at your option) any later version.
*/
+#include <stdio.h>
#include <string.h>
#include "timer.h"
{
return timer_sub(timer_now(), a);
}
+
+/* print timer value */
+void
+timer_dump(TIMEVAL a)
+{
+ unsigned long timer;
+ timer = a.tv_sec * TIMER_HZ + a.tv_usec;
+ printf("=> %lu (usecs)\n", timer);
+}
+
+unsigned long
+timer_tol(TIMEVAL a)
+{
+ unsigned long timer;
+ timer = a.tv_sec * TIMER_HZ + a.tv_usec;
+ return timer;
+}
+
*
* Part: timer.c include file.
*
- * Version: $Id: timer.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: timer.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
extern int timer_cmp(TIMEVAL a, TIMEVAL b);
extern TIMEVAL timer_sub(TIMEVAL a, TIMEVAL b);
extern TIMEVAL timer_sub_now(TIMEVAL a);
+extern void timer_dump(TIMEVAL a);
+extern unsigned long timer_tol(TIMEVAL a);
#endif
*
* Part: General program utils.
*
- * Version: $Id: utils.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: utils.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: utils.h include file.
*
- * Version: $Id: utils.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: utils.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Vector structure manipulation.
*
- * Version: $Id: vector.c,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vector.c,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vector.c include file.
*
- * Version: $Id: vector.h,v 0.7.1 2002/09/17 22:03:31 acassen Exp $
+ * Version: $Id: vector.h,v 0.7.6 2002/11/20 21:34:18 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*