* keepalived-0.5.3 released.
* Added autoconf / automake generic scripts.
* Rewrite the configuration file stream parser.
Using a generic keywords tree. Each keyword refer a specific
stream handler. The main stream processor is a multilevel
recursive function getting file stream and backtracking the
keyword tree. Kind of global compiler structure using event driven
stream processing.
* Re-design the global data structure to be much more generic and
to dissociate LVS configuration related to checkers related. Remove
static char lenght to use dynamic length strings.
* Created a global timer framework.
* Created a global vector template, used in cofiguration file
parsing (both stream process & keywords tree generation).
* Created a global list template, used in most of the code.
* Review the global scheduler to remove repeated code.
* Created a global checkers API. The design and goal here is to
facilitate new checkers creation by localizing specific checker
code into a single file without any other global framework
integration.
* Patched a SSL stream handling race condition finding end of stream.
* Jan Holmberg, review MISC checker to use forked process to not degrade
global scheduler timer.
* Revisited the whole code to use new templates structures.
* Fixed a url lentgh bug into the genhash utility.
* Fabrice Bucher, <fabrice.bucher@urbanet.ch> fixed a timeout_persistence
bug in the IPVS wrapper code.
* Bradley McLean, <bradlist@bradm.net> added support to '0' port number
service in VS manipulation. Useful for balancing all services (host rather
than service).
* Matthijs van der Klip, <matthijs.van.der.klip@nos.nl> enhanced smtp
framework to use SMTP header and email enclosed with angle brackets.
-Alexandre Cassen <acassen@linux-vs.org>
+Alexandre Cassen, <acassen@linux-vs.org>
+2002-02-25 Alexandre Cassen <acassen@linux-vs.org>
+ * keepalived-0.5.3 released.
+ * Added autoconf / automake generic scripts.
+ * Rewrite the configuration file stream parser.
+ Using a generic keywords tree. Each keyword refer a specific
+ stream handler. The main stream processor is a multilevel
+ recursive function getting file stream and backtracking the
+ keyword tree. Kind of global compiler structure using event driven
+ stream processing.
+ * Re-design the global data structure to be much more generic and
+ to dissociate LVS configuration related to checkers related. Remove
+ static char lenght to use dynamic length strings.
+ * Created a global timer framework.
+ * Created a global vector template, used in cofiguration file
+ parsing (both stream process & keywords tree generation).
+ * Created a global list template, used in most of the code.
+ * Review the global scheduler to remove repeated code.
+ * Created a global checkers API. The design and goal here is to
+ facilitate new checkers creation by localizing specific checker
+ code into a single file without any other global framework
+ integration.
+ * Patched a SSL stream handling race condition finding end of stream.
+ * Jan Holmberg, review MISC checker to use forked process to not degrade
+ global scheduler timer.
+ * Revisited the whole code to use new templates structures.
+ * Fixed a url lentgh bug into the genhash utility.
+ * Fabrice Bucher, <fabrice.bucher@urbanet.ch> fixed a timeout_persistence
+ bug in the IPVS wrapper code.
+ * Bradley McLean, <bradlist@bradm.net> added support to '0' port number
+ service in VS manipulation. Useful for balancing all services (host rather
+ than service).
+ * Matthijs van der Klip, <matthijs.van.der.klip@nos.nl> enhanced smtp
+ framework to use SMTP header and email enclosed with angle brackets.
+
2001-12-20 Alexandre Cassen <acassen@linux-vs.org>
* keepalived-0.4.9a released.
* Jan and I patched a memory pointer problems in vrrp_scheduler.c
Routing messages
LinuxVirtualServer
+ Keepalived support all LVS code : including IPVS code for kernel 2.2
+ and kernel 2.4
+
Library needing
===============
1. uncompress the tarball
2. cd into the directory
- 3. 'make' and 'make install'. This will install
- keepalived into your system (binary and configuration file).
- 4. cd into genhash directory (read the INSTALL file).
- 5. 'make' and 'make install'. This will install
- the MD5 url digest generator. You need it to configure HTTP GET check
- and SSL GET check in order to compute MD5SUM digest etalon.
+ 3. './configure'
+ 4. 'make'
+ 5. 'make install'. This will install keepalived on your system,
+ binaries and configuration file :
+ * keepalived : The keepalived daemon program.
+ * genhash : The MD5 url digest generator. You need it to
+ configure HTTP GET check and SSL GET check in
+ order to compute MD5SUM digest etalon.
+ * /etc/keepalived/keepalived.conf
6. link keepalived.init into your runlevel directory. On redhat systems :
ln -s /etc/rc.d/init.d/keepalived.init /etc/rc.d/rc3.d/S99keepalived
+ By default configure script use /usr/local as base directory. You can change
+ this value to your own by passing --prefix value to configure script
+
+ eg: './configure --prefix=/usr/'
+
Configuration
=============
Have fun with it !
-Alexandre
+
+Alexandre, <acassen@linux-vs.org>
+++ /dev/null
-# Makefile
-# Alexandre Cassen <acassen@linux-vs.org>
-
-EXEC = keepalived
-CC = gcc
-
-KERNEL := _KRNL_2_$(shell uname -r | cut -d'.' -f2)_
-
-# To compile with debug messages uncomment the following line
-CFLAGS= -g -O6 -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
-# CFLAGS= -g -Wall -O6 -D$(KERNEL) $(SSL)
-DEFS=
-
-SSL := -lssl -lcrypto
-LIB := $(LIB) $(SSL) -lpopt
-
-ifeq ($(KERNEL),_KRNL_2_2_)
- LIB := $(LIB) libipfwc/libipfwc.a
-endif
-
-DEFS= main.h \
- memory.h \
- scheduler.h \
- cfreader.h \
- layer4.h \
- check_tcp.h \
- check_http.h \
- check_ssl.h \
- check_misc.h \
- vrrp.h \
- vrrp_scheduler.h \
- vrrp_netlink.h \
- vrrp_ipaddress.h \
- vrrp_ipsecah.h \
- smtp.h
-
-OBJECTS := main.o \
- memory.o \
- utils.o \
- scheduler.o \
- cfreader.o \
- layer4.o \
- check_tcp.o \
- check_http.o \
- check_ssl.o \
- check_misc.o \
- ipwrapper.o \
- ipvswrapper.o
-ifeq ($(KERNEL),_KRNL_2_2_)
- OBJECTS := $(OBJECTS) ipfwwrapper.o
-endif
-OBJECTS := $(OBJECTS) \
- pidfile.o \
- smtp.o \
- vrrp.o \
- vrrp_scheduler.o \
- vrrp_netlink.o \
- vrrp_ipaddress.o \
- vrrp_ipsecah.o
-
-INCLUDE= -I/usr/src/linux/include
-
-.c.o:
- $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
-
-all: $(EXEC)
- strip $(EXEC)
- @echo ""
- @echo "Make complete"
-
-debug: $(EXEC)
- @echo""
- @echo "Make complete"
-
-$(EXEC): $(OBJECTS) $(DEFS) $(LIB)
- $(CC) -o $(EXEC) $(CFLAGS) $(OBJECTS) $(LIB)
-
-ifeq ($(KERNEL),_KRNL_2_2_)
-libipfwc/libipfwc.a:
- cd libipfwc/ && $(MAKE) libipfwc.a
-endif
-
-subclean:
-ifeq ($(KERNEL),_KRNL_2_2_)
- cd libipfwc/ && $(MAKE) clean
-endif
-
-clean: subclean
- rm -f core *.o $(EXEC)
-
-install:
- install -m 700 keepalived /usr/sbin/
- install -m 755 etc/rc.d/init.d/keepalived.init /etc/rc.d/init.d/
- mkdir /etc/keepalived
- install -m 644 etc/keepalived/keepalived.conf /etc/keepalived/
- mkdir /etc/keepalived/samples
- install -m 644 samples/* /etc/keepalived/samples/
-
--- /dev/null
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = keepalived
+KERNEL := _KRNL_2_$(shell uname -r | cut -d'.' -f2)_
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sbindir = @sbindir@
+
+init_dir = /etc/rc.d/init.d
+init_script = keepalived.init
+src_init_script = etc/rc.d/init.d/$(init_script)
+src_conf_file = etc/keepalived/keepalived.conf
+keepalived_conf_dir = /etc/keepalived
+
+CC = @CC@
+CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes -D_DEBUG_ -D$(KERNEL)
+LDFLAGS = @LIBS@ @LDFLAGS@
+OBJS = @LIBOBJS@ \
+ main.o \
+ memory.o \
+ daemon.o \
+ utils.o \
+ timer.o \
+ scheduler.o \
+ vector.o \
+ list.o \
+ data.o \
+ parser.o \
+ layer4.o \
+ check_api.o \
+ check_tcp.o \
+ check_http.o \
+ check_ssl.o \
+ check_misc.o \
+ ipwrapper.o \
+ ipvswrapper.o \
+ pidfile.o \
+ smtp.o \
+ vrrp.o \
+ vrrp_scheduler.o \
+ vrrp_netlink.o \
+ vrrp_ipaddress.o \
+ vrrp_ipsecah.o
+
+INCLUDE= -I/usr/src/linux/include
+
+.c.o:
+ $(CC) -o $@ $(CFLAGS) $(INCLUDE) -c $*.c
+
+all: $(EXEC)
+ strip $(EXEC)
+ @echo ""
+ cd genhash && $(MAKE)
+ @echo ""
+ @echo "Make complete"
+
+debug: $(EXEC)
+ @echo ""
+ @echo "Make complete"
+
+$(EXEC): $(OBJS) $(LDFLAGS)
+ $(CC) -o $(EXEC) $(CFLAGS) $(OBJS) $(LDFLAGS)
+
+libipfwc/libipfwc.a:
+ cd libipfwc/ && $(MAKE) libipfwc.a
+
+subclean:
+ifeq ($(KERNEL),_KRNL_2_2_)
+ cd libipfwc/ && $(MAKE) clean
+endif
+ cd genhash/ && $(MAKE) clean
+
+clean: subclean
+ rm -f core *.o $(EXEC)
+
+subclean-dist:
+ cd genhash/ && $(MAKE) clean-dist
+
+clean-dist: subclean-dist
+ rm -f $(sbindir)/$(EXEC)
+ rm -rf $(keepalived_conf_dir)
+ rm -f $(init_dir)/$(init_script)
+
+mrproper: clean clean-dist
+ rm -f config.*
+ rm -f Makefile
+ rm -f genhash/Makefile
+
+subinstall:
+ cd genhash/ && $(MAKE) install
+
+install: subinstall
+ install -m 700 $(EXEC) $(sbindir)/
+ install -m 755 $(src_init_script) $(init_dir)/
+ mkdir $(keepalived_conf_dir)
+ install -m 644 $(src_conf_file) $(keepalived_conf_dir)
+ mkdir $(keepalived_conf_dir)/samples
+ install -m 644 samples/* $(keepalived_conf_dir)/samples/
-* Synchronize IPVS topology with VRRP synchronization events.
* Insert LDAP, FTP, SSH, IMAP, POP, RADIUS checkers.
-* Replave some unfixed len strcat & sprintf
* Add minimum configuration verification (realserver must have
a checker defined, ...)
* Add system verification (must have LVS support in kernel,
+++ /dev/null
-/*
- * Soft: Keepalived is a failover program for the LVS project
- * <www.linuxvirtualserver.org>. It monitor & manipulate
- * a loadbalanced server pool using multi-layer checks.
- *
- * Part: Configuration file parser/reader. Place into the dynamic
- * data structure representation the conf file representing
- * the loadbalanced server pool.
- *
- * Version: $Id: cfreader.c,v 0.4.9a 2001/12/20 17:14:25 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.
- */
-
-#include "cfreader.h"
-#include "memory.h"
-
-/* Global keyword structure defs */
-char *string; /* Temp read buffer */
-
-struct keyword keywords[] = {
- {KW_BEGINFLAG, "{"},
- {KW_ENDFLAG, "}"},
-
- {KW_GLOBALDEFS, "global_defs"},
- {KW_EMAIL, "notification_email"},
- {KW_EMAILFROM, "notification_email_from"},
- {KW_LVSID, "lvs_id"},
- {KW_SMTP, "smtp_server"},
- {KW_STIMEOUT, "smtp_connect_timeout"},
-
- {KW_VS, "virtual_server"},
- {KW_DELAY, "delay_loop"},
- {KW_LBSCHED, "lb_algo"},
- {KW_LBKIND, "lb_kind"},
- {KW_NATMASK, "nat_mask"},
- {KW_PTIMEOUT, "persistence_timeout"},
- {KW_PROTOCOL, "protocol"},
- {KW_SSVR, "sorry_server"},
- {KW_FWMARK, "fwmark"},
-
- {KW_SVR, "real_server"},
- {KW_WEIGHT, "weight"},
- {KW_CTIMEOUT, "connect_timeout"},
- {KW_URL, "url"},
- {KW_URLPATH, "path"},
- {KW_DIGEST, "digest"},
- {KW_NBGETRETRY, "nb_get_retry"},
- {KW_DELAYRETRY, "delay_before_retry"},
-
- {KW_ICMPCHECK, "ICMP_CHECK"},
- {KW_TCPCHECK, "TCP_CHECK"},
- {KW_HTTPGET, "HTTP_GET"},
- {KW_SSLGET, "SSL_GET"},
- {KW_LDAPGET, "LDAP_GET"},
-
- {KW_MISCCHECK, "MISC_CHECK"},
- {KW_MISCPATH, "misc_path"},
-
- {KW_VRRP, "vrrp_instance"},
- {KW_VRRPSTATE, "state"},
- {KW_VRRPINT, "interface"},
- {KW_VRRPVRID, "virtual_router_id"},
- {KW_VRRPAUTH, "authentication"},
- {KW_VRRPAUTHTYPE, "auth_type"},
- {KW_VRRPAUTHAH, "AH"},
- {KW_VRRPAUTHPWD, "PASS"},
- {KW_VRRPAUTHPASS, "auth_pass"},
- {KW_VRRPPRIO, "priority"},
- {KW_VRRPADVERT, "advert_int"},
- {KW_VRRPIPADD, "virtual_ipaddress"},
- {KW_VRRPSYNC, "sync_instance"},
- {KW_VRRPPREEMPT, "preempt"},
- {KW_VRRPDEBUG, "debug"},
- {KW_VRRPNOTIFY, "notify"},
-
- {KW_SSLPASSWORD, "password"},
- {KW_SSLCAFILE, "ca"},
- {KW_SSLCERTFILE, "certificate"},
- {KW_SSLKEYFILE, "key"},
- {KW_SSL, "SSL"},
-
- {KW_UNKNOWN, NULL}
-};
-
-int key(const char *word)
-{
- int i;
-
- for (i=0; keywords[i].word; i++)
- if (strcmp(word, keywords[i].word) == 0)
- return keywords[i].key;
-
- return KW_UNKNOWN;
-}
-
-/* Dynamic data structure creation functions start here */
-int already_exist_vs(virtualserver *lstptr, uint32_t ip, uint16_t port)
-{
- virtualserver *pointerptr=lstptr;
-
- while(lstptr != NULL) {
- if((lstptr->addr_ip.s_addr == ip) && (lstptr->addr_port == port)) {
- lstptr = pointerptr;
- return 1;
- }
- lstptr = (virtualserver *)lstptr->next;
- }
- lstptr = pointerptr;
- return 0;
-}
-
-int already_exist_svr(realserver *lstptr, uint32_t ip, uint16_t port)
-{
- realserver *pointerptr=lstptr;
-
- while(lstptr != NULL) {
- if((lstptr->addr_ip.s_addr == ip) && (lstptr->addr_port == port)) {
- lstptr = pointerptr;
- return 1;
- }
- lstptr = (realserver *)lstptr->next;
- }
- lstptr = pointerptr;
- return 0;
-}
-
-vrrp_instance * add_item_vrrp(vrrp_instance *lstvrrp, vrrp_instance *vrrp)
-{
- vrrp_instance *pointerlst = lstvrrp;
-
- if (lstvrrp != NULL) {
- while(lstvrrp->next != NULL) lstvrrp = (vrrp_instance *)lstvrrp->next;
- lstvrrp->next = (struct vrrp_instance *)vrrp;
- return pointerlst;
- } else {
- lstvrrp = vrrp;
- return lstvrrp;
- }
-}
-
-notification_email * add_item_email(notification_email *lstemail,notification_email *email)
-{
- notification_email *pointerlst = lstemail;
-
- if (lstemail != NULL) {
- while(lstemail->next != NULL) lstemail = (notification_email *)lstemail->next;
- lstemail->next = (struct notification_email *)email;
- return pointerlst;
- } else {
- lstemail = email;
- return lstemail;
- }
-}
-
-virtualserver * add_item_vs(virtualserver *lstvs,virtualserver *vs)
-{
- virtualserver *pointerlst = lstvs;
-
- if(already_exist_vs(lstvs, vs->addr_ip.s_addr, vs->addr_port)) return lstvs;
-
- if (lstvs != NULL) {
- while(lstvs->next != NULL) lstvs = (virtualserver *)lstvs->next;
- lstvs->next = (struct virtualserver *)vs;
- return pointerlst;
- } else {
- lstvs = vs;
- return lstvs;
- }
-}
-
-realserver * add_item_svr(realserver *lstsvr,realserver *svr)
-{
- realserver *pointerlst = lstsvr;
-
- if(already_exist_svr(lstsvr, svr->addr_ip.s_addr, svr->addr_port)) return lstsvr;
-
- if (lstsvr != NULL) {
- while(lstsvr->next != NULL) lstsvr = (realserver *)lstsvr->next;
- lstsvr->next = (struct realserver *)svr;
- return pointerlst;
- } else {
- lstsvr = svr;
- return lstsvr;
- }
-}
-
-urls * add_item_url(urls *lsturls,urls *url)
-{
- urls *pointerlst = lsturls;
-
- if (lsturls != NULL) {
- while(lsturls->next != NULL) lsturls = (urls *)lsturls->next;
- lsturls->next = (struct urls *)url;
- return pointerlst;
- } else {
- lsturls = url;
- return lsturls;
- }
-}
-
-/* Dynamic data structure cleanup functions start here */
-urls * remove_url(urls * lstptr)
-{
- urls *t;
-
- t = (urls *)lstptr->next;
- FREE(lstptr);
- return t;
-}
-
-realserver * remove_svr(realserver * lstptr)
-{
- realserver *t;
-
- t = (realserver *)lstptr->next;
-
- if(lstptr->method->u.http_get != NULL) {
- while(lstptr->method->u.http_get->check_urls != NULL)
- lstptr->method->u.http_get->check_urls = remove_url(lstptr->method->u.http_get->check_urls);
- FREE(lstptr->method->u.http_get);
- }
-
- FREE(lstptr->method);
- FREE(lstptr);
- return t;
-}
-
-virtualserver * remove_vs(virtualserver * lstptr)
-{
- virtualserver *t;
-
- t = (virtualserver *)lstptr->next;
- while(lstptr->svr != NULL) lstptr->svr = remove_svr(lstptr->svr);
-
- if (lstptr->s_svr)
- FREE(lstptr->s_svr);
- FREE(lstptr);
- return t;
-}
-
-vrrp_instance *remove_vrrp(vrrp_instance *lstptr)
-{
- vrrp_instance *t;
-
- t = (vrrp_instance *)lstptr->next;
- FREE(lstptr->vsrv->vaddr);
- FREE(lstptr->vsrv->ipsecah_counter);
- FREE(lstptr->vsrv->vif);
- FREE(lstptr->vsrv);
- FREE(lstptr);
- return t;
-}
-
-notification_email * remove_email(notification_email *lstptr)
-{
- notification_email *t;
-
- t = (notification_email *)lstptr->next;
- FREE(lstptr);
- return t;
-}
-
-void clear_conf(configuration_data * lstptr)
-{
- while(lstptr->email != NULL)
- lstptr->email = remove_email(lstptr->email);
-
- while(lstptr->vrrp != NULL)
- lstptr->vrrp = remove_vrrp(lstptr->vrrp);
-
- while(lstptr->lvstopology != NULL)
- lstptr->lvstopology = remove_vs(lstptr->lvstopology);
-
- /* All SSL GET use the same shared SSL context */
- if (lstptr->ssldata)
- FREE(lstptr->ssldata);
-
- FREE(lstptr);
-}
-
-void clear_vrrp_instance(vrrp_instance *lstptr)
-{
- while (lstptr) {
- vrrp_state_stop_instance(lstptr->vsrv);
- lstptr = (vrrp_instance *)lstptr->next;
- }
-}
-
-/* Dynamic data structure dump functions start here */
-void dump_httpget(http_get_check *pointerhttpget)
-{
- urls *pointerurls;
-
- syslog(LOG_INFO," -> Nb get retry = %d",
- pointerhttpget->nb_get_retry);
- syslog(LOG_INFO," -> Delay before retry = %d",
- pointerhttpget->delay_before_retry);
-
- pointerurls = pointerhttpget->check_urls;
- while(pointerhttpget->check_urls) {
- syslog(LOG_INFO," -> Url = %s, Digest = %s",
- pointerhttpget->check_urls->url,
- pointerhttpget->check_urls->digest);
-
- pointerhttpget->check_urls = (urls *)pointerhttpget->check_urls->next;
- }
- pointerhttpget->check_urls = pointerurls;
-}
-
-void dump_svr(realserver *pointersvr)
-{
- while(pointersvr != NULL) {
- syslog(LOG_INFO," -> SVR IP = %s, PORT = %d, WEIGHT = %d",
- inet_ntoa(pointersvr->addr_ip),
- ntohs(pointersvr->addr_port),
- pointersvr->weight);
-
- switch (pointersvr->method->type) {
- case ICMP_CHECK_ID: /* no more implemented... */
- syslog(LOG_INFO," -> Keepalive method = ICMP_CHECK");
- break;
- case TCP_CHECK_ID:
- syslog(LOG_INFO," -> Keepalive method = TCP_CHECK");
- syslog(LOG_INFO," -> Connection timeout = %d",
- pointersvr->method->connection_to);
- break;
- case HTTP_GET_ID:
- syslog(LOG_INFO," -> Keepalive method = HTTP_GET");
- syslog(LOG_INFO," -> Connection timeout = %d",
- pointersvr->method->connection_to);
- dump_httpget(pointersvr->method->u.http_get);
- break;
- case SSL_GET_ID:
- syslog(LOG_INFO," -> Keepalive method = SSL_GET");
- syslog(LOG_INFO," -> Connection timeout = %d",
- pointersvr->method->connection_to);
- dump_httpget(pointersvr->method->u.http_get);
- break;
- case LDAP_GET_ID:
- break;
- case MISC_CHECK_ID:
- syslog(LOG_INFO," -> Keepalive method = MISC_CHECK");
- syslog(LOG_INFO," -> Check path = %s",
- pointersvr->method->u.misc_check_path);
- break;
- }
-
- pointersvr = (realserver *)pointersvr->next;
- }
-}
-
-void dump_vs(virtualserver *pointervs)
-{
- while(pointervs != NULL) {
- if (pointervs->vfwmark) {
- syslog(LOG_INFO, " VS FWMARK = %d"
- , pointervs->vfwmark);
- } else {
- syslog(LOG_INFO, " VS IP = %s, PORT = %d"
- , inet_ntoa(pointervs->addr_ip)
- , ntohs(pointervs->addr_port));
- }
- syslog(LOG_INFO, " -> delay_loop = %d, lb_algo = %s, "
- "persistence = %s, protocol = %s",
- pointervs->delay_loop, pointervs->sched,
- pointervs->timeout_persistence,
- (pointervs->service_type == IPPROTO_TCP)?"TCP":"UDP");
-
- switch (pointervs->loadbalancing_kind) {
-#ifdef _KRNL_2_2_
- case 0:
- syslog(LOG_INFO, " -> lb_kind = NAT");
- syslog(LOG_INFO, " -> nat mask = %s", inet_ntoa(pointervs->nat_mask));
- break;
- case IP_MASQ_F_VS_DROUTE:
- syslog(LOG_INFO, " -> lb_kind = DR");
- break;
- case IP_MASQ_F_VS_TUNNEL:
- syslog(LOG_INFO, " -> lb_kind = TUN");
- break;
-#else
- case IP_VS_CONN_F_MASQ:
- syslog(LOG_INFO, " -> lb_kind = NAT");
- break;
- case IP_VS_CONN_F_DROUTE:
- syslog(LOG_INFO, " -> lb_kind = DR");
- break;
- case IP_VS_CONN_F_TUNNEL:
- syslog(LOG_INFO, " -> lb_kind = TUN");
- break;
-#endif
- }
-
- if (pointervs->s_svr != NULL) {
- syslog(LOG_INFO, " -> sorry server = [%s:%d]"
- , inet_ntoa(pointervs->s_svr->addr_ip)
- , ntohs(pointervs->s_svr->addr_port));
- }
-
- dump_svr(pointervs->svr);
-
- pointervs = (virtualserver *)pointervs->next;
- }
-}
-
-void dump_email(notification_email *pointeremail)
-{
- while(pointeremail != NULL) {
- syslog(LOG_INFO," Email notification = %s", pointeremail->addr);
-
- pointeremail = (notification_email *)pointeremail->next;
- }
-}
-
-void dump_vrrp(vrrp_instance *pointervrrp)
-{
- int i;
-
- while (pointervrrp != NULL) {
- syslog(LOG_INFO, " VRRP Instance = %s", pointervrrp->iname);
- if (pointervrrp->vsrv->init_state == VRRP_STATE_BACK)
- syslog(LOG_INFO, " Want State = BACKUP");
- else
- syslog(LOG_INFO, " Want State = MASTER");
- syslog(LOG_INFO, " Device = %s", pointervrrp->vsrv->vif->ifname);
- if (strlen(pointervrrp->isync) > 0)
- syslog(LOG_INFO, " Sync with instance = %s", pointervrrp->isync);
- syslog(LOG_INFO, " Virtual Router ID = %d", pointervrrp->vsrv->vrid);
- syslog(LOG_INFO, " Priority = %d", pointervrrp->vsrv->priority);
- syslog(LOG_INFO, " Advert interval = %dsec",
- pointervrrp->vsrv->adver_int/VRRP_TIMER_HZ);
- if (pointervrrp->vsrv->preempt)
- syslog(LOG_INFO, " Preempt active");
- if (pointervrrp->vsrv->vif->auth_type) {
- syslog(LOG_INFO, " Authentication type = %s",
- (pointervrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
- syslog(LOG_INFO, " Password = %s", pointervrrp->vsrv->vif->auth_data);
- }
- syslog(LOG_INFO, " VIP count = %d", pointervrrp->vsrv->naddr);
- for (i = 0; i<pointervrrp->vsrv->naddr; i++)
- syslog(LOG_INFO, " VIP%d = %s", i+1, ip_ntoa(ntohl(pointervrrp->vsrv->vaddr[i].addr)));
-
- pointervrrp = (vrrp_instance *)pointervrrp->next;
- }
-}
-
-void dump_conf(configuration_data *lstconf)
-{
- if (lstconf == NULL) {
- syslog(LOG_INFO, "Empty data configuration !!!");
- } else {
- syslog(LOG_INFO, "------< Global definitions >------");
- syslog(LOG_INFO, " LVS ID = %s",lstconf->lvs_id);
- syslog(LOG_INFO, " Smtp server = %s", inet_ntoa(lstconf->smtp_server));
- syslog(LOG_INFO, " Smtp server connection timeout = %d", lstconf->smtp_connection_to);
- syslog(LOG_INFO, " Email notification from = %s", lstconf->email_from);
- dump_email(lstconf->email);
-
- if (lstconf->ssldata) {
- syslog(LOG_INFO, "------< SSL definitions >------");
- if (strlen(lstconf->ssldata->password) > 0)
- syslog(LOG_INFO, " Password: %s", lstconf->ssldata->password);
- if (strlen(lstconf->ssldata->cafile) > 0)
- syslog(LOG_INFO, " CA-file: %s", lstconf->ssldata->cafile);
- if (strlen(lstconf->ssldata->certfile) > 0)
- syslog(LOG_INFO, " Certificate file: %s", lstconf->ssldata->certfile);
- if (strlen(lstconf->ssldata->keyfile) > 0)
- syslog(LOG_INFO, " Key file: %s", lstconf->ssldata->keyfile);
- if (!strlen(lstconf->ssldata->keyfile) &&
- !strlen(lstconf->ssldata->certfile) &&
- !strlen(lstconf->ssldata->cafile) &&
- !strlen(lstconf->ssldata->password))
- syslog(LOG_INFO, " Using autogen SSL context");
- }
-
- if (lstconf->vrrp) {
- syslog(LOG_INFO, "------< VRRP Topology >------");
- dump_vrrp(lstconf->vrrp);
- }
-
- if (lstconf->lvstopology) {
- syslog(LOG_INFO, "------< LVS Topology >------");
- dump_vs(lstconf->lvstopology);
- }
- }
-}
-
-/* Dynamic data structure stream processing functions start here */
-void process_stream_icmpcheck(FILE *stream, realserver *svrfill)
-{
- keepalive_check *methodfill;
-
- /* Allocate new method structure */
- methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
- methodfill->type = ICMP_CHECK_ID;
- methodfill->u.http_get = NULL;
-
- svrfill->method = methodfill;
-}
-
-void process_stream_tcpcheck(FILE *stream, realserver *svrfill)
-{
- keepalive_check *methodfill;
-
- /* Allocate new method structure */
- methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
- methodfill->type = TCP_CHECK_ID;
- methodfill->u.http_get = NULL;
-
- do {
- switch (key(string)) {
- case KW_CTIMEOUT:
- fscanf(stream, "%d", &methodfill->connection_to);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- svrfill->method = methodfill;
-}
-
-void process_stream_misccheck(FILE *stream, realserver *svrfill)
-{
- keepalive_check *methodfill;
- char* pathstring = (char*)MALLOC(512);
-
- /* Allocate new method structure */
- methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
- methodfill->type = MISC_CHECK_ID;
- methodfill->u.misc_check_path = NULL;
-
- do {
- switch (key(string)) {
- case KW_CTIMEOUT:
- fscanf(stream, "%d", &methodfill->connection_to);
- break;
- case KW_MISCPATH:
- fgets(pathstring,512,stream);
- methodfill->u.misc_check_path=pathstring;
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- svrfill->method = methodfill;
-}
-
-void process_stream_url(FILE *stream, http_get_check *httpgetfill)
-{
- urls *urlfill;
-
- /* Allocate new url structure */
- urlfill = (urls *)MALLOC(sizeof(urls));
-
- urlfill->next = NULL;
-
- do {
- switch (key(string)) {
- case KW_URLPATH:
- fscanf(stream, "%s", urlfill->url);
- break;
- case KW_DIGEST:
- fscanf(stream, "%s", urlfill->digest);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- httpgetfill->check_urls = add_item_url(httpgetfill->check_urls, urlfill);
-}
-
-void process_stream_httpget(FILE *stream, realserver *svrfill, int type)
-{
- keepalive_check *methodfill;
- http_get_check *httpgetfill;
-
- /* Allocate new method structure */
- methodfill = (keepalive_check *)MALLOC(sizeof(keepalive_check));
-
- /* Allocate new http get structure */
- httpgetfill = (http_get_check *)MALLOC(sizeof(http_get_check));
-
- methodfill->type = type;
- methodfill->u.http_get = httpgetfill;
-
- httpgetfill->check_urls = NULL;
-
- do {
- switch (key(string)) {
- case KW_CTIMEOUT:
- fscanf(stream, "%d", &methodfill->connection_to);
- break;
- case KW_NBGETRETRY:
- fscanf(stream, "%d", &httpgetfill->nb_get_retry);
- break;
- case KW_DELAYRETRY:
- fscanf(stream, "%d", &httpgetfill->delay_before_retry);
- break;
- case KW_URL:
- process_stream_url(stream, httpgetfill);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- svrfill->method = methodfill;
-}
-
-void process_stream_svr(FILE *stream, virtualserver *vsfill)
-{
- realserver *svrfill;
-
- /* Allocate new real server structure */
- svrfill = (realserver *)MALLOC(sizeof(realserver));
-
- /* Add the real server allocated to the virtual server
- * data structure.
- */
- svrfill->next = NULL; /* not required */
- svrfill->alive = 1; /* server is alive */
- vsfill->svr = add_item_svr(vsfill->svr, svrfill);
-
- fscanf(stream, "%s", string);
- svrfill->addr_ip.s_addr = inet_addr(string);
- fscanf(stream, "%s", string);
- svrfill->addr_port = htons(atoi(string));
-
- do {
- switch (key(string)) {
- case KW_WEIGHT:
- fscanf(stream, "%d", &svrfill->weight);
- break;
- case KW_ICMPCHECK:
- process_stream_icmpcheck(stream, svrfill);
- break;
- case KW_TCPCHECK:
- process_stream_tcpcheck(stream, svrfill);
- break;
- case KW_HTTPGET:
- process_stream_httpget(stream, svrfill, HTTP_GET_ID);
- break;
- case KW_SSLGET:
- process_stream_httpget(stream, svrfill, SSL_GET_ID);
- break;
- case KW_LDAPGET: /* not yet implemented */
- break;
- case KW_MISCCHECK:
- process_stream_misccheck(stream, svrfill);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_ssvr(FILE *stream, virtualserver *vsfill)
-{
- realserver *ssvrfill;
-
- /* Allocate new sorry server structure */
- ssvrfill = (realserver *)MALLOC(sizeof(realserver));
-
- /* direct affectation, we can use add_item_svr, so
- * can specify more than 1 sorry_server...
- * Not really needed !
- */
- vsfill->s_svr = ssvrfill;
-
- ssvrfill->alive = 0;
- ssvrfill->weight = 1;
- ssvrfill->method = NULL;
- ssvrfill->next = NULL;
-
- fscanf(stream, "%s", string);
- ssvrfill->addr_ip.s_addr = inet_addr(string);
- fscanf(stream, "%s", string);
- ssvrfill->addr_port = htons(atoi(string));
-}
-
-void process_stream_vs(FILE *stream, configuration_data *conf_data)
-{
- virtualserver *vsfill;
-
- /* Allocate new virtual server structure */
- vsfill = (virtualserver *)MALLOC(sizeof(virtualserver));
-
- /* Add the virtual server allocated to the configuration
- * data structure.
- */
- vsfill->next = NULL; /* not required */
- vsfill->s_svr = NULL;
- conf_data->lvstopology = add_item_vs(conf_data->lvstopology, vsfill);
-
- fscanf(stream, "%s", string);
- if (!strcmp(string, "fwmark")) {
- fscanf(stream, "%s", string);
- vsfill->vfwmark = atoi(string);
- } else {
- vsfill->vfwmark = 0;
- vsfill->addr_ip.s_addr = inet_addr(string);
- fscanf(stream, "%s", string);
- vsfill->addr_port = htons(atoi(string));
- }
-
- /* Setting default value */
- vsfill->delay_loop = KEEPALIVED_DEFAULT_DELAY;
-
- do {
- switch (key(string)) {
- case KW_DELAY:
- fscanf(stream, "%d", &vsfill->delay_loop);
- break;
- case KW_LBSCHED:
- fscanf(stream, "%s", vsfill->sched);
- break;
- case KW_LBKIND:
- fscanf(stream, "%s", string);
-
-#ifdef _KRNL_2_2_
- if (strcmp(string, "NAT") == 0)
- vsfill->loadbalancing_kind = 0;
- else
- if (strcmp(string, "DR") == 0)
- vsfill->loadbalancing_kind = IP_MASQ_F_VS_DROUTE;
- else
- if (strcmp(string, "TUN") == 0)
- vsfill->loadbalancing_kind = IP_MASQ_F_VS_TUNNEL;
- else
- syslog(LOG_DEBUG,"CFREADER : unknown [%s] routing method."
- , string);
-#else
- if (strcmp(string, "NAT") == 0)
- vsfill->loadbalancing_kind = IP_VS_CONN_F_MASQ;
- else
- if (strcmp(string, "DR") == 0)
- vsfill->loadbalancing_kind = IP_VS_CONN_F_DROUTE;
- else
- if (strcmp(string, "TUN") == 0)
- vsfill->loadbalancing_kind = IP_VS_CONN_F_TUNNEL;
- else
- syslog(LOG_DEBUG,"CFREADER : unknown [%s] routing method."
- , string);
-#endif
-
- break;
- case KW_NATMASK:
- fscanf(stream, "%s", string);
- vsfill->nat_mask.s_addr = inet_addr(string);
- break;
- case KW_PTIMEOUT:
- fscanf(stream, "%s", vsfill->timeout_persistence);
- break;
- case KW_PROTOCOL:
- fscanf(stream, "%s", string);
- vsfill->service_type = (strcmp(string,"TCP") == 0)?IPPROTO_TCP:IPPROTO_UDP;
- break;
- case KW_SSVR:
- process_stream_ssvr(stream, vsfill);
- break;
- case KW_SVR:
- process_stream_svr(stream, vsfill);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_email(FILE *stream, configuration_data *conf_data)
-{
- notification_email *emailfill;
-
- /* Fill in email liste */
- do {
- fscanf(stream, "%s", string);
- if(key(string) != KW_BEGINFLAG && key(string) != KW_ENDFLAG) {
- emailfill = (notification_email *)MALLOC(sizeof(notification_email));
- strncat(emailfill->addr, string, sizeof(emailfill->addr));
- emailfill->next = NULL;
- conf_data->email = add_item_email(conf_data->email, emailfill);
- }
- } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_globaldefs(FILE *stream, configuration_data *conf_data)
-{
- /* Fill in the global defs structure */
- do {
- switch (key(string)) {
- case KW_LVSID:
- fscanf(stream, "%s", conf_data->lvs_id);
- break;
- case KW_SMTP:
- fscanf(stream, "%s", string);
- conf_data->smtp_server.s_addr = inet_addr(string);
- break;
- case KW_STIMEOUT:
- fscanf(stream, "%d", &conf_data->smtp_connection_to);
- break;
- case KW_EMAILFROM:
- fscanf(stream, "%s", conf_data->email_from);
- break;
- case KW_EMAIL:
- process_stream_email(stream, conf_data);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-}
-
-int process_stream_ssl(FILE *stream, configuration_data *conf_data)
-{
- /* Fill in the global defs structure */
- do {
- switch (key(string)) {
- case KW_SSLPASSWORD:
- fscanf(stream, "%s", conf_data->ssldata->password);
- conf_data->ssldata->enable |= 1;
- break;
- case KW_SSLCAFILE:
- fscanf(stream, "%s", conf_data->ssldata->cafile);
- conf_data->ssldata->enable |= 2;
- break;
- case KW_SSLKEYFILE:
- fscanf(stream, "%s", conf_data->ssldata->keyfile);
- conf_data->ssldata->enable |= 4;
- break;
- case KW_SSLCERTFILE:
- fscanf(stream, "%s", conf_data->ssldata->certfile);
- conf_data->ssldata->enable |= 8;
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- return conf_data->ssldata->enable;
-}
-
-static void add_item_vrrp_vip(vrrp_rt *vsrv, uint32_t ipaddr)
-{
- vsrv->naddr++;
- /* alloc the room */
- if( vsrv->vaddr ){
- vsrv->vaddr = REALLOC(vsrv->vaddr, vsrv->naddr*sizeof(*vsrv->vaddr));
- } else {
- vsrv->vaddr = (vip_addr *)MALLOC(sizeof(*vsrv->vaddr));
- }
- /* store the data */
- vsrv->vaddr[vsrv->naddr-1].addr = ipaddr;
- vsrv->vaddr[vsrv->naddr-1].deletable = 0;
-}
-
-void process_stream_vrrp_ipaddress(FILE *stream, vrrp_rt *vrrp)
-{
- uint32_t ipaddr;
-
- do {
- fscanf(stream, "%s", string);
- if(key(string) != KW_BEGINFLAG && key(string) != KW_ENDFLAG) {
- ipaddr = inet_addr(string);
- add_item_vrrp_vip(vrrp, ntohl(ipaddr));
- }
- } while(key(string) != KW_ENDFLAG);
-}
-
-void process_stream_vrrp_auth(FILE *stream, vrrp_if *vif)
-{
- do {
- switch (key(string)) {
- case KW_VRRPAUTHTYPE:
- fscanf(stream, "%s", string);
- vif->auth_type = (key(string) == KW_VRRPAUTHAH)?VRRP_AUTH_AH:VRRP_AUTH_PASS;
- break;
- case KW_VRRPAUTHPASS:
- fscanf(stream, "%s", vif->auth_data);
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-}
-
-int process_stream_vrrp(FILE *stream, configuration_data *conf_data)
-{
- vrrp_instance *vrrpfill;
- vrrp_rt *rtfill;
- vrrp_if *viffill;
- seq_counter *counterfill;
-
- /* Allocate new VRRP structure */
- vrrpfill = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
- rtfill = (vrrp_rt *) MALLOC(sizeof(vrrp_rt));
- viffill = (vrrp_if *) MALLOC(sizeof(vrrp_if));
- counterfill = (seq_counter *) MALLOC(sizeof(seq_counter));
-
- /* Add the vrrp instance allocated to the configuration
- * data structure.
- */
- vrrpfill->vsrv = rtfill;
- vrrpfill->vsrv->vif = viffill;
- vrrpfill->vsrv->ipsecah_counter = counterfill;
- vrrpfill->vsrv->vaddr = NULL;
- vrrpfill->vsrv->vaddr = NULL;
- vrrpfill->next = NULL;
-
- /* default value */
- rtfill->wantstate = VRRP_STATE_BACK;
- rtfill->init_state = VRRP_STATE_BACK;
-
- conf_data->vrrp = add_item_vrrp(conf_data->vrrp, vrrpfill);
-
- fscanf(stream, "%s", vrrpfill->iname);
-
- /* Fill in the VRRP structure */
- do {
- switch (key(string)) {
- case KW_VRRPSYNC:
- fscanf(stream, "%s", vrrpfill->isync);
- break;
- case KW_VRRPSTATE:
- fscanf(stream, "%s", string);
- if (strcmp(string, "MASTER") == 0) {
- rtfill->wantstate = VRRP_STATE_MAST;
- rtfill->init_state = VRRP_STATE_MAST;
- } else {
- rtfill->wantstate = VRRP_STATE_BACK;
- rtfill->init_state = VRRP_STATE_BACK;
- }
- break;
- case KW_VRRPINT:
- fscanf(stream, "%s", viffill->ifname);
- break;
- case KW_VRRPVRID:
- fscanf(stream, "%d", &rtfill->vrid);
- if (VRRP_IS_BAD_VID(rtfill->vrid)) {
- syslog(LOG_DEBUG, "VRRP Error : VRID not valid !");
- syslog(LOG_DEBUG, "VRRP Error : must be between 1 & 255. reconfigure !");
- return 0;
- }
- break;
- case KW_VRRPPRIO:
- fscanf(stream, "%d", &rtfill->priority);
- if (VRRP_IS_BAD_PRIORITY(rtfill->priority)) {
- syslog(LOG_DEBUG, "VRRP Error : priority not valid !");
- syslog(LOG_DEBUG, "VRRP Error : must be between 1 & 255. reconfigure !");
- return 0;
- }
- break;
- case KW_VRRPADVERT:
- fscanf(stream, "%d", &rtfill->adver_int);
- if (VRRP_IS_BAD_ADVERT_INT(rtfill->adver_int)) {
- syslog(LOG_DEBUG, "VRRP Error : Advert intervall not valid !");
- syslog(LOG_DEBUG, "VRRP Error : must be between less than 1sec. reconfigure !");
- return 0;
- }
- rtfill->adver_int *= VRRP_TIMER_HZ;
- break;
- case KW_VRRPAUTH:
- process_stream_vrrp_auth(stream, viffill);
- break;
- case KW_VRRPIPADD:
- process_stream_vrrp_ipaddress(stream, rtfill);
- break;
- case KW_VRRPPREEMPT:
- rtfill->preempt = !rtfill->preempt;
- break;
- case KW_VRRPDEBUG:
- fscanf(stream, "%d", &rtfill->debug);
- if (VRRP_IS_BAD_DEBUG_INT(rtfill->debug)) {
- syslog(LOG_DEBUG, "VRRP Error : Debug intervall not valid !");
- syslog(LOG_DEBUG, "VRRP Error : must be between 0-4");
- return 0;
- }
- break;
- case KW_VRRPNOTIFY:
- fscanf(stream, "%s", rtfill->notify_file);
- rtfill->notify_exec = 1;
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- } while(key(string) != KW_ENDFLAG);
-
- /* Compute the static values to finish initialization */
- if (!complete_vrrp_init(rtfill))
- return 0;
-
- return 1;
-}
-
-configuration_data *conf_reader(char *conf_file)
-{
- configuration_data *conf_data;
- FILE *stream;
-
- /* Parse the confuguration file */
- stream = fopen((conf_file)?conf_file:CONFFILE, "r");
- if(!stream) {
- syslog(LOG_INFO, "ConfReader : Can not read the configuration file...");
- return(NULL);
- }
-
- /* Allocate configuration data memory */
- conf_data = (configuration_data *)MALLOC(sizeof(configuration_data));
-
- /* Allocate temp buffer string */
- string = (char *)MALLOC(TEMP_BUFFER_LENGTH);
-
- /* Initialise the dynamic data structure */
- conf_data->email = NULL;
- conf_data->lvstopology = NULL;
- conf_data->ssldata = NULL;
-
- while (!feof(stream)) {
- switch (key(string)) {
- case KW_GLOBALDEFS:
- process_stream_globaldefs(stream, conf_data);
- break;
- case KW_VS:
- process_stream_vs(stream, conf_data);
- break;
- case KW_VRRP:
- if (!process_stream_vrrp(stream, conf_data))
- return NULL;
- break;
- case KW_SSL:
- conf_data->ssldata = (ssl_data *)MALLOC(sizeof(ssl_data));
- conf_data->ssldata->enable = 0;
- if ((process_stream_ssl(stream, conf_data) & 7) != 7)
- return NULL;
- break;
- case KW_UNKNOWN:
- break;
- }
- fscanf(stream, "%s", string);
- }
-
- FREE(string);
- fclose(stream);
- return(conf_data);
-}
+++ /dev/null
-/*
- * Soft: Keepalived is a failover program for the LVS project
- * <www.linuxvirtualserver.org>. It monitor & manipulate
- * a loadbalanced server pool using multi-layer checks.
- *
- * Part: cfreader.c include file.
- *
- * Version: $Id: cfreader.h,v 0.4.9a 2001/12/20 17:14:25 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 _CFREADER_H
-#define _CFREADER_H
-
-/* system includes */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <syslog.h>
-#include <arpa/inet.h>
-#include <openssl/ssl.h>
-#ifdef _KRNL_2_2_
- #include <linux/ip_masq.h>
- #include <net/ip_masq.h>
-#else
- #include <net/ip_vs.h>
-#endif
-
-/* local includes */
-#include "utils.h"
-#include "vrrp.h"
-
-#define CONFFILE "/etc/keepalived/keepalived.conf"
-
-#define TEMP_BUFFER_LENGTH 100
-#define MAX_EMAIL_LENGTH 45
-#define MAX_LVSID_LENGTH 20
-#define MAX_URL_LENGTH 110
-#define DIGEST_LENGTH 32+1
-#define MAX_TIMEOUT_LENGTH 5
-#define MAX_INT_LENGTH 10
-
-#define MAX_SSL_PASSWORD 48
-#define MAX_SSL_PATH 240
-
-#ifdef _KRNL_2_2_
- #define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
-#else
- #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
-#endif
-
-/* Keywords definition */
-struct keyword {
- int key;
- char *word;
-};
-
-/* configuration file keyword definition */
-#define KW_GLOBALDEFS 0
-#define KW_VS 1
-#define KW_SVR 2
-#define KW_SSVR 3
-#define KW_BEGINFLAG 4
-#define KW_ENDFLAG 5
-#define KW_DELAY 6
-#define KW_EMAIL 7
-#define KW_EMAILFROM 8
-#define KW_LVSID 9
-#define KW_SMTP 10
-#define KW_STIMEOUT 11
-#define KW_LBSCHED 12
-#define KW_LBKIND 13
-#define KW_NATMASK 14
-#define KW_PTIMEOUT 15
-#define KW_PROTOCOL 16
-#define KW_WEIGHT 17
-#define KW_URL 18
-#define KW_URLPATH 19
-#define KW_DIGEST 20
-#define KW_CTIMEOUT 21
-#define KW_NBGETRETRY 22
-#define KW_DELAYRETRY 23
-
-#define KW_ICMPCHECK 24
-#define KW_TCPCHECK 25
-#define KW_HTTPGET 26
-#define KW_SSLGET 27
-#define KW_LDAPGET 28
-#define KW_MISCCHECK 29
-#define KW_MISCPATH 30
-
-#define KW_VRRP 31
-#define KW_VRRPSTATE 32
-#define KW_VRRPINT 33
-#define KW_VRRPVRID 34
-#define KW_VRRPAUTH 35
-#define KW_VRRPAUTHTYPE 36
-#define KW_VRRPAUTHAH 37
-#define KW_VRRPAUTHPWD 38
-#define KW_VRRPAUTHPASS 39
-#define KW_VRRPPRIO 40
-#define KW_VRRPADVERT 41
-#define KW_VRRPIPADD 42
-#define KW_VRRPSYNC 43
-#define KW_VRRPPREEMPT 44
-
-#define KW_VRRPDEBUG 45
-#define KW_VRRPNOTIFY 46
-#define KW_FWMARK 47
-
-#define KW_SSLPASSWORD 48
-#define KW_SSLCAFILE 49
-#define KW_SSLKEYFILE 50
-#define KW_SSLCERTFILE 51
-#define KW_SSL 52
-
-#define KW_UNKNOWN 53
-
-#define KEEPALIVED_DEFAULT_DELAY 60
-
-/* Structure definition */
-
-/* SSL common data */
-typedef struct _ssl_data SSL_DATA;
-typedef struct _ssl_data {
- int enable;
- int strong_check;
- SSL_CTX *ctx;
- SSL_METHOD *meth;
- char password[MAX_SSL_PASSWORD];
- char cafile[MAX_SSL_PATH];
- char certfile[MAX_SSL_PATH];
- char keyfile[MAX_SSL_PATH];
-} ssl_data;
-
-typedef struct _urls {
- char url[MAX_URL_LENGTH];
- char digest[DIGEST_LENGTH];
-
- struct urls *next;
-} urls;
-
-typedef struct _http_get_check {
- int nb_get_retry;
- int delay_before_retry;
- urls *check_urls;
-} http_get_check;
-
-typedef struct _keepalive_check {
- int type;
-#define ICMP_CHECK_ID (1 << 0)
-#define TCP_CHECK_ID (1 << 1)
-#define HTTP_GET_ID (1 << 2)
-#define SSL_GET_ID (1 << 3)
-#define LDAP_GET_ID (1 << 4)
-#define MISC_CHECK_ID (1 << 5)
- int connection_to;
- union {
- http_get_check *http_get;
- char *misc_check_path;
- } u;
-} keepalive_check;
-
-typedef struct _real_server {
- struct in_addr addr_ip;
- uint16_t addr_port;
- int weight;
- keepalive_check *method;
- int alive;
-
- struct realserver *next;
-} realserver;
-
-typedef struct _virtual_server {
- struct in_addr addr_ip;
- uint32_t vfwmark;
- uint16_t addr_port;
- uint16_t service_type;
- int delay_loop;
- char sched[SCHED_MAX_LENGTH];
- unsigned loadbalancing_kind;
- struct in_addr nat_mask;
- char timeout_persistence[MAX_TIMEOUT_LENGTH];
- realserver *s_svr;
- realserver *svr;
-
- struct virtualserver *next;
-} virtualserver;
-
-typedef struct _vrrp_instance {
- char iname[MAX_INT_LENGTH]; /* Instance Name */
- char isync[MAX_INT_LENGTH]; /* Instance Name to synchronize with */
- vrrp_rt *vsrv; /* VRRP data */
-
- struct vrrp_instance *next;
-} vrrp_instance;
-
-typedef struct _notification_email {
- char addr[MAX_EMAIL_LENGTH];
-
- struct notification_email *next;
-} notification_email;
-
-typedef struct _configuration_data {
- char lvs_id[MAX_LVSID_LENGTH];
- char email_from[MAX_EMAIL_LENGTH];
- struct in_addr smtp_server;
- int smtp_connection_to;
- notification_email *email;
- vrrp_instance *vrrp;
- virtualserver *lvstopology;
- ssl_data *ssldata;
-} configuration_data;
-
-/* prototypes */
-extern configuration_data *conf_reader(char *conf_file);
-extern void clear_conf(configuration_data * lstptr);
-extern void clear_vrrp_instance(vrrp_instance *lstptr);
-extern void dump_conf(configuration_data * lstptr);
-
-#endif
+++ /dev/null
-/*
- * Soft: Keepalived is a failover program for the LVS project
- * <www.linuxvirtualserver.org>. It monitor & manipulate
- * a loadbalanced server pool using multi-layer checks.
- *
- * Part: Checkers arguments structures definitions.
- *
- * Version: $Id: check.h,v 0.4.9a 2001/12/20 17:14:25 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 _CHECK_H
-#define _CHECK_H
-
-/* system includes */
-#include <openssl/md5.h>
-#include <openssl/ssl.h>
-
-/* ssl specific thread arguments defs */
-typedef struct {
- char *buffer;
- char *extracted;
- int error;
- int len;
- SSL *ssl;
- BIO *bio;
- MD5_CTX context;
-} REQ;
-
-/* http specific thread arguments defs */
-typedef struct _http_thread_arg {
- int retry_it; /* current number of get retry */
- int url_it; /* current url checked index */
- REQ *req; /* GET buffer and SSL args */
-} http_thread_arg;
-
-/* global thread arguments defs */
-typedef struct _thread_arg {
- configuration_data *root; /* pointer to the configuration root data */
- virtualserver *vs; /* pointer to the checker thread virtualserver */
- realserver *svr; /* pointer to the checker thread realserver */
- void *checker_arg; /* pointer to the specific checker arg */
-} thread_arg;
-
-#endif
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Checkers registration.
+ *
+ * Version: $Id: check_api.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "check_api.h"
+#include "parser.h"
+#include "memory.h"
+#include "check_misc.h"
+#include "check_tcp.h"
+#include "check_http.h"
+#include "check_ssl.h"
+
+extern thread_master *master;
+extern data *conf_data;
+
+/* free checker data */
+static void free_checker(void *data)
+{
+ checker *checker = data;
+ (*checker->free) (checker);
+}
+
+/* dump checker data */
+static void dump_checker(void *data)
+{
+ checker *checker = data;
+ syslog(LOG_INFO, " %s:%d"
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
+ (*checker->dump) (checker);
+}
+
+/* init the global checkers queue */
+void init_checkers_queue(void)
+{
+ checkers_queue = alloc_list(free_checker, dump_checker);
+}
+
+/* Queue a checker to the checkers_queue */
+void queue_checker(void (*free) (void *), void (*dump) (void *)
+ , int (*launch) (struct _thread *)
+ , void *data)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ real_server *rs = LIST_TAIL_DATA(vs->rs);
+ checker *chk = (checker *)MALLOC(sizeof(checker));
+
+ chk->free = free;
+ chk->dump = dump;
+ chk->launch = launch;
+ chk->vs = vs;
+ chk->rs = rs;
+ chk->data = data;
+
+ /* queue the checker */
+ list_add(checkers_queue, chk);
+}
+
+/* dump the checkers_queue */
+void dump_checkers_queue(void)
+{
+ if (!LIST_ISEMPTY(checkers_queue)) {
+ syslog(LOG_INFO, "------< Health checkers >------");
+ dump_list(checkers_queue);
+ }
+}
+
+/* release the checkers_queue */
+void free_checkers_queue(void)
+{
+ free_list(checkers_queue);
+}
+
+/* register the checker to the global I/O scheduler */
+void register_checkers_thread(void)
+{
+ checker *checker;
+ element e;
+
+ for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
+ checker = ELEMENT_DATA(e);
+ thread_add_timer(master, checker->launch
+ , checker
+ , BOOTSTRAP_DELAY);
+ }
+}
+
+/* Install checkers keywords */
+void install_checkers_keyword(void)
+{
+ install_misc_check_keyword();
+ install_tcp_check_keyword();
+ install_http_check_keyword();
+ install_ssl_check_keyword();
+}
--- /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: Checkers arguments structures definitions.
+ *
+ * Version: $Id: check_api.h,v 0.5.3 2002/02/24 23:50:11 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 _CHECK_API_H
+#define _CHECK_API_H
+
+/* local includes */
+#include "data.h"
+#include "scheduler.h"
+
+/* Checkers structure definition */
+typedef struct _checker {
+ void (*free) (void *);
+ void (*dump) (void *);
+ int (*launch) (struct _thread *);
+ virtual_server *vs; /* pointer to the checker thread virtualserver */
+ real_server *rs; /* pointer to the checker thread realserver */
+ void *data;
+} checker;
+
+/* Checkers queue */
+list checkers_queue;
+
+/* utility macro */
+#define CHECKER_ARG(X) ((X)->data)
+#define CHECKER_DATA(X) (((checker *)X)->data)
+#define CHECKER_GET() (CHECKER_DATA(LIST_TAIL_DATA(checkers_queue)))
+#define CHECKER_VALUE_INT(X) (atoi(VECTOR_SLOT(X,1)))
+#define CHECKER_VALUE_STRING(X) (set_value(X))
+#define CHECKER_RIP(C) (SVR_IP((C)->rs))
+#define CHECKER_RPORT(C) (SVR_PORT((C)->rs))
+
+/* Prototypes definition */
+extern void init_checkers_queue(void);
+extern void queue_checker(void (*free) (void *), void (*dump) (void *)
+ , int (*launch) (struct _thread *)
+ , void *data);
+extern void dump_checkers_queue(void);
+extern void free_checkers_queue(void);
+extern void register_checkers_thread(void);
+extern void install_checkers_keyword(void);
+
+#endif
*
* Part: WEB CHECK. Common HTTP/SSL checker primitives.
*
- * Version: $Id: check_http.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_http.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include <openssl/err.h>
#include "check_http.h"
#include "check_ssl.h"
+#include "check_api.h"
#include "memory.h"
+#include "parser.h"
+#include "utils.h"
+
+int http_connect_thread(thread *);
+
+/* Configuration stream handling */
+void free_url(void *data)
+{
+ url *url = data;
+ FREE(url->path);
+ FREE(url->digest);
+ FREE(url);
+}
+void dump_url(void *data)
+{
+ url *url = data;
+ syslog(LOG_INFO, " Checked url = %s, digest = %s"
+ , url->path
+ , url->digest);
+}
+void free_http_get_check(void *data)
+{
+ http_get_checker *http_get_chk = CHECKER_DATA(data);
+
+ free_list(http_get_chk->url);
+ FREE(http_get_chk->arg);
+ FREE(http_get_chk);
+ FREE(data);
+}
+void dump_http_get_check(void *data)
+{
+ http_get_checker *http_get_chk = CHECKER_DATA(data);
+
+ if (http_get_chk->proto == PROTO_HTTP)
+ syslog(LOG_INFO, " Keepalive method = HTTP_GET");
+ else
+ syslog(LOG_INFO, " Keepalive method = SSL_GET");
+ syslog(LOG_INFO, " Connection timeout = %d" , http_get_chk->connection_to);
+ syslog(LOG_INFO, " Nb get retry = %d" , http_get_chk->nb_get_retry);
+ syslog(LOG_INFO, " Delay before retry = %d"
+ , http_get_chk->delay_before_retry);
+ dump_list(http_get_chk->url);
+}
+void http_get_handler(vector strvec)
+{
+ http_get_checker *http_get_chk;
+ char *str = VECTOR_SLOT(strvec, 0);
+
+ http_get_chk = (http_get_checker *)MALLOC(sizeof(http_get_checker));
+ http_get_chk->arg = (http_arg *)MALLOC(sizeof(http_arg));
+ http_get_chk->proto = (!strcmp(str, "HTTP_GET"))?PROTO_HTTP:PROTO_SSL;
+ http_get_chk->url = alloc_list(free_url, dump_url);
+
+ /* queue new checker */
+ queue_checker(free_http_get_check, dump_http_get_check
+ , http_connect_thread
+ , http_get_chk);
+}
+void connect_to_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ http_get_chk->connection_to = CHECKER_VALUE_INT(strvec);
+}
+void nb_get_retry_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ http_get_chk->nb_get_retry = CHECKER_VALUE_INT(strvec);
+}
+void delay_before_retry_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ http_get_chk->delay_before_retry = CHECKER_VALUE_INT(strvec);
+}
+void url_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ url *new;
+
+ /* allocate the new URL */
+ new = (url *)MALLOC(sizeof(url));
+
+ list_add(http_get_chk->url, new);
+}
+void path_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ url *url = LIST_TAIL_DATA(http_get_chk->url);
+
+ url->path = CHECKER_VALUE_STRING(strvec);
+}
+void digest_handler(vector strvec)
+{
+ http_get_checker *http_get_chk = CHECKER_GET();
+ url *url = LIST_TAIL_DATA(http_get_chk->url);
+
+ url->digest = CHECKER_VALUE_STRING(strvec);
+}
+void install_http_check_keyword(void)
+{
+ install_keyword("HTTP_GET", &http_get_handler);
+ install_sublevel();
+ install_keyword("connect_timeout", &connect_to_handler);
+ install_keyword("nb_get_retry", &nb_get_retry_handler);
+ install_keyword("delay_before_retry", &delay_before_retry_handler);
+ install_keyword("url", &url_handler);
+ install_sublevel();
+ install_keyword("path", &path_handler);
+ install_keyword("digest", &digest_handler);
+ install_sublevel_end();
+ install_sublevel_end();
+}
+/* a little code duplication :/ */
+void install_ssl_check_keyword(void)
+{
+ install_keyword("SSL_GET", &http_get_handler);
+ install_sublevel();
+ install_keyword("connect_timeout", &connect_to_handler);
+ install_keyword("nb_get_retry", &nb_get_retry_handler);
+ install_keyword("delay_before_retry", &delay_before_retry_handler);
+ install_keyword("url", &url_handler);
+ install_sublevel();
+ install_keyword("path", &path_handler);
+ install_keyword("digest", &digest_handler);
+ install_sublevel_end();
+ install_sublevel_end();
+}
/*
* The global design of this checker is the following :
*/
int epilog(thread *thread, int metod, int t, int c)
{
- thread_arg *thread_arg = THREAD_ARG(thread);
- http_thread_arg *checker_arg;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
int delay = 0;
- REQ *req;
-
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
if (metod) {
- checker_arg->url_it += t ? t : -checker_arg->url_it;
- checker_arg->retry_it += c ? c : -checker_arg->retry_it;
+ http_arg->url_it += t ? t : -http_arg->url_it;
+ http_arg->retry_it += c ? c : -http_arg->retry_it;
}
/* register next timer thread */
switch (metod) {
case 1:
if (req)
- delay = thread_arg->vs->delay_loop;
+ delay = checker->vs->delay_loop;
else
- delay = thread_arg->vs->delay_loop -
- thread_arg->svr->method->u.http_get->delay_before_retry;
- thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+ delay = checker->vs->delay_loop - http_get_check->delay_before_retry;
+ thread_add_timer(thread->master, http_connect_thread
+ , checker
+ , delay);
break;
case 2:
- delay = thread_arg->svr->method->u.http_get->delay_before_retry;
- thread_add_timer(thread->master, http_connect_thread, thread_arg, delay);
+ delay = http_get_check->delay_before_retry;
+ thread_add_timer(thread->master, http_connect_thread
+ , checker
+ , delay);
break;
}
/* If req == NULL, fd is not created */
- if (req != NULL) {
+ if (req) {
if (req->ssl)
SSL_free(req->ssl);
if (req->buffer)
int timeout_epilog(thread *thread, char *smtp_msg, char *debug_msg)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
-
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
/*
* The get retry implementation mean that we retry performing
* html buffer. This is sometime needed with some applications
* servers.
*/
- if (++checker_arg->retry_it <=
- thread_arg->svr->method->u.http_get->nb_get_retry) {
+ if (++http_arg->retry_it <= http_get_check->nb_get_retry) {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Retry %s server [%s:%d] after %d retry.", debug_msg,
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port),
- checker_arg->retry_it - 1);
+ syslog(LOG_DEBUG, "Retry %s server [%s:%d] after %d retry."
+ , debug_msg
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker))
+ , http_arg->retry_it - 1);
#endif
return epilog(thread,2,0,1);
+
} else {
+
#ifdef _DEBUG_
- if (thread_arg->svr)
- syslog(LOG_DEBUG, "Timeout %s server [%s:%d].", debug_msg,
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ if (checker->rs)
+ syslog(LOG_DEBUG, "Timeout %s server [%s:%d]."
+ , debug_msg
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
/* check if server is currently alive */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr, "DOWN", smtp_msg);
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , smtp_msg);
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
/* simple function returning a pointer to the html buffer begin */
char *extract_html(char *buffer, int size_buffer)
{
- char *end = buffer+size_buffer;
+ char *end = buffer + size_buffer;
while ( buffer < end &&
!(*buffer++ == '\n' &&
}
/* return the url pointer of the current url iterator */
-urls *fetch_next_url(thread_arg *thread_arg)
+url *fetch_next_url(http_get_checker *http_get_check)
{
- http_thread_arg *checker_arg;
- int i = 0;
+ http_arg *http_arg = HTTP_ARG(http_get_check);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
- /* fetch the next url */
- for (i=0; i<checker_arg->url_it; i++)
- thread_arg->svr->method->u.http_get->check_urls=(urls *)thread_arg->svr->method->u.http_get->check_urls->next;
-
- if (thread_arg->svr->method->u.http_get->check_urls != NULL)
- return thread_arg->svr->method->u.http_get->check_urls;
-
- return NULL;
+ return list_element(http_get_check->url, http_arg->url_it);
}
/* Handle response */
-int http_handle_response(thread *thread, unsigned char digest[16], int empty_buffer)
+int http_handle_response(thread *thread, unsigned char digest[16]
+ , int empty_buffer)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- REQ *req;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
int r, di = 0;
unsigned char *digest_tmp;
- urls *fetched_url;
- urls *pointerurls;
-
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
-
+ url *fetched_url;
+
if (empty_buffer) {
- return timeout_epilog(thread,
- "=> CHECK failed on service : empty buffer received <=\n\n",
- "Read, no data received from ");
+ return timeout_epilog(thread, "=> CHECK failed on service"
+ " : empty buffer received <=\n\n"
+ , "Read, no data received from ");
} else {
/* Compute MD5SUM */
digest_tmp = (char *)MALLOC(MD5_BUFFER_LENGTH+1);
for (di=0; di < 16; di++)
sprintf(digest_tmp+2*di, "%02x", digest[di]);
- pointerurls = thread_arg->svr->method->u.http_get->check_urls;
- fetched_url = fetch_next_url(thread_arg);
- thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+ fetched_url = fetch_next_url(http_get_check);
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port),
- checker_arg->url_it+1, digest_tmp);
+ syslog(LOG_DEBUG, "MD5SUM to [%s:%d] url(%d) = [%s]."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker))
+ , http_arg->url_it + 1
+ , digest_tmp);
#endif
r = strcmp(fetched_url->digest, digest_tmp);
if (r) {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d), expecting MD5SUM [%s].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port),
- checker_arg->url_it+1, fetched_url->digest);
+ syslog(LOG_DEBUG, "MD5 digest error to [%s:%d] url(%d)"
+ ", expecting MD5SUM [%s]."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker))
+ , http_arg->url_it + 1
+ , fetched_url->digest);
#endif
/* check if server is currently alive */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> CHECK failed on service : MD5 digest mismatch <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> CHECK failed on service"
+ " : MD5 digest mismatch <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
} else {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "MD5 digest success to [%s:%d] url(%d).",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port),
- checker_arg->url_it+1);
+ syslog(LOG_DEBUG, "MD5 digest success to [%s:%d] url(%d)."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker))
+ , http_arg->url_it + 1);
#endif
return epilog(thread,2,1,0)+1;
}
/* Asynchronous HTTP stream reader */
int http_read_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
unsigned char digest[16];
- REQ *req;
int r = 0;
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
-
/* Handle read timeout */
- if (thread->type == THREAD_READ_TIMEOUT) {
- return timeout_epilog(thread,
- "=> HTTP CHECK failed on service : recevice data <=\n\n",
- "HTTP read");
- }
+ if (thread->type == THREAD_READ_TIMEOUT)
+ return timeout_epilog(thread, "=> HTTP CHECK failed on service"
+ " : recevice data <=\n\n"
+ , "HTTP read");
/* read the HTTP stream */
- r = read(thread->u.fd, req->buffer+req->len, MAX_BUFFER_LENGTH-req->len);
+ r = read(thread->u.fd, req->buffer + req->len
+ , MAX_BUFFER_LENGTH - req->len);
if (r == -1 || r == 0) { /* -1:error , 0:EOF */
if (r == -1) {
/* We have encourred a real read error */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> HTTP CHECK failed on service : cannot receive data <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> HTTP CHECK failed on service"
+ " : cannot receive data <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
}
* Register next http stream reader.
* Register itself to not perturbe global I/O multiplexer.
*/
- thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ thread_add_read(thread->master, http_read_thread
+ , checker
+ , thread->u.fd
+ , http_get_check->connection_to);
}
return 0;
*/
int http_response_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- REQ *req;
-
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
/* Handle read timeout */
- if (thread->type == THREAD_READ_TIMEOUT) {
- return timeout_epilog(thread,
- "=> CHECK failed on service : recevice data <=\n\n",
- "WEB read");
- }
+ if (thread->type == THREAD_READ_TIMEOUT)
+ return timeout_epilog(thread, "=> CHECK failed on service"
+ " : recevice data <=\n\n"
+ , "WEB read");
/* Allocate & clean the get buffer */
req->buffer = (char *)MALLOC(MAX_BUFFER_LENGTH);
MD5_Init(&req->context);
/* Register asynchronous http/ssl read thread */
- if (thread_arg->svr->method->type == SSL_GET_ID)
- thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ if (http_get_check->proto == PROTO_SSL)
+ thread_add_event(thread->master, ssl_read_thread
+ , checker
+ , 0);
else
- thread_add_read(thread->master, http_read_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ thread_add_read(thread->master, http_read_thread
+ , checker
+ , thread->u.fd
+ , http_get_check->connection_to);
return 0;
}
/* remote Web server is connected, send it the get url query. */
int http_request_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- char *str_request;
- urls *fetched_url;
- urls *pointerurls;
- REQ *req;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
+ char *str_request;
+ url *fetched_url;
int ret = 0;
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
-
/* Handle read timeout */
- if(thread->type == THREAD_WRITE_TIMEOUT) {
- return timeout_epilog(thread,
- "=> CHECK failed on service : read timeout <=\n\n",
- "Web read, timeout");
- }
+ if(thread->type == THREAD_WRITE_TIMEOUT)
+ return timeout_epilog(thread, "=> CHECK failed on service"
+ " : read timeout <=\n\n"
+ , "Web read, timeout");
/* Allocate & clean the GET string */
str_request = (char *)MALLOC(GET_REQUEST_BUFFER_LENGTH);
- pointerurls = thread_arg->svr->method->u.http_get->check_urls;
- fetched_url = fetch_next_url(thread_arg);
- thread_arg->svr->method->u.http_get->check_urls = pointerurls;
+ fetched_url = fetch_next_url(http_get_check);
snprintf(str_request, GET_REQUEST_BUFFER_LENGTH
- , REQUEST_TEMPLATE, fetched_url->url
- , inet_ntoa(thread_arg->svr->addr_ip)
- , ntohs(thread_arg->svr->addr_port));
+ , REQUEST_TEMPLATE
+ , fetched_url->path
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d].",
- checker_arg->url_it+1,
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "Processing url(%d) of [%s:%d]."
+ , http_arg->url_it + 1
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
/* Send the GET request to remote Web server */
- if (thread_arg->svr->method->type == SSL_GET_ID)
+ if (http_get_check->proto == PROTO_SSL)
ret = ssl_send_request(req->ssl, str_request, strlen(str_request));
else
ret = (send(thread->u.fd, str_request, strlen(str_request), 0) != -1)?1:0;
FREE(str_request);
if (!ret) {
- syslog(LOG_WARNING, "Cannot send get request to [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_INFO, "Cannot send get request to [%s:%d]."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
/* check if server is currently alive */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> CHECK failed on service : cannot send data <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> CHECK failed on service"
+ " : cannot send data <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
}
/* Register read timeouted thread */
- thread_add_read(thread->master, http_response_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ thread_add_read(thread->master, http_response_thread
+ , checker
+ , thread->u.fd
+ , http_get_check->connection_to);
return 1;
}
/* WEB checkers threads */
int http_check_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- REQ *req;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
int ret = 1;
-
int status;
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
-
- status = tcp_socket_state(thread->u.fd, thread, http_check_thread);
-
+ status = tcp_socket_state(thread->u.fd, thread
+ , CHECKER_RIP(checker)
+ , CHECKER_RPORT(checker)
+ , http_check_thread);
switch (status) {
case connect_error:
#ifdef _DEBUG_
- syslog(LOG_DEBUG,"Error connecting server [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "Error connecting server [%s:%d]."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
/* check if server is currently alive */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> CHECK failed on service : connection error <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> CHECK failed on service"
+ " : connection error <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
break;
case connect_timeout:
- return timeout_epilog(thread,
- "==> CHECK failed on service : connection timeout <=\n\n",
- "connect, timeout");
+ return timeout_epilog(thread, "==> CHECK failed on service"
+ " : connection timeout <=\n\n"
+ , "connect, timeout");
break;
case connect_success: {
- if (thread_arg->svr->method->type == SSL_GET_ID)
+ if (http_get_check->proto == PROTO_SSL)
ret = ssl_connect(thread);
-
+
if (ret) {
/* Remote WEB server is connected.
* Register the next step thread ssl_request_thread.
*/
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Remote Web server [%s:%d] connected.",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "Remote Web server [%s:%d] connected."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
- thread_add_write(thread->master, http_request_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ thread_add_write(thread->master, http_request_thread
+ , checker
+ , thread->u.fd
+ , http_get_check->connection_to);
} else {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Connection problem host: [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
- if (thread_arg->svr->method->type == SSL_GET_ID)
+ syslog(LOG_DEBUG, "Connection trouble to: [%s:%d]."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
+ if (http_get_check->proto == PROTO_SSL)
ssl_printerr(SSL_get_error(req->ssl, ret));
#endif
return epilog(thread,1,0,0);
int http_connect_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- urls *fetched_url;
- urls *pointerurls;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ url *fetched_url;
enum connect_result status;
+ uint16_t addr_port;
int fd;
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
/* Find eventual url end */
- pointerurls = thread_arg->svr->method->u.http_get->check_urls;
- fetched_url = fetch_next_url(thread_arg);
- thread_arg->svr->method->u.http_get->check_urls = pointerurls;
- if (fetched_url == NULL) {
+ fetched_url = fetch_next_url(http_get_check);
+
+ if (!fetched_url) {
/* All the url have been successfully checked.
* Check completed.
* check if server is currently alive.
*/
- if (!thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "UP", "=> CHECK succeed on service <=\n\n");
- perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+ if (!ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "UP"
+ , "=> CHECK succeed on service <=\n\n");
+ perform_svr_state(UP, checker->vs, checker->rs);
#ifdef _DEBUG_
syslog(LOG_DEBUG, "Remote Web server [%s:%d] succeed on service."
- , inet_ntoa(thread_arg->svr->addr_ip)
- , ntohs(thread_arg->svr->addr_port));
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
}
- checker_arg->req = NULL;
+ http_arg->req = NULL;
return epilog(thread,1,0,0)+1;
}
/* Allocate & clean request struct */
- checker_arg->req = (REQ *)MALLOC(sizeof(REQ));
+ http_arg->req = (REQ *)MALLOC(sizeof(REQ));
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
#ifdef _DEBUG_
return 0;
}
- status = tcp_connect(fd, thread_arg->svr->addr_ip.s_addr, thread_arg->svr->addr_port);
+ /*
+ * Set the remote connection port.
+ * If we are balancing all services (host rather than service),
+ * then assume we want to use default ports for HTTP or HTTPS.
+ * Known as 'Layer3 stickyness'
+ */
+ addr_port = CHECKER_RPORT(checker);
+ if (!addr_port)
+ addr_port = htons((http_get_check->proto == PROTO_SSL)?443:80);
- /* handle tcp connection status & register check worker thread */
- tcp_connection_state(fd, status, thread, http_check_thread);
+ status = tcp_connect(fd, CHECKER_RIP(checker), addr_port);
+ /* handle tcp connection status & register check worker thread */
+ tcp_connection_state(fd, status, thread
+ , http_check_thread
+ , http_get_check->connection_to);
return 0;
}
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#ifndef _HTTP_H
#define _HTTP_H
+/* system includes */
+#include <stdio.h>
+#include <openssl/md5.h>
+#include <openssl/ssl.h>
+
/* local includes */
-#include "cfreader.h"
+#include "data.h"
#include "ipwrapper.h"
#include "scheduler.h"
#include "layer4.h"
+#include "list.h"
+
+/* Checker argument structure */
+/* ssl specific thread arguments defs */
+typedef struct {
+ char *buffer;
+ char *extracted;
+ int error;
+ int len;
+ SSL *ssl;
+ BIO *bio;
+ MD5_CTX context;
+} REQ;
+
+/* http specific thread arguments defs */
+typedef struct _http_arg {
+ int retry_it; /* current number of get retry */
+ int url_it; /* current url checked index */
+ REQ *req; /* GET buffer and SSL args */
+} http_arg;
+
+typedef struct _url {
+ char *path;
+ char *digest;
+} url;
+typedef struct _http_get_checker {
+ int proto;
+ int connection_to;
+ int nb_get_retry;
+ int delay_before_retry;
+ list url;
+ http_arg *arg;
+} http_get_checker;
/* global defs */
#define MD5_BUFFER_LENGTH 32
#define GET_REQUEST_BUFFER_LENGTH 128
#define GET_BUFFER_LENGTH 2048
#define MAX_BUFFER_LENGTH 4096
+#define PROTO_HTTP 0x01
+#define PROTO_SSL 0x02
-/* http get processing command */
+/* GET processing command */
#define REQUEST_TEMPLATE "GET %s HTTP/1.0\r\n" \
"User-Agent:KeepAliveClient\r\n" \
"Host: %s:%d\r\n\r\n"
+/* macro utility */
+#define HTTP_ARG(X) ((X)->arg)
+#define HTTP_REQ(X) ((X)->req)
+
/* Define prototypes */
+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 urls *fetch_next_url(thread_arg *thread_arg);
+extern url *fetch_next_url(http_get_checker *http_get_check);
extern int http_handle_response(thread *thread
, unsigned char digest[16]
, int empty_buffer);
-
-extern void smtp_alert(thread_master *
- , configuration_data *
- , realserver *
- , const char *
- , const char *);
-
#endif
* Part: MISC CHECK. Perform a system call to run an extra
* system prog or script.
*
- * Version: $Id: check_misc.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_misc.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
*/
#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"
+
+int misc_check_thread(thread *);
+
+/* Configuration stream handling */
+void free_misc_check(void *data)
+{
+ misc_checker *misc_chk = CHECKER_DATA(data);
+
+ FREE(misc_chk->path);
+ FREE(misc_chk);
+ FREE(data);
+}
+void dump_misc_check(void *data)
+{
+ misc_checker *misc_chk = CHECKER_DATA(data);
+
+ syslog(LOG_INFO, " Keepalive method = MISC_CHECK");
+ syslog(LOG_INFO, " script = %s"
+ , misc_chk->path);
+}
+void misc_check_handler(vector strvec)
+{
+ misc_checker *misc_chk = (misc_checker *)MALLOC(sizeof(misc_checker));
+
+ /* queue new checker */
+ queue_checker(free_misc_check, dump_misc_check
+ , misc_check_thread
+ , misc_chk);
+}
+void misc_path_handler(vector strvec)
+{
+ misc_checker *misc_chk = CHECKER_GET();
+
+ misc_chk->path = CHECKER_VALUE_STRING(strvec);
+}
+void install_misc_check_keyword(void)
+{
+ install_keyword("MISC_CHECK", &misc_check_handler);
+ install_sublevel();
+ install_keyword("misc_path", &misc_path_handler);
+ install_sublevel_end();
+}
-/* does this need to be threaded? */
int misc_check_call(char* cmdline)
{
int retval;
if (retval == 127) {
/* couldn't exec command */
- syslog(LOG_DEBUG,"Couldn't exec command: %s", cmdline);
+ syslog(LOG_DEBUG, "Couldn't exec command: %s", cmdline);
} else if (retval == -1) {
/* other error */
- syslog(LOG_DEBUG,"Error exec-ing command: %s", cmdline);
+ syslog(LOG_DEBUG, "Error exec-ing command: %s", cmdline);
} else {
/* everything is good */
syslog(LOG_DEBUG, "Successfully exec command: %s retval is %d"
int misc_check_thread(thread *thread)
{
- thread_arg *thread_arg;
+ checker *checker;
+ misc_checker *misc_chk;
int status;
- thread_arg = THREAD_ARG(thread);
+ checker = THREAD_ARG(thread);
+ misc_chk = CHECKER_ARG(checker);
- status = misc_check_call(thread_arg->svr->method->u.misc_check_path);
+ /* Register next timer checker */
+ thread_add_timer(thread->master, misc_check_thread
+ , checker
+ , checker->vs->delay_loop);
- if (status == 0) {
- /* everything is good */
- if (!thread_arg->svr->alive) {
- perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+ /* Daemonization to not degrade our scheduling timer */
+ if (xdaemon(0, 0, 1))
+ return 0x80000000;
+
+ status = misc_check_call(misc_chk->path);
+
+ if (status >= 0) { /* script error assumed not an svr error */
+ if (status == 0) {
+ /* everything is good */
+ if (!checker->rs->alive) {
+ smtp_alert(thread->master, checker->rs
+ , "UP"
+ , "=> MISC CHECK succeed on service <=\n\n");
+ perform_svr_state(UP, checker->vs, checker->rs);
+ }
+ } else {
+ if (checker->rs->alive) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> MISC CHECK failed on service <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
+ }
}
- } else {
- if (thread_arg->svr->alive) {
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
- }
}
- /* Register next timer checker */
- thread_add_timer(thread->master, misc_check_thread, thread_arg,
- thread_arg->vs->delay_loop);
-
- return 0;
+ exit(0);
}
*
* Part: check_misc.c include file.
*
- * Version: $Id: check_misc.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_misc.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
#include <stdlib.h>
/* local includes */
-#include "cfreader.h"
-#include "ipwrapper.h"
#include "scheduler.h"
-#include "smtp.h"
+
+/* Checker argument structure */
+typedef struct _misc_checker {
+ char *path;
+} misc_checker;
/* Prototypes defs */
-extern int misc_check_thread(thread *thread);
+extern void install_misc_check_keyword(void);
#endif
* url, compute a MD5 over this result and match it to the
* expected value.
*
- * Version: $Id: check_ssl.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_ssl.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include <openssl/err.h>
#include "check_ssl.h"
+#include "check_api.h"
#include "memory.h"
+#include "parser.h"
+#include "smtp.h"
+#include "utils.h"
+
+extern data *conf_data;
/* SSL primitives */
/* Free an SSL context */
/* Inititalize global SSL context */
static BIO *bio_err = 0;
-static SSL_DATA *build_ssl_ctx(SSL_DATA *ssl)
+static int build_ssl_ctx(void)
{
+ SSL_DATA *ssl;
+
/* Library initialization */
SSL_library_init();
SSL_load_error_strings();
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
- if (!ssl)
+ if (!conf_data->ssl)
ssl = (SSL_DATA *)MALLOC(sizeof(ssl_data));
+ else
+ ssl = conf_data->ssl;
/* Initialize SSL context for SSL v2/3 */
ssl->meth = SSLv23_method();
ssl->ctx = SSL_CTX_new(ssl->meth);
+ /* return for autogen context */
+ if (!conf_data->ssl) {
+ conf_data->ssl = ssl;
+ goto end;
+ }
+
/* Load our keys and certificates */
- if (strlen(ssl->keyfile) > 0)
- if (!(SSL_CTX_use_certificate_chain_file(ssl->ctx, ssl->keyfile))) {
+ if (conf_data->ssl->keyfile)
+ if (!(SSL_CTX_use_certificate_chain_file(ssl->ctx, conf_data->ssl->keyfile))) {
syslog(LOG_INFO, "SSL error : Cant load certificate file...");
- return NULL;
+ return 0;
}
/* Handle password callback using userdata ssl */
- if (strlen(ssl->password) > 0) {
- SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, ssl);
+ if (conf_data->ssl->password) {
+ SSL_CTX_set_default_passwd_cb_userdata(ssl->ctx, conf_data->ssl);
SSL_CTX_set_default_passwd_cb(ssl->ctx, password_cb);
}
- if (strlen(ssl->keyfile) > 0)
- if (!(SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->keyfile, SSL_FILETYPE_PEM))) {
+ if (conf_data->ssl->keyfile)
+ if (!(SSL_CTX_use_PrivateKey_file(ssl->ctx, conf_data->ssl->keyfile
+ , SSL_FILETYPE_PEM))) {
syslog(LOG_INFO, "SSL error : Cant load key file...");
- return NULL;
+ return 0;
}
/* Load the CAs we trust */
- if (strlen(ssl->cafile) > 0)
- if (!(SSL_CTX_load_verify_locations(ssl->ctx, ssl->cafile, 0))) {
+ if (conf_data->ssl->cafile)
+ if (!(SSL_CTX_load_verify_locations(ssl->ctx, conf_data->ssl->cafile, 0))) {
syslog(LOG_INFO, "SSL error : Cant load CA file...");
- return NULL;
+ return 0;
}
+end:
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
- SSL_CTX_set_verify_depth(ssl->ctx,1);
+ SSL_CTX_set_verify_depth(ssl->ctx, 1);
#endif
- return ssl;
+ return 1;
}
/*
* Initialize the SSL context, with or without specific
* configuration files.
*/
-SSL_DATA *init_ssl_ctx(SSL_DATA *ssl)
+int init_ssl_ctx(void)
{
- if (!(ssl = build_ssl_ctx(ssl))) {
+ SSL_DATA *ssl = conf_data->ssl;
+
+ if (!build_ssl_ctx()) {
syslog(LOG_INFO, "Error Initialize SSL, ctx Instance");
syslog(LOG_INFO, " SSL keyfile:%s", ssl->keyfile);
syslog(LOG_INFO, " SSL password:%s", ssl->password);
syslog(LOG_INFO, " SSL cafile:%s", ssl->cafile);
syslog(LOG_INFO, "Terminate...\n");
clear_ssl(ssl);
- return NULL;
+ return 0;
}
-
- return ssl;
+ return 1;
}
/* Display SSL error to readable string */
int ssl_connect(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
- REQ *req;
-
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
- req->ssl = SSL_new(thread_arg->root->ssldata->ctx);
+ req->ssl = SSL_new(conf_data->ssl->ctx);
req->bio = BIO_new_socket(thread->u.fd, BIO_NOCLOSE);
SSL_set_bio(req->ssl, req->bio, req->bio);
err++;
break;
}
-
+
return (err == 3)?1:0;
}
/* Asynchronous SSL stream reader */
int ssl_read_thread(thread *thread)
{
- thread_arg *thread_arg;
- http_thread_arg *checker_arg;
+ checker *checker = THREAD_ARG(thread);
+ http_get_checker *http_get_check = CHECKER_ARG(checker);
+ http_arg *http_arg = HTTP_ARG(http_get_check);
+ REQ *req = HTTP_REQ(http_arg);
unsigned char digest[16];
- REQ *req;
int r = 0;
- thread_arg = THREAD_ARG(thread);
- checker_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
- req = checker_arg->req;
-
/* Handle read timeout */
- if (thread->type == THREAD_READ_TIMEOUT) {
- return timeout_epilog(thread,
- "=> SSL CHECK failed on service : recevice data <=\n\n",
- "SSL read");
- }
+ if (thread->type == THREAD_READ_TIMEOUT &&
+ !req->extracted)
+ return timeout_epilog(thread, "=> SSL CHECK failed on service"
+ " : recevice data <=\n\n"
+ , "SSL read");
/* read the SSL stream */
- r = SSL_read(req->ssl, req->buffer+req->len, MAX_BUFFER_LENGTH-req->len);
+ r = SSL_read(req->ssl, req->buffer + req->len
+ , MAX_BUFFER_LENGTH - req->len);
req->error = SSL_get_error(req->ssl, r);
if (req->error) {
r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0;
- if (r) {
+ if (r && !req->extracted) {
/* check if server is currently alive */
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> SSL CHECK failed on service : cannot receive data <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> SSL CHECK failed on service"
+ " : cannot receive data <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
return epilog(thread,1,0,0);
}
* Register next ssl stream reader.
* Register itself to not perturbe global I/O multiplexer.
*/
- thread_add_read(thread->master, ssl_read_thread, thread_arg, thread->u.fd,
- thread_arg->svr->method->connection_to);
+ thread_add_read(thread->master, ssl_read_thread
+ , checker
+ , thread->u.fd
+ , http_get_check->connection_to);
}
return 0;
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_http.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#include "check_http.h"
/* Prototypes */
-extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
+extern void install_ssl_check_keyword(void);
+extern int init_ssl_ctx(void);
extern void clear_ssl(SSL_DATA *ssl);
extern int ssl_connect(thread *thread);
extern int ssl_printerr(int err);
*
* Part: TCP checker.
*
- * Version: $Id: check_tcp.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_tcp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#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"
+
+int tcp_connect_thread(thread *);
+
+/* Configuration stream handling */
+void free_tcp_check(void *data)
+{
+ tcp_checker *tcp_chk = CHECKER_DATA(data);
+
+ FREE(tcp_chk);
+ FREE(data);
+}
+void dump_tcp_check(void *data)
+{
+ tcp_checker *tcp_chk = CHECKER_DATA(data);
+
+ syslog(LOG_INFO, " Keepalive method = TCP_CHECK");
+ syslog(LOG_INFO, " Connection timeout = %d"
+ , tcp_chk->connection_to);
+}
+void tcp_check_handler(vector strvec)
+{
+ tcp_checker *tcp_chk = (tcp_checker *)MALLOC(sizeof(tcp_checker));
+
+ /* queue new checker */
+ queue_checker(free_tcp_check, dump_tcp_check
+ , tcp_connect_thread
+ , tcp_chk);
+}
+void connect_timeout_handler(vector strvec)
+{
+ tcp_checker *tcp_chk = CHECKER_GET();
+ tcp_chk->connection_to = CHECKER_VALUE_INT(strvec);
+}
+void install_tcp_check_keyword(void)
+{
+ install_keyword("TCP_CHECK", &tcp_check_handler);
+ install_sublevel();
+ install_keyword("connect_timeout", &connect_timeout_handler);
+ install_sublevel_end();
+}
int tcp_check_thread(thread *thread)
{
- thread_arg *thread_arg;
+ checker *checker;
int status;
- thread_arg = THREAD_ARG(thread);
+ checker = THREAD_ARG(thread);
- status = tcp_socket_state(thread->u.fd, thread, tcp_check_thread);
+ status = tcp_socket_state(thread->u.fd, thread
+ , CHECKER_RIP(checker)
+ , CHECKER_RPORT(checker)
+ , tcp_check_thread);
/* If status = connect_success, TCP connection to remote host is established.
* Otherwise we have a real connection error or connection timeout.
if (status == connect_success) {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "TCP connection to [%s:%d] success.",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection to [%s:%d] success."
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
close(thread->u.fd);
- if (!thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "UP", "=> TCP CHECK succeed on service <=\n\n");
- perform_svr_state(UP, thread_arg->vs, thread_arg->svr);
+ if (!ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "UP"
+ , "=> TCP CHECK succeed on service <=\n\n");
+ perform_svr_state(UP, checker->vs, checker->rs);
}
} else {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "TCP connection to [%s:%d] failed !!!",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection to [%s:%d] failed !!!"
+ , ip_ntoa(CHECKER_RIP(checker))
+ , ntohs(CHECKER_RPORT(checker)));
#endif
- if (thread_arg->svr->alive) {
- smtp_alert(thread->master, thread_arg->root, thread_arg->svr,
- "DOWN", "=> TCP CHECK failed on service <=\n\n");
- perform_svr_state(DOWN, thread_arg->vs, thread_arg->svr);
+ if (ISALIVE(checker->rs)) {
+ smtp_alert(thread->master, checker->rs
+ , "DOWN"
+ , "=> TCP CHECK failed on service <=\n\n");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
}
}
/* Register next timer checker */
if (status != connect_in_progress)
- thread_add_timer(thread->master, tcp_connect_thread, thread_arg,
- thread_arg->vs->delay_loop);
-
+ thread_add_timer(thread->master, tcp_connect_thread
+ , checker
+ , checker->vs->delay_loop);
return 0;
}
int tcp_connect_thread(thread *thread)
{
- thread_arg *thread_arg;
+ checker *checker;
+ tcp_checker *tcp_check;
int fd;
int status;
- thread_arg = THREAD_ARG(thread);
+ checker = THREAD_ARG(thread);
+ tcp_check = CHECKER_ARG(checker);
if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
#ifdef _DEBUG_
return 0;
}
- status = tcp_connect(fd, thread_arg->svr->addr_ip.s_addr, thread_arg->svr->addr_port);
+ status = tcp_connect(fd, CHECKER_RIP(checker)
+ , CHECKER_RPORT(checker));
/* handle tcp connection status & register check worker thread */
- tcp_connection_state(fd, status, thread, tcp_check_thread);
-
+ tcp_connection_state(fd, status, thread
+ , tcp_check_thread
+ , tcp_check->connection_to);
return 0;
}
*
* Part: check_tcp.c include file.
*
- * Version: $Id: check_tcp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: check_tcp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <arpa/inet.h>
/* local includes */
-#include "cfreader.h"
-#include "ipwrapper.h"
#include "scheduler.h"
-#include "layer4.h"
-#include "smtp.h"
+
+/* Checker argument structure */
+typedef struct _tcp_checker {
+ int connection_to;
+} tcp_checker;
+
/* Prototypes defs */
-extern int tcp_connect_thread(thread *thread);
+extern void install_tcp_check_keyword(void);
#endif
--- /dev/null
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=parser.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:529: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:559: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:610: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:642: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 653 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:684: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:689: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:717: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:779: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+KERNEL_VERSION=`uname -r`
+modprobe ip_vs
+if test -f /proc/net/ip_vs; then
+ IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+else
+ echo
+ echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
+ echo
+ exit 1
+fi
+VERSION=`cat VERSION`
+
+echo $ac_n "checking for main in -lcrypto""... $ac_c" 1>&6
+echo "configure:845: checking for main in -lcrypto" >&5
+ac_lib_var=`echo crypto'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcrypto $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 853 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:860: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo crypto | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcrypto $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lpopt""... $ac_c" 1>&6
+echo "configure:888: checking for main in -lpopt" >&5
+ac_lib_var=`echo popt'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lpopt $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 896 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:903: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo popt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lpopt $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lssl""... $ac_c" 1>&6
+echo "configure:931: checking for main in -lssl" >&5
+ac_lib_var=`echo ssl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lssl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 939 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo ssl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lssl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
+if test "${KERNEL_CODE}" = "2"; then
+ LDFLAGS = ${LIBS} libipfwc/libipfwc.a
+ LIBOBJS = ${LIBOBJS} ipfwwrapper.o
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:981: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 996 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1013 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1019: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1030 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1036: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1061: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1066 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1074: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1091 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1109 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1130 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1141: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:1165: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1170 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:1186: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1210: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1215 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1220: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1248: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1253 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1302: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:1323: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1328 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:1356: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1361 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1370: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+
+if test $ac_cv_prog_gcc = yes; then
+ echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
+echo "configure:1393: checking whether ${CC-cc} needs -traditional" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat > conftest.$ac_ext <<EOF
+#line 1399 "configure"
+#include "confdefs.h"
+#include <sgtty.h>
+Autoconf TIOCGETP
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+else
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat > conftest.$ac_ext <<EOF
+#line 1417 "configure"
+#include "confdefs.h"
+#include <termio.h>
+Autoconf TCGETA
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "$ac_pattern" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
+echo "configure:1439: checking for 8-bit clean memcmp" >&5
+if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_memcmp_clean=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1447 "configure"
+#include "confdefs.h"
+
+main()
+{
+ char c0 = 0x40, c1 = 0x80, c2 = 0x81;
+ exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+}
+
+EOF
+if { (eval echo configure:1457: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_memcmp_clean=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_memcmp_clean=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
+test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1475: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1480 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1497: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+for ac_func in gettimeofday select socket strerror strtol uname
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1518: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1523 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1546: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile genhash/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@CPP@%$CPP%g
+s%@LIBOBJS@%$LIBOBJS%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile genhash/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+cat <<EOF;
+
+Keepalived configuration
+------------------------
+Keepalived version : ${VERSION}
+Linux Kernel release : ${KERNEL_VERSION}
+IPVS version code : ${IPVS_VERSION}
+Compiler : ${CC}
+Compiler flags : ${CFLAGS}
+
+EOF
--- /dev/null
+#
+# Keepalived OpenSource project.
+#
+# Configuration template file for keepalived.
+# autoconf will generate & check deps for proper compilation
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+dnl ----[ Process this file with autoconf to produce a configure script ]----
+AC_INIT(cfreader.c)
+
+dnl ----[ Checks for programs ]----
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl ----[ Checks for kernel support ]----
+KERNEL_VERSION=`uname -r`
+modprobe ip_vs
+if test -f /proc/net/ip_vs; then
+ IPVS_VERSION=`cat /proc/net/ip_vs | head -1 | awk '{ print $5}'`
+else
+ echo
+ echo "!!!WARN!!! Your kernel need to be patched with LVS code !!!WARN!!!"
+ echo
+ exit 1
+fi
+VERSION=`cat VERSION`
+
+dnl ----[ Checks for libraries ]----
+dnl Replace `main' with a function in -lcrypto:
+AC_CHECK_LIB(crypto, main)
+dnl Replace `main' with a function in -lpopt:
+AC_CHECK_LIB(popt, main)
+dnl Replace `main' with a function in -lssl:
+AC_CHECK_LIB(ssl, main)
+
+dnl ----[ Create object list ]----
+KERNEL_CODE=`echo $KERNEL_VERSION | cut -d'.' -f2`
+if test "${KERNEL_CODE}" = "2"; then
+ LDFLAGS = ${LIBS} libipfwc/libipfwc.a
+ LIBOBJS = ${LIBOBJS} ipfwwrapper.o
+fi
+
+dnl ----[ Checks for header files ]----
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h)
+
+dnl ----[ Checks for typedefs, structures, and compiler characteristics ]----
+AC_C_CONST
+AC_TYPE_PID_T
+AC_HEADER_TIME
+
+dnl ----[ Checks for library functions ]----
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MEMCMP
+AC_TYPE_SIGNAL
+AC_CHECK_FUNCS(gettimeofday select socket strerror strtol uname)
+
+AC_OUTPUT(Makefile genhash/Makefile)
+
+cat <<EOF;
+
+Keepalived configuration
+------------------------
+Keepalived version : ${VERSION}
+Linux Kernel release : ${KERNEL_VERSION}
+IPVS version code : ${IPVS_VERSION}
+Compiler : ${CC}
+Compiler flags : ${CFLAGS}
+
+EOF
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Main program structure.
+ *
+ * Version: $Id: main.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "daemon.h"
+
+/* Daemonization function coming from zebra source code */
+pid_t xdaemon(int nochdir, int noclose, int exitflag)
+{
+ pid_t pid;
+
+ /* In case of fork is error. */
+ pid = fork ();
+ if (pid < 0) {
+ perror ("fork");
+ return -1;
+ }
+
+ /* In case of this is parent process. */
+ if (pid != 0 ) {
+ if (!exitflag)
+ exit(0);
+ else
+ return pid;
+ }
+
+ /* Become session leader and get pid. */
+ pid = setsid();
+ if (pid < -1) {
+ perror ("setsid");
+ return -1;
+ }
+
+ /* Change directory to root. */
+ if (!nochdir)
+ chdir ("/");
+
+ /* File descriptor close. */
+ if (!noclose) {
+ int fd;
+
+ fd = open("/dev/null", O_RDWR, 0);
+ if (fd != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close (fd);
+ }
+ }
+
+ umask (0);
+ return 0;
+}
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Daemon process handling.
+ *
+ * Version: $Id: daemon.h,v 0.5.3 2002/02/24 23:50:11 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 _DAEMON_H
+#define _DAEMON_H
+
+/* System includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/* prototype */
+extern pid_t xdaemon(int, int, int);
+
+#endif
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Dynamic data structure definition.
+ *
+ * Version: $Id: data.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "data.h"
+#include "memory.h"
+#include "utils.h"
+#include "check_api.h"
+
+extern data *conf_data;
+
+/* email facility functions */
+static void free_email(void *data)
+{
+ FREE(data);
+}
+static void dump_email(void *data)
+{
+ char *addr = data;
+ syslog(LOG_INFO, " Email notification = %s", addr);
+}
+void alloc_email(char *addr)
+{
+ int size = strlen(addr);
+ char *new;
+
+ new = (char *)MALLOC(size+1);
+ memcpy(new, addr, size);
+
+ list_add(conf_data->email, new);
+}
+
+/* SSL facility functions */
+SSL_DATA *alloc_ssl(void)
+{
+ SSL_DATA *ssl = (SSL_DATA *)MALLOC(sizeof(SSL_DATA));
+ return ssl;
+}
+static void free_ssl(void)
+{
+ SSL_DATA *ssl = conf_data->ssl;
+
+ if (!ssl) return;
+ FREE_PTR(ssl->password);
+ FREE_PTR(ssl->cafile);
+ FREE_PTR(ssl->certfile);
+ FREE_PTR(ssl->keyfile);
+ FREE(ssl);
+}
+static void dump_ssl(void)
+{
+ SSL_DATA *ssl = conf_data->ssl;
+
+ if (ssl->password)
+ syslog(LOG_INFO, " Password : %s", ssl->password);
+ if (ssl->cafile)
+ syslog(LOG_INFO, " CA-file : %s", ssl->cafile);
+ if (ssl->certfile)
+ syslog(LOG_INFO, " Certificate file : %s", ssl->certfile);
+ if (ssl->keyfile)
+ syslog(LOG_INFO, " Key file : %s", ssl->keyfile);
+ if (!ssl->password && !ssl->cafile && !ssl->certfile && !ssl->keyfile)
+ syslog(LOG_INFO, " Using autogen SSL context");
+}
+
+/* VRRP facility functions */
+static void free_vrrp(void *data)
+{
+ vrrp_instance *vrrp = data;
+ vrrp_rt *ptr = vrrp->vsrv;
+
+ FREE(vrrp->iname);
+ FREE_PTR(vrrp->isync);
+ FREE_PTR(ptr->vaddr);
+ FREE(ptr->ipsecah_counter);
+ FREE(ptr->vif->ifname);
+ FREE(ptr->vif);
+ FREE(ptr);
+ FREE(vrrp);
+}
+static void dump_vrrp(void *data)
+{
+ vrrp_instance *vrrp = data;
+ vrrp_rt *ptr = vrrp->vsrv;
+ int i;
+
+ syslog(LOG_INFO, " VRRP Instance = %s", vrrp->iname);
+ if (vrrp->isync)
+ syslog(LOG_INFO, " Sync with instance = %s", vrrp->isync);
+ if (ptr->init_state == VRRP_STATE_BACK)
+ syslog(LOG_INFO, " Want State = BACKUP");
+ else
+ syslog(LOG_INFO, " Want State = MASTER");
+ syslog(LOG_INFO, " Runing on device = %s", ptr->vif->ifname);
+ syslog(LOG_INFO, " Virtual Router ID = %d", ptr->vrid);
+ syslog(LOG_INFO, " Priority = %d", ptr->priority);
+ syslog(LOG_INFO, " Advert interval = %dsec", ptr->adver_int/TIMER_HZ);
+ if (ptr->preempt)
+ syslog(LOG_INFO, " Preempt Active");
+ if (ptr->vif->auth_type) {
+ syslog(LOG_INFO, " Authentication type = %s",
+ (ptr->vif->auth_type == VRRP_AUTH_AH)?"IPSEC_AH":"SIMPLE_PASSWORD" );
+ syslog(LOG_INFO, " Password = %s", ptr->vif->auth_data);
+ }
+ syslog(LOG_INFO, " VIP count = %d", ptr->naddr);
+ for (i = 0; i < ptr->naddr; i++)
+ syslog(LOG_INFO, " VIP%d = %s", i+1, ip_ntoa(ptr->vaddr[i].addr));
+}
+void alloc_vrrp(char *iname)
+{
+ int size = strlen(iname);
+ vrrp_instance *new;
+ vrrp_rt *rt;
+ vrrp_if *vif;
+ seq_counter *counter;
+
+ /* Allocate new VRRP structure */
+ new = (vrrp_instance *)MALLOC(sizeof(vrrp_instance));
+ rt = (vrrp_rt *) MALLOC(sizeof(vrrp_rt));
+ vif = (vrrp_if *) MALLOC(sizeof(vrrp_if));
+ counter = (seq_counter *) MALLOC(sizeof(seq_counter));
+
+ /* Build the structure */
+ new->vsrv = rt;
+ rt->vif = vif;
+ rt->ipsecah_counter = counter;
+
+ /* Set default values */
+ rt->wantstate = VRRP_STATE_BACK;
+ rt->init_state = VRRP_STATE_BACK;
+ rt->adver_int = TIMER_HZ;
+ new->iname = (char *)MALLOC(size+1);
+ memcpy(new->iname, iname, size);
+
+ list_add(conf_data->vrrp, new);
+}
+void alloc_vrrp_vip(char *vip)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ uint32_t ipaddr = inet_addr(vip);
+ vrrp_rt *ptr = vrrp->vsrv;
+
+ ptr->naddr++;
+ if (ptr->vaddr)
+ ptr->vaddr = REALLOC(ptr->vaddr, ptr->naddr*sizeof(*ptr->vaddr));
+ else
+ ptr->vaddr = (vip_addr *)MALLOC(sizeof(*ptr->vaddr));
+ ptr->vaddr[ptr->naddr-1].addr = ipaddr;
+ ptr->vaddr[ptr->naddr-1].deletable = 0;
+}
+
+/* Virtual server facility functions */
+static void free_vs(void *data)
+{
+ virtual_server *vs = data;
+ FREE_PTR(vs->s_svr);
+ if (!LIST_ISEMPTY(vs->rs))
+ free_list(vs->rs);
+ FREE(vs);
+}
+static void dump_vs(void *data)
+{
+ virtual_server *vs = data;
+ if (vs->vfwmark)
+ syslog(LOG_INFO, " VS FWMARK = %d", vs->vfwmark);
+ else
+ syslog(LOG_INFO, " VIP = %s, VPORT = %d"
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
+ syslog(LOG_INFO, " delay_loop = %d, lb_algo = %s"
+ , vs->delay_loop
+ , vs->sched);
+ if (atoi(vs->timeout_persistence) > 0)
+ syslog(LOG_INFO, " persistence = %s"
+ , vs->timeout_persistence);
+ syslog(LOG_INFO, " protocol = %s"
+ , (vs->service_type == IPPROTO_TCP)?"TCP":"UDP");
+
+ switch (vs->loadbalancing_kind) {
+#ifdef _KRNL_2_2_
+ case 0:
+ syslog(LOG_INFO, " lb_kind = NAT");
+ syslog(LOG_INFO, " nat mask = %s", ip_ntoa(vs->nat_mask));
+ break;
+ case IP_MASQ_F_VS_DROUTE:
+ syslog(LOG_INFO, " lb_kind = DR");
+ break;
+ case IP_MASQ_F_VS_TUNNEL:
+ syslog(LOG_INFO, " lb_kind = TUN");
+ break;
+#else
+ case IP_VS_CONN_F_MASQ:
+ syslog(LOG_INFO, " lb_kind = NAT");
+ break;
+ case IP_VS_CONN_F_DROUTE:
+ syslog(LOG_INFO, " lb_kind = DR");
+ break;
+ case IP_VS_CONN_F_TUNNEL:
+ syslog(LOG_INFO, " lb_kind = TUN");
+ break;
+#endif
+ }
+
+ if (vs->s_svr) {
+ syslog(LOG_INFO, " sorry server = %s:%d"
+ , ip_ntoa(SVR_IP(vs->s_svr))
+ , ntohs(SVR_PORT(vs->s_svr)));
+ }
+
+ dump_list(vs->rs);
+}
+void alloc_vs(char *ip, char *port)
+{
+ virtual_server *new;
+
+ new = (virtual_server *)MALLOC(sizeof(virtual_server));
+
+ if (!strcmp(ip, "fwmark")) {
+ new->vfwmark = atoi(port);
+ } else {
+ new->addr_ip = inet_addr(ip);
+ new->addr_port = htons(atoi(port));
+ }
+ new->delay_loop = KEEPALIVED_DEFAULT_DELAY;
+ strncpy(new->timeout_persistence, "0", 1);
+
+ list_add(conf_data->vs, new);
+}
+
+/* Sorry server facility functions */
+void alloc_ssvr(char *ip, char *port)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+
+ vs->s_svr = (real_server *)MALLOC(sizeof(real_server));
+ vs->s_svr->weight = 1;
+ vs->s_svr->addr_ip = inet_addr(ip);
+ vs->s_svr->addr_port = htons(atoi(port));
+}
+
+/* Real server facility functions */
+static void free_rs(void *data)
+{
+ real_server *rs = data;
+ FREE(rs);
+}
+static void dump_rs(void *data)
+{
+ real_server *rs = data;
+ syslog(LOG_INFO, " RIP = %s, RPORT = %d, WEIGHT = %d"
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs))
+ , rs->weight);
+}
+void alloc_rs(char *ip, char *port)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ real_server *new;
+
+ new = (real_server *)MALLOC(sizeof(real_server));
+
+ new->addr_ip = inet_addr(ip);
+ new->addr_port = htons(atoi(port));
+ new->alive = 1;
+
+ if (LIST_ISEMPTY(vs->rs))
+ vs->rs = alloc_list(free_rs, dump_rs);
+
+ list_add(vs->rs, new);
+}
+
+/* data facility functions */
+data *alloc_data(void)
+{
+ data *new;
+
+ new = (data *)MALLOC(sizeof(data));
+ new->email = alloc_list(free_email, dump_email);
+ new->vrrp = alloc_list(free_vrrp, dump_vrrp);
+ new->vs = alloc_list(free_vs, dump_vs);
+
+ return new;
+}
+void free_data(void)
+{
+ free_ssl();
+ free_list(conf_data->email);
+ free_list(conf_data->vrrp);
+ free_list(conf_data->vs);
+
+ FREE(conf_data->lvs_id);
+ FREE(conf_data->email_from);
+ FREE(conf_data);
+}
+void dump_data(void)
+{
+ syslog(LOG_INFO, "------< Global definitions >------");
+ syslog(LOG_INFO, " LVS ID = %s", conf_data->lvs_id);
+ syslog(LOG_INFO, " Smtp server = %s", ip_ntoa(conf_data->smtp_server));
+ syslog(LOG_INFO, " Smtp server connection timeout = %d", conf_data->smtp_connection_to);
+ syslog(LOG_INFO, " Email notification from = %s", conf_data->email_from);
+ dump_list(conf_data->email);
+
+ if (conf_data->ssl) {
+ syslog(LOG_INFO, "------< SSL definitions >------");
+ dump_ssl();
+ }
+ if (!LIST_ISEMPTY(conf_data->vrrp)) {
+ syslog(LOG_INFO, "------< VRRP Topology >------");
+ dump_list(conf_data->vrrp);
+ }
+ if (!LIST_ISEMPTY(conf_data->vs)) {
+ syslog(LOG_INFO, "------< LVS Topology >------");
+ syslog(LOG_INFO, " System is compiled with LVS v%d.%d.%d"
+ , NVERSION(IP_VS_VERSION_CODE));
+ dump_list(conf_data->vs);
+ }
+ dump_checkers_queue();
+}
--- /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: Dynamic data structure definition.
+ *
+ * Version: $Id: data.h,v 0.5.3 2002/02/24 23:50:11 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 _DATA_H
+#define _DATA_H
+
+/* system includes */
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <openssl/ssl.h>
+
+#ifdef _KRNL_2_2_
+ #include <linux/ip_masq.h>
+ #include <net/ip_masq.h>
+ #define SCHED_MAX_LENGTH IP_MASQ_TNAME_MAX
+#else
+ #define SCHED_MAX_LENGTH IP_VS_SCHEDNAME_MAXLEN
+#endif
+#include <net/ip_vs.h>
+
+/* local includes */
+#include "list.h"
+#include "vrrp.h"
+
+/* Daemon dynamic data structure definition */
+#define MAX_TIMEOUT_LENGTH 5
+#define KEEPALIVED_DEFAULT_DELAY 60
+
+/* SSL specific data */
+typedef struct _ssl_data SSL_DATA;
+typedef struct _ssl_data {
+ int enable;
+ int strong_check;
+ SSL_CTX *ctx;
+ SSL_METHOD *meth;
+ char *password;
+ char *cafile;
+ char *certfile;
+ char *keyfile;
+} ssl_data;
+
+/* Real Server definition */
+typedef struct _real_server {
+ uint32_t addr_ip;
+ uint16_t addr_port;
+ int weight;
+ int alive;
+} real_server;
+
+/* Virtual Server definition */
+typedef struct _virtual_server {
+ uint32_t addr_ip;
+ uint32_t vfwmark;
+ uint16_t addr_port;
+ uint16_t service_type;
+ int delay_loop;
+ char sched[SCHED_MAX_LENGTH];
+ unsigned loadbalancing_kind;
+ uint32_t nat_mask;
+ char timeout_persistence[MAX_TIMEOUT_LENGTH];
+ real_server *s_svr;
+ list rs;
+} virtual_server;
+
+/* VRRP instance definition */
+typedef struct _vrrp_instance {
+ char *iname; /* Instance Name */
+ char *isync; /* Instance Name to synchronize with */
+ vrrp_rt *vsrv; /* VRRP data */
+} vrrp_instance;
+
+/* email link list */
+typedef struct _email {
+ char *addr;
+} email;
+
+/* Configuration data root */
+typedef struct _data {
+ char *lvs_id;
+ char *email_from;
+ uint32_t smtp_server;
+ int smtp_connection_to;
+ SSL_DATA *ssl;
+ list email;
+ list vrrp;
+ list vs;
+} data;
+
+/* macro utility */
+#define ISALIVE(R) ((R)->alive)
+#define SVR_IP(H) ((H)->addr_ip)
+#define SVR_PORT(H) ((H)->addr_port)
+
+/* prototypes */
+extern void alloc_email(char *addr);
+extern SSL_DATA *alloc_ssl(void);
+extern void alloc_vrrp(char *iname);
+extern void alloc_vrrp_vip(char *vip);
+extern void alloc_vs(char *ip, char *port);
+extern void alloc_rs(char *ip, char *port);
+extern void alloc_ssvr(char *ip, char *port);
+
+extern data *alloc_data(void);
+extern void free_data(void);
+extern void dump_data(void);
+
+#endif
+2002-01-17 Alexandre Cassen <acassen@linux-vs.org>
+ * Patched the dynamic GET request lenght allocation.
+
2001-11-29 Alexandre Cassen <acassen@linux-vs.org>
* genhash 0.4.9 released.
* Rewrite the whole previous code
+++ /dev/null
-# Makefile
-# Alexandre Cassen <acassen@linux-vs.org>
-
-EXEC = genhash
-
-CC = gcc
-CFLAGS = -Wall -Wunused -Wstrict-prototypes -g -O2
-#LD = -lssl -lcrypto -dynamic -lpopt
-LD = -lssl -lcrypto -lpopt
-
-OBJS = main.o client.o common.o
-
-all: genhash
- strip genhash
- @echo ""
- @echo "Make complete"
-$(EXEC): $(OBJS)
- $(CC) $(OBJS) -o $(EXEC) $(LD)
-clean:
- rm -f core *.o $(EXEC)
-install:
- install -m 755 genhash /usr/bin/
--- /dev/null
+# Makefile
+#
+# Keepalived OpenSource project.
+#
+# Copyright (C) 2001, 2002 Alexandre Cassen, <acassen@linux-vs.org>
+
+EXEC = genhash
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+
+CC = gcc
+CFLAGS = @CFLAGS@ -Wall -Wunused -Wstrict-prototypes
+LDFLAGS = @LIBS@ @LDFLAGS@
+
+OBJS = main.o client.o common.o
+
+all: $(EXEC)
+ strip $(EXEC)
+ @echo ""
+ @echo "Make complete"
+
+$(EXEC): $(OBJS)
+ $(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
+
+clean:
+ rm -f core *.o $(EXEC)
+
+clean-dist:
+ rm -f $(bindir)/$(EXEC)
+
+install:
+ install -m 755 $(EXEC) $(bindir)/
char *request;
int request_len = 0;
- request_len = strlen(REQUEST_TEMPLATE) + strlen(req->host) + 12;
+ request_len = strlen(REQUEST_TEMPLATE) +
+ strlen(req->host) +
+ strlen(req->url) +
+ sizeof(unsigned short int);
request = xmalloc(request_len);
if (!request) return NULL;
--- /dev/null
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
* library to add/remove server MASQ rules to the kernel
* firewall framework.
*
- * Version: $Id: ipfwwrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: ipfwwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "ipfwwrapper.h"
+#include "utils.h"
-int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipfw_cmd(int cmd, virtual_server *vs, real_server *rs)
{
struct ip_fwuser ctl;
int ret = 1;
/* Create the firewall MASQ rule */
strncpy(ctl.label, IP_FW_LABEL_MASQUERADE, IP_FW_MAX_LABEL_LENGTH);
- ctl.ipfw.fw_proto = vserver->service_type;
+ ctl.ipfw.fw_proto = vs->service_type;
/* compute the source ip address */
- ctl.ipfw.fw_src.s_addr = rserver->addr_ip.s_addr & vserver->nat_mask.s_addr;
- ctl.ipfw.fw_smsk.s_addr = vserver->nat_mask.s_addr;
+ ctl.ipfw.fw_src.s_addr = SVR_IP(rs) & vs->nat_mask;
+ ctl.ipfw.fw_smsk.s_addr = vs->nat_mask;
- ctl.ipfw.fw_spts[0] = ctl.ipfw.fw_spts[1] = ntohs(rserver->addr_port);
+ ctl.ipfw.fw_spts[0] = ctl.ipfw.fw_spts[1] = ntohs(rs->addr_port);
ctl.ipfw.fw_dpts[0] = 0x0000;
ctl.ipfw.fw_dpts[1] = 0xFFFF;
ctl.ipfw.fw_tosand = 0xFF;
if (cmd & IP_FW_CMD_ADD) {
ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
if (!(errno & EINVAL)) {
-#ifdef DEBUG
- syslog(LOG_DEBUG, "ipfw_cmd : MASQ firewall rule [%s:%d] already exist.",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+#ifdef _DEBUG_
+ syslog(LOG_DEBUG, "ipfw_cmd : MASQ firewall rule [%s:%d] already exist."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
#endif
}
ret &= ipfwc_insert_entry(IP_FW_LABEL_FORWARD, &ctl, 1);
ret &= ipfwc_delete_entry(IP_FW_LABEL_FORWARD, &ctl);
if(!ret) {
-#ifdef DEBUG
- syslog(LOG_DEBUG, "ipfw_cmd : firewall error (%s) processing [%s:%d] MASQ rule.",
- strerror(errno),
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+#ifdef _DEBUG_
+ syslog(LOG_DEBUG, "ipfw_cmd : firewall error (%s) processing [%s:%d] MASQ rule."
+ , strerror(errno)
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
#endif
return IPFW_ERROR;
}
*
* Part: ipfwwrapper.c include file.
*
- * Version: $Id: ipfwwrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: ipfwwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* locale includes */
#include "libipfwc/libipfwc.h"
-#include "cfreader.h"
+#include "data.h"
/* local defs */
#define IPFW_ERROR 0
#define IPFW_SRC_NETMASK 0xffffffff
/* prototypes */
-extern int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver);
+extern int ipfw_cmd(int cmd, virtual_server *vserver, real_server *rserver);
#endif
* Part: IPVS Kernel wrapper. Use setsockopt call to add/remove
* server to/from the loadbalanced server pool.
*
- * Version: $Id: ipvswrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: ipvswrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "ipvswrapper.h"
+#include "utils.h"
#ifdef _KRNL_2_2_ /* KERNEL 2.2 LVS handling */
-int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
{
struct ip_masq_ctl ctl;
int result=0;
ctl.m_target = IP_MASQ_TARGET_VS;
ctl.m_cmd = cmd;
- strncpy(ctl.m_tname, vserver->sched, IP_MASQ_TNAME_MAX);
+ strncpy(ctl.m_tname, vs->sched, IP_MASQ_TNAME_MAX);
ctl.u.vs_user.weight = -1;
- ctl.u.vs_user.masq_flags = vserver->loadbalancing_kind;
+ ctl.u.vs_user.masq_flags = vs->loadbalancing_kind;
ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff); /* f:f:f:f for default netmask */
- ctl.u.vs_user.protocol = vserver->service_type;
+ ctl.u.vs_user.protocol = vs->service_type;
- if(!parse_timeout(vserver->timeout_persistence, &ctl.u.vs_user.timeout)) {
- syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout.",
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ if(!parse_timeout(vs->timeout_persistence, &ctl.u.vs_user.timeout)) {
+ syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout."
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
}
ctl.u.vs_user.vs_flags = (ctl.u.vs_user.timeout!=0)?IP_VS_SVC_F_PERSISTENT:0;
/* VS specific */
- if (vserver->vfwmark) {
- ctl.u.vs_user.vfwmark = vserver->vfwmark;
+ if (vs->vfwmark) {
+ ctl.u.vs_user.vfwmark = vs->vfwmark;
} else {
- ctl.u.vs_user.vaddr = vserver->addr_ip.s_addr;
- ctl.u.vs_user.vport = vserver->addr_port;
+ ctl.u.vs_user.vaddr = SVR_IP(vs);
+ ctl.u.vs_user.vport = SVR_PORT(vs);
}
/* SVR specific */
if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST) {
- ctl.u.vs_user.weight = rserver->weight;
- ctl.u.vs_user.daddr = rserver->addr_ip.s_addr;
- ctl.u.vs_user.dport = rserver->addr_port;
+ ctl.u.vs_user.weight = rs->weight;
+ ctl.u.vs_user.daddr = SVR_IP(rs);
+ ctl.u.vs_user.dport = SVR_PORT(rs);
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
result = setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *)&ctl, sizeof(ctl));
if (errno == ESRCH) {
- syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] not defined.",
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] not defined."
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
close(sockfd);
return IPVS_ERROR;
} else if (errno == EEXIST) {
- syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
} else if (errno == ENOENT) {
- syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
}
close(sockfd);
#else /* KERNEL 2.4 LVS handling */
-int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver)
+int ipvs_cmd(int cmd, virtual_server *vs, real_server *rs)
{
struct ip_vs_rule_user urule;
int result=0;
memset(&urule, 0, sizeof(struct ip_vs_rule_user));
- strncpy(urule.sched_name, vserver->sched, IP_VS_SCHEDNAME_MAXLEN);
+ strncpy(urule.sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
urule.weight = 1;
- urule.conn_flags = vserver->loadbalancing_kind;
+ urule.conn_flags = vs->loadbalancing_kind;
urule.netmask = ((u_int32_t) 0xffffffff);
- urule.protocol = vserver->service_type;
+ urule.protocol = vs->service_type;
- if (!parse_timeout(vserver->timeout_persistence, &urule.timeout)) {
- syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout.",
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
- }
+ if (!parse_timeout(vs->timeout_persistence, &urule.timeout))
+ syslog(LOG_INFO, "IPVS WRAPPER : Virtual service [%s:%d] illegal timeout."
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
urule.vs_flags = (urule.timeout != 0)?IP_VS_SVC_F_PERSISTENT:0;
/* VS specific */
- if (vserver->vfwmark) {
- urule.vfwmark = vserver->vfwmark;
+ if (vs->vfwmark) {
+ urule.vfwmark = vs->vfwmark;
} else {
- urule.vaddr = vserver->addr_ip.s_addr;
- urule.vport = vserver->addr_port;
+ urule.vaddr = SVR_IP(vs);
+ urule.vport = SVR_PORT(vs);
}
/* SVR specific */
if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
- urule.weight = rserver->weight;
- urule.daddr = rserver->addr_ip.s_addr;
- urule.dport = rserver->addr_port;
+ urule.weight = rs->weight;
+ urule.daddr = SVR_IP(rs);
+ urule.dport = SVR_PORT(rs);
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
switch (cmd) {
case IP_VS_SO_SET_ADD:
if (errno == EEXIST)
- syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
else if (errno == ENOENT) {
- syslog(LOG_INFO, "IPVS WRAPPER : Scheduler not found: ip_vs_%s.o !!!",
- urule.sched_name);
+ syslog(LOG_INFO, "IPVS WRAPPER : Scheduler not found: ip_vs_%s.o !!!"
+ , urule.sched_name);
close(sockfd);
return IPVS_ERROR;
}
case IP_VS_SO_SET_DEL:
if (errno == ESRCH)
- syslog(LOG_INFO, "IPVS WRAPPER : No such service [%s:%d].",
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : No such service [%s:%d]."
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
close(sockfd);
return IPVS_ERROR;
break;
case IP_VS_SO_SET_ADDDEST:
if (errno == ESRCH)
- syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
else if (errno == EEXIST)
- syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Destination already exists [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
break;
case IP_VS_SO_SET_DELDEST:
if (errno == ESRCH)
- syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : Service not defined [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
else if (errno == ENOENT)
- syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d].",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port));
+ syslog(LOG_INFO, "IPVS WRAPPER : No such destination [%s:%d]."
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs)));
break;
}
}
return 1;
}
- if ((i=string_to_number(buf, 1, 86400*31)) == -1)
+ if ((i=string_to_number(buf, 0, 86400*31)) == -1)
return 0;
*timeout = i * HZ;
*
* Part: ipvswrapper.c include file.
*
- * Version: $Id: ipvswrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: ipvswrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <linux/ip_fw.h>
#include <net/ip_masq.h>
#endif
-
#include <net/ip_vs.h>
/* locale includes */
-#include "cfreader.h"
+#include "data.h"
#define IPVS_ERROR 0
#define IPVS_SUCCESS 1
/* prototypes */
extern int parse_timeout(char *buf, unsigned *timeout);
extern int string_to_number(const char *s, int min, int max);
-extern int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver);
+extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
#endif
*
* Part: Manipulation functions for IPVS & IPFW wrappers.
*
- * Version: $id: ipwrapper.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $id: ipwrapper.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "ipwrapper.h"
+#include "utils.h"
-int clear_service_vs(virtualserver *vserver)
+extern data *conf_data;
+
+int clear_service_vs(virtual_server *vs)
{
- realserver *pointersvr;
+ element e;
- pointersvr = vserver->svr;
- while (vserver->svr) {
+ for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
/* IPVS cleaning server entry */
- if (!ipvs_cmd(LVS_CMD_DEL_DEST, vserver, vserver->svr)) {
- vserver->svr = pointersvr;
+ if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs, e->data))
return 0;
- }
#ifdef _KRNL_2_2_
/* IPFW cleaning server entry if granularity = /32 */
- if (vserver->nat_mask.s_addr == HOST_NETMASK)
- if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
+ if (vserver->nat_mask == HOST_NETMASK)
+ if (!ipfw_cmd(IP_FW_CMD_DEL, vs, e->data))
return 0;
#endif
-
- vserver->svr = (realserver *)vserver->svr->next;
}
- vserver->svr = pointersvr;
- if (!ipvs_cmd(LVS_CMD_DEL, vserver, vserver->svr))
+ if (!ipvs_cmd(LVS_CMD_DEL, vs, NULL))
return 0;
-
return 1;
}
-int clear_services(virtualserver *vserver)
+/* IPVS cleaner processing */
+int clear_services(void)
{
- while (vserver) {
- /* IPVS cleaner processing */
- if (!clear_service_vs(vserver))
+ element e;
+ list vs = conf_data->vs;
+ virtual_server *vsvr;
+ real_server *rsvr;
+
+ for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
+ vsvr = ELEMENT_DATA(e);
+ rsvr = (real_server *)LIST_HEAD(vsvr->rs);
+ if (!clear_service_vs(vsvr))
return 0;
#ifdef _KRNL_2_2_
- /* IPFW cleaner processing */
- if (vserver->nat_mask.s_addr != HOST_NETMASK)
- if (!ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->svr))
+ if (vsvr->nat_mask != HOST_NETMASK)
+ if (!ipfw_cmd(IP_FW_CMD_DEL, vsvr, rsvr))
return 0;
#endif
-
- vserver = (virtualserver *)vserver->next;
}
return 1;
}
-int all_realservers_down(virtualserver *vserver)
+int all_realservers_down(virtual_server *vs)
{
- realserver *pointersvr;
+ element e;
+ real_server *svr;
- pointersvr = vserver->svr;
- while (vserver->svr) {
- if (vserver->svr->alive) return 0;
-
- vserver->svr = (realserver *)vserver->svr->next;
+ for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
+ svr = ELEMENT_DATA(e);
+ if (svr->alive) return 0;
}
- vserver->svr = pointersvr;
return 1;
}
-void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver)
+void perform_svr_state(int alive, virtual_server *vs, real_server *rs)
{
- if (!rserver->alive && alive) {
+ if (!ISALIVE(rs) && alive) {
/* adding a server to the vs pool, if sorry server is flagged alive,
* we remove it from the vs pool.
*/
- if (vserver->s_svr) {
- if (vserver->s_svr->alive) {
- syslog(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]",
- inet_ntoa(vserver->s_svr->addr_ip), ntohs(vserver->s_svr->addr_port),
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
-
- vserver->s_svr->alive = 0;
- ipvs_cmd(LVS_CMD_DEL_DEST, vserver, vserver->s_svr);
+ if (vs->s_svr) {
+ if (vs->s_svr->alive) {
+ syslog(LOG_INFO, "Removing sorry server [%s:%d] from VS [%s:%d]"
+ , ip_ntoa(SVR_IP(vs->s_svr))
+ , ntohs(SVR_PORT(vs->s_svr))
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
+
+ vs->s_svr->alive = 0;
+ ipvs_cmd(LVS_CMD_DEL_DEST, vs, vs->s_svr);
#ifdef _KRNL_2_2_
- ipfw_cmd(IP_FW_CMD_DEL, vserver, vserver->s_svr);
+ ipfw_cmd(IP_FW_CMD_DEL, vs, vs->s_svr);
#endif
}
}
- rserver->alive = alive;
- syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port),
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
- ipvs_cmd(LVS_CMD_ADD_DEST, vserver, rserver);
+ rs->alive = alive;
+ syslog(LOG_INFO, "Adding service [%s:%d] to VS [%s:%d]"
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs))
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
+ ipvs_cmd(LVS_CMD_ADD_DEST, vs, rs);
#ifdef _KRNL_2_2_
- if (vserver->nat_mask.s_addr == HOST_NETMASK)
- ipfw_cmd(IP_FW_CMD_ADD, vserver, rserver);
+ if (vs->nat_mask == HOST_NETMASK)
+ ipfw_cmd(IP_FW_CMD_ADD, vs, rs);
#endif
} else {
- rserver->alive = alive;
- syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]",
- inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port),
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ rs->alive = alive;
+ syslog(LOG_INFO, "Removing service [%s:%d] from VS [%s:%d]"
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs))
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
/* server is down, it is removed from the LVS realserver pool */
- ipvs_cmd(LVS_CMD_DEL_DEST, vserver, rserver);
+ ipvs_cmd(LVS_CMD_DEL_DEST, vs, rs);
#ifdef _KRNL_2_2_
- if (vserver->nat_mask.s_addr == HOST_NETMASK)
- ipfw_cmd(IP_FW_CMD_DEL, vserver, rserver);
+ if (vs->nat_mask == HOST_NETMASK)
+ ipfw_cmd(IP_FW_CMD_DEL, vs, rs);
#endif
/* if all the realserver pool is down, we add sorry server */
- if (vserver->s_svr && all_realservers_down(vserver)) {
- syslog(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]",
- inet_ntoa(vserver->s_svr->addr_ip), ntohs(vserver->s_svr->addr_port),
- inet_ntoa(vserver->addr_ip), ntohs(vserver->addr_port));
+ if (vs->s_svr && all_realservers_down(vs)) {
+ syslog(LOG_INFO, "Adding sorry server [%s:%d] to VS [%s:%d]"
+ , ip_ntoa(SVR_IP(vs->s_svr))
+ , ntohs(SVR_PORT(vs->s_svr))
+ , ip_ntoa(SVR_IP(vs))
+ , ntohs(SVR_PORT(vs)));
/* the sorry server is now up in the pool, we flag it alive */
- vserver->s_svr->alive = 1;
- ipvs_cmd(LVS_CMD_ADD_DEST, vserver, vserver->s_svr);
+ vs->s_svr->alive = 1;
+ ipvs_cmd(LVS_CMD_ADD_DEST, vs, vs->s_svr);
#ifdef _KRNL_2_2_
- ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->s_svr);
+ ipfw_cmd(IP_FW_CMD_ADD, vs, vs->s_svr);
#endif
}
}
}
-int init_service_vs(virtualserver *vserver)
+int init_service_vs(virtual_server *vs)
{
- realserver *pointersvr;
+ element e;
+
+ /* Init the IPVS root */
+ if (!ipvs_cmd(LVS_CMD_ADD, vs, NULL))
+ return 0;
- pointersvr = vserver->svr;
- while (vserver->svr) {
- if (!ipvs_cmd(LVS_CMD_ADD_DEST, vserver, vserver->svr)) {
- vserver->svr = pointersvr;
+ for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
+ if (!ipvs_cmd(LVS_CMD_ADD_DEST, vs, e->data))
return 0;
- }
#ifdef _KRNL_2_2_
/* if we have a /32 mask, we create one nat rules per
* realserver.
*/
- if (vserver->nat_mask.s_addr == HOST_NETMASK)
- if(!ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->svr)) {
- vserver->svr = pointersvr;
+ if (vs->nat_mask == HOST_NETMASK)
+ if(!ipfw_cmd(IP_FW_CMD_ADD, vs, e->data))
return 0;
- }
#endif
-
- vserver->svr = (realserver *)vserver->svr->next;
}
- vserver->svr = pointersvr;
-
return 1;
}
-int init_services(virtualserver *vserver)
+int init_services(void)
{
- virtualserver *pointervs;
-
- pointervs = vserver;
- while (vserver) {
- if (!ipvs_cmd(LVS_CMD_ADD, vserver, vserver->svr))
+ element e;
+ list vs = conf_data->vs;
+ virtual_server *vsvr;
+ real_server *rsvr;
+
+ for (e = LIST_HEAD(vs); e; ELEMENT_NEXT(e)) {
+ vsvr = ELEMENT_DATA(e);
+ rsvr = (real_server *)LIST_HEAD(vsvr->rs);
+ if (!init_service_vs(vsvr))
return 0;
#ifdef _KRNL_2_2_
/* work if all realserver ip address are in the
* same network (it is assumed).
*/
- if (vserver->nat_mask.s_addr != HOST_NETMASK)
- if (!ipfw_cmd(IP_FW_CMD_ADD, vserver, vserver->svr))
+ if (vsvr->nat_mask != HOST_NETMASK)
+ if (!ipfw_cmd(IP_FW_CMD_ADD, vsvr, rsvr))
return 0;
#endif
-
- if (!init_service_vs(vserver))
- return 0;
-
- vserver = (virtualserver *)vserver->next;
}
- vserver = pointervs;
-
return 1;
}
*
* Part: ipwrapper.c include file.
*
- * Version: $Id: ipwrapper.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: ipwrapper.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <syslog.h>
/* locale includes */
-#include "cfreader.h"
+#include "data.h"
#include "smtp.h"
/* NAT netmask */
#endif
/* prototypes */
-extern void perform_svr_state(int alive, virtualserver *vserver, realserver *rserver);
-extern int init_services(virtualserver *vserver);
-extern int clear_services(virtualserver *vserver);
+extern void perform_svr_state(int alive, virtual_server *vs, real_server *rs);
+extern int init_services(void);
+extern int clear_services(void);
-extern int ipvs_cmd(int cmd, virtualserver *vserver, realserver *rserver);
-extern int ipfw_cmd(int cmd, virtualserver *vserver, realserver *rserver);
+extern int ipvs_cmd(int cmd, virtual_server *vserver, real_server *rserver);
+extern int ipfw_cmd(int cmd, virtual_server *vserver, real_server *rserver);
#endif
* Part: Layer4 checkers handling. Register worker threads &
* upper layer checkers.
*
- * Version: $Id: layer4.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: layer4.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "layer4.h"
+#include "check_api.h"
enum connect_result
-tcp_connect (int fd, uint32_t IP_DST, uint16_t PORT_DST)
+tcp_connect (int fd, uint32_t addr_ip, uint16_t addr_port)
{
struct linger li = { 0 };
int long_inet;
/* 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));
+ 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 = PORT_DST;
- adr_serv.sin_addr.s_addr = IP_DST;
+ 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);
}
enum connect_result tcp_socket_state(int fd, thread *thread
- , int (*func) (struct _thread *))
+ , uint32_t addr_ip
+ , uint16_t addr_port
+ , int (*func) (struct _thread *))
{
- thread_arg *thread_arg;
int status;
int slen;
int ret = 0;
- TIMEVAL timer_now;
TIMEVAL timer_min;
- thread_arg = THREAD_ARG(thread);
-
/* Handle connection timeout */
if(thread->type == THREAD_WRITE_TIMEOUT) {
#ifdef _DEBUG_
- if (thread_arg->svr)
- syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection timeout to [%s:%d]."
+ , ip_ntoa(addr_ip)
+ , ntohs(addr_port));
#endif
close(thread->u.fd);
return connect_timeout;
/* Connection failed !!! */
if (ret) {
#ifdef _DEBUG_
- if (thread_arg->svr)
- syslog(LOG_DEBUG, "TCP connection failed to [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection failed to [%s:%d]."
+ , ip_ntoa(addr_ip)
+ , ntohs(addr_port));
#endif
close(thread->u.fd);
return connect_error;
*/
if (status != 0) {
#ifdef _DEBUG_
- if (thread_arg->svr)
- syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS.",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection to [%s:%d] still IN_PROGRESS."
+ , ip_ntoa(addr_ip)
+ , ntohs(addr_port));
#endif
- gettimeofday(&timer_now,NULL);
- timer_min = thread_timer_sub(thread->sands,timer_now);
+ timer_min = timer_sub_now(thread->sands);
- if (timer_min.tv_sec <= 0)
- thread_add_write(thread->master, func,
- thread_arg, thread->u.fd, 0);
+ 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->u.fd, timer_min.tv_sec);
-
+ thread_add_write(thread->master, func
+ , THREAD_ARG(thread)
+ , thread->u.fd
+ , TIMER_SEC(timer_min));
return connect_in_progress;
}
void tcp_connection_state(int fd, enum connect_result status
, thread *thread
- , int (*func) (struct _thread *))
+ , int (*func) (struct _thread *)
+ , int timeout)
{
- thread_arg *thread_arg;
+ checker *checker;
- thread_arg = THREAD_ARG(thread);
+ checker = THREAD_ARG(thread);
switch (status) {
case connect_error:
#ifdef _DEBUG_
- syslog(LOG_DEBUG,"TCP connection ERROR to [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection ERROR to [%s:%d]."
+ , ip_ntoa(SVR_IP(checker->rs))
+ , ntohs(SVR_PORT(checker->rs)));
#endif
close(fd);
break;
case connect_success:
#ifdef _DEBUG_
- syslog(LOG_DEBUG,"TCP connection SUCCESS to [%s:%d].",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection SUCCESS to [%s:%d]."
+ , ip_ntoa(SVR_IP(checker->rs))
+ , ntohs(SVR_PORT(checker->rs)));
#endif
- thread_add_write(thread->master, func, thread_arg, fd,
- thread_arg->svr->method->connection_to);
+ thread_add_write(thread->master, func, checker, fd, timeout);
break;
/* Checking non-blocking connect, we wait until socket is writable */
case connect_in_progress:
#ifdef _DEBUG_
- syslog(LOG_DEBUG,"TCP connection to [%s:%d] now IN_PROGRESS.",
- inet_ntoa(thread_arg->svr->addr_ip),
- ntohs(thread_arg->svr->addr_port));
+ syslog(LOG_DEBUG, "TCP connection to [%s:%d] now IN_PROGRESS."
+ , ip_ntoa(SVR_IP(checker->rs))
+ , ntohs(SVR_PORT(checker->rs)));
#endif
- thread_add_write(thread->master, func, thread_arg, fd,
- thread_arg->svr->method->connection_to);
+ thread_add_write(thread->master, func, checker, fd, timeout);
break;
default:
*
* Part: layer4.c include file.
*
- * Version: $Id: layer4.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: layer4.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* 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 "cfreader.h"
#include "scheduler.h"
-#include "check_http.h"
enum connect_result {
connect_error,
/* Prototypes defs */
extern enum connect_result
-tcp_connect(int fd, uint32_t IP_DST, uint16_t PORT_DST);
+tcp_connect(int fd, uint32_t, uint16_t);
extern enum connect_result
-tcp_socket_state(int fd, thread *thread,
- int (*func) (struct _thread *));
+tcp_socket_state(int, thread *
+ , uint32_t
+ , uint16_t
+ , int (*func) (struct _thread *));
extern void
-tcp_connection_state(int fd, enum connect_result status,
- thread *thread,
- int (*func) (struct _thread *));
-
+tcp_connection_state(int, enum connect_result
+ , thread *
+ , int (*func) (struct _thread *)
+ , int);
#endif
-# Makefile to make libipfwc.
-
-CC = gcc
-COPTS = -g -O
-CFLAGS = -Wall -Wunused $(COPTS)
-
-libipfwc.a: libipfwc.a(libipfwc.o)
-
-libipfwc.o: libipfwc.h ipfwc_kernel_headers.h
-
-clean:
- rm -f *.a *.o *~
--- /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: List structure manipulation.
+ *
+ * Version: $Id: list.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "list.h"
+#include "memory.h"
+
+list alloc_list(void (*free_func) (void *), void (*dump_func) (void *))
+{
+ list new = (list)MALLOC(sizeof(struct _list));
+ new->free = free_func;
+ new->dump = dump_func;
+ return new;
+}
+
+static element alloc_element(void)
+{
+ element new = (element)MALLOC(sizeof(struct _element));
+ return new;
+}
+
+void list_add(list l, void *data)
+{
+ element e = alloc_element();
+
+ e->prev = l->tail;
+ e->data = data;
+
+ if (l->head == NULL)
+ l->head = e;
+ else
+ l->tail->next = e;
+ l->tail = e;
+ l->count++;
+}
+
+void *list_element(list l, int num)
+{
+ element e;
+ int i = 0;
+
+ e = LIST_HEAD(l);
+
+ /* fetch element number num */
+ for (i = 0; i < num; i++)
+ if (e)
+ e = ELEMENT_NEXT(e);
+
+ if (e)
+ return ELEMENT_DATA(e);
+ return NULL;
+}
+
+void dump_list(list l)
+{
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e))
+ if (l->dump)
+ (*l->dump) (e->data);
+}
+
+void free_list(list l)
+{
+ element e;
+ element next;
+
+ for (e = LIST_HEAD(l); e; e = next) {
+ next = e->next;
+ if (l->free)
+ (*l->free) (e->data);
+ FREE(e);
+ }
+ FREE(l);
+}
--- /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: list.c include file.
+ *
+ * Version: $Id: list.h,v 0.5.3 2002/02/24 23:50:11 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 _LIST_H
+#define _LIST_H
+
+/* list definition */
+typedef struct _element *element;
+typedef struct _list *list;
+
+struct _element {
+ struct _element *next;
+ struct _element *prev;
+ void *data;
+};
+
+struct _list {
+ struct _element *head;
+ struct _element *tail;
+ unsigned int count;
+ void (*free) (void *);
+ void (*dump) (void *);
+};
+
+/* utility macro */
+#define ELEMENT_NEXT(E) ((E) = (E)->next)
+#define ELEMENT_DATA(E) ((E)->data)
+#define LIST_HEAD(L) ((L)->head)
+#define LIST_TAIL_DATA(L) ((L)->tail->data)
+#define LIST_ISEMPTY(L) ((L) == NULL || ((L)->head == NULL && (L)->tail == NULL))
+#define LIST_SIZE(V) ((V)->count)
+
+/* Prototypes */
+extern list alloc_list(void (*free_func) (void *), void (*dump_func) (void *));
+extern void free_list(list l);
+extern void *list_element(list l, int num);
+extern void dump_list(list l);
+extern void list_add(list l, void *data);
+
+#endif
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: main.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "main.h"
+#include "daemon.h"
#include "memory.h"
+#include "parser.h"
/* SIGHUP handler */
void sighup(int sig)
void sigchld(int sig)
{
int child;
-
wait(&child);
-/* child >>= 9;
- * if (child)
- * syslog(LOG_INFO, "Error from notify program, code:%d, %s"
- * , child, strerror(child));
- */
}
/* Signal wrapper */
signal_set (SIGCHLD, sigchld);
}
-/* Daemonization function coming from zebra source code */
-int daemon(int nochdir, int noclose)
-{
- pid_t pid;
-
- /* In case of fork is error. */
- pid = fork ();
- if (pid < 0) {
- perror ("fork");
- return -1;
- }
-
- /* In case of this is parent process. */
- if (pid != 0)
- exit (0);
-
- /* Become session leader and get pid. */
- pid = setsid();
- if (pid < -1) {
- perror ("setsid");
- return -1;
- }
-
- /* Change directory to root. */
- if (!nochdir)
- chdir ("/");
-
- /* File descriptor close. */
- if (! noclose) {
- int fd;
-
- fd = open ("/dev/null", O_RDWR, 0);
- if (fd != -1) {
- dup2 (fd, STDIN_FILENO);
- dup2 (fd, STDOUT_FILENO);
- dup2 (fd, STDERR_FILENO);
- if (fd > 2)
- close (fd);
- }
- }
-
- umask (0);
- return 0;
-}
-
/* Usage function */
static void usage(const char *prog)
{
- fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+ fprintf(stderr, VERSION_STRING);
fprintf(stderr,
- "Usage:\n"
+ "\nUsage:\n"
" %s\n"
" %s -n\n"
" %s -f keepalived.conf\n"
/* The first option car */
switch (c) {
case 'v':
- fprintf(stderr, "%s Version %s\n", PROG, VERSION);
+ fprintf(stderr, VERSION_STRING);
exit(0);
break;
case 'h':
/* Entry point */
int main(int argc, char **argv)
{
- configuration_data *conf_data;
char *conf_file = NULL;
thread thread;
openlog(PROG, LOG_PID | (debug & 1)?LOG_CONS:0
, LOG_DAEMON);
- syslog(LOG_INFO, "Starting "PROG" v"VERSION);
+ syslog(LOG_INFO, "Starting "VERSION_STRING);
/* Check if keepalived is already running */
if (keepalived_running()) {
- syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+ syslog(LOG_INFO, "Stopping "VERSION_STRING);
closelog();
exit(0);
}
/* daemonize process */
- if (!(debug & 2)) {
- daemon(0, 0);
- }
+ if (!(debug & 2))
+ xdaemon(0, 0, 0);
/* write the pidfile */
if (!pidfile_write(getpid())) {
- syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+ syslog(LOG_INFO, "Stopping "VERSION_STRING);
closelog();
exit(0);
}
+ /* Signal handling initialization */
+ signal_init();
+
+ /* Create the master thread */
+ master = thread_make_master();
+
/* Parse the configuration file */
- if (!(conf_data = (configuration_data *)conf_reader(conf_file))) {
- syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+ init_checkers_queue();
+ init_keywords();
+ init_data(conf_file);
+ if (!conf_data) {
+ syslog(LOG_INFO, "Stopping "VERSION_STRING);
closelog();
+ thread_destroy_master(master);
+ keepalived_free_final();
exit(0);
}
/* SSL load static data & initialize common ctx context */
- if (!(conf_data->ssldata = init_ssl_ctx(conf_data->ssldata))) {
+ if (!init_ssl_ctx()) {
closelog();
+ thread_destroy_master(master);
+ keepalived_free_final();
exit(0);
}
if (debug & 4)
- dump_conf(conf_data);
+ dump_data();
- if (!init_services(conf_data->lvstopology)) {
- syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+ if (!init_services()) {
+ syslog(LOG_INFO, "Stopping "VERSION_STRING);
closelog();
- clear_conf(conf_data);
+ free_data();
exit(0);
}
- /* Signal handling initialization */
- signal_init();
-
- /* Create the master thread */
- master = thread_make_master();
-
- /* registering worker threads */
- register_worker_thread(master, conf_data);
+ /* register workers threads */
+ register_checkers_thread();
+ vrrp_complete_init();
+ register_vrrp_thread();
/* processing the master thread queues, return and execute one ready thread */
while(thread_fetch(master, &thread)) {
}
/* Reached when terminate signal catched */
- syslog(LOG_INFO, "Stopping "PROG" v"VERSION);
+ syslog(LOG_INFO, "Stopping "VERSION_STRING);
/* Just cleanup memory & exit */
+ free_checkers_queue();
thread_destroy_master(master);
- clear_services(conf_data->lvstopology);
- clear_vrrp_instance(conf_data->vrrp);
- clear_ssl(conf_data->ssldata);
- clear_conf(conf_data);
+ clear_services();
+ shutdown_vrrp_instances();
+ free_data();
pidfile_rm();
*
* Part: Main program include file.
*
- * Version: $Id: main.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: main.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local includes */
#include "utils.h"
#include "pidfile.h"
-#include "cfreader.h"
+#include "data.h"
#include "scheduler.h"
#include "ipwrapper.h"
#include "smtp.h"
#include "vrrp.h"
-#include "check_ssl.h"
+#include "check_api.h"
+//#include "check_ssl.h"
/* global var */
thread_master *master;
unsigned int debug;
+data *conf_data;
-/* SSL support */
+/* extern prototypes */
extern void clear_ssl(SSL_DATA *ssl);
-extern SSL_DATA *init_ssl_ctx(SSL_DATA *ssl);
+extern int init_ssl_ctx(void);
+extern void register_vrrp_thread(void);
/* Build version */
-#define PROG "keepalived"
-#define VERSION "0.4.9a (20/12, 2001)"
+#define PROG "Keepalived"
+#define VERSION_CODE 0x000503
+#define DATE_CODE 0x160202
+
+#define KEEPALIVED_VERSION(version) \
+ (version >> 16) & 0xFF, \
+ (version >> 8) & 0xFF, \
+ version & 0xFF
+
+#define VERSION_STRING PROG" v%d.%d.%d (%.2d/%.2d, 20%.2d)", \
+ KEEPALIVED_VERSION(VERSION_CODE), \
+ KEEPALIVED_VERSION(DATE_CODE)
#endif
* Part: Memory management framework. This framework is used to
* find any memory leak.
*
- * Version: $Id: memory.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: memory.c,v 0.5.3 2002/02/24 23:50:11 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.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: memory.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
#endif
+/* Common defines */
+#define FREE_PTR(P) if((P)) FREE((P));
+
#endif
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Configuration file parser/reader. Place into the dynamic
+ * data structure representation the conf file representing
+ * the loadbalanced server pool.
+ *
+ * Version: $Id: parser.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "parser.h"
+#include "memory.h"
+#include "vrrp.h"
+#include "check_api.h"
+
+/* global defs */
+static vector keywords;
+static int sublevel = 0;
+static FILE *stream;
+extern data *conf_data;
+
+static void keyword_alloc(vector keywords, char *string, void (*handler)(vector))
+{
+ struct keyword *keyword;
+
+ vector_alloc_slot(keywords);
+
+ keyword = (struct keyword *)MALLOC(sizeof(struct keyword));
+ keyword->string = string;
+ keyword->handler = handler;
+
+ vector_set_slot(keywords, keyword);
+}
+
+static void install_keyword_root(char *string, void (*handler)(vector))
+{
+ keyword_alloc(keywords, string, handler);
+}
+
+void install_sublevel(void)
+{
+ sublevel++;
+}
+void install_sublevel_end(void)
+{
+ sublevel--;
+}
+
+void install_keyword(char *string, void (*handler)(vector))
+{
+ int i = 0;
+ struct keyword *keyword;
+
+ /* fetch last keyword */
+ keyword = VECTOR_SLOT(keywords, VECTOR_SIZE(keywords)-1);
+
+ /* position to last sub level */
+ for (i = 0; i < sublevel; i++)
+ keyword = VECTOR_SLOT(keyword->sub, VECTOR_SIZE(keyword->sub)-1);
+
+ /* First sub level allocation */
+ if (!keyword->sub)
+ keyword->sub = vector_alloc();
+
+ /* add new sub keyword */
+ keyword_alloc(keyword->sub, string, handler);
+}
+
+static void dump_keywords(vector keydump, int level)
+{
+ int i, j;
+ struct keyword *keyword;
+
+ for (i = 0; i < VECTOR_SIZE(keydump); i++) {
+ keyword = VECTOR_SLOT(keydump, i);
+ for (j = 0; j < level; j++) printf(" ");
+ printf ("Keyword : %s\n", keyword->string);
+ if (keyword->sub)
+ dump_keywords(keyword->sub, level+1);
+ }
+}
+
+static void free_keywords(vector keywords)
+{
+ int i;
+ struct keyword *keyword;
+
+ for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+ keyword = VECTOR_SLOT(keywords, i);
+ if (keyword->sub)
+ free_keywords(keyword->sub);
+ FREE(keyword);
+ }
+ vector_free(keywords);
+}
+
+/*
+static void dump_strvec(vector strvec)
+{
+ int i;
+ char *str;
+
+ if (!strvec)
+ return;
+
+ printf("String Vector : ");
+
+ for (i = 0; i < VECTOR_SIZE(strvec); i++) {
+ str = VECTOR_SLOT(strvec, i);
+ printf("[%i]=%s ", i, str);
+ }
+ printf("\n");
+}
+*/
+
+static void free_strvec(vector strvec)
+{
+ int i;
+ char *str;
+
+ if (!strvec)
+ return;
+
+ for (i=0; i < VECTOR_SIZE(strvec); i++)
+ if ((str = VECTOR_SLOT(strvec, i)) != NULL)
+ FREE(str);
+
+ vector_free(strvec);
+}
+
+static vector alloc_strvec(char *string)
+{
+ char *cp, *start, *token;
+ int strlen;
+ vector strvec;
+
+ if (!string)
+ return NULL;
+
+ cp = string;
+
+ /* Skip white spaces */
+ while ((isspace((int) *cp) || *cp == '\r' || *cp == '\n') &&
+ *cp != '\0')
+ cp++;
+
+ /* Return if there is only white spaces */
+ if (*cp == '\0')
+ return NULL;
+
+ /* Return if string begin with a comment */
+ if (*cp == '!' || *cp == '#')
+ return NULL;
+
+ /* Create a vector and alloc each command piece */
+ strvec = vector_alloc();
+
+ while (1) {
+ start = cp;
+ while (!(isspace((int) *cp) || *cp == '\r' || *cp == '\n') &&
+ *cp != '\0')
+ cp++;
+ strlen = cp - start;
+ token = MALLOC(strlen + 1);
+ memcpy(token, start, strlen);
+ *(token + strlen) = '\0';
+
+ /* Alloc & set the slot */
+ vector_alloc_slot(strvec);
+ vector_set_slot(strvec, token);
+
+ while ((isspace((int) *cp) || *cp == '\n' || *cp == '\r') &&
+ *cp != '\0')
+ cp++;
+ if (*cp == '\0' || *cp == '!' || *cp == '#')
+ return strvec;
+ }
+}
+
+static char *read_line(char *buf, int size)
+{
+ return(fgets(buf, size, stream));
+}
+
+vector read_value_block(void)
+{
+ char buf[BUFSIZ];
+ int i;
+ char *str = NULL;
+ char *dup;
+ vector vec = NULL;
+ vector elements = vector_alloc();
+
+ while (read_line(buf, BUFSIZ)) {
+ vec = alloc_strvec(buf);
+ str = VECTOR_SLOT(vec, 0);
+ if (!strcmp(str, EOB)) {
+ free_strvec(vec);
+ break;
+ }
+
+ if (VECTOR_SIZE(vec))
+ for (i = 0; i < VECTOR_SIZE(vec); i++) {
+ str = VECTOR_SLOT(vec, i);
+ dup = (char *)MALLOC(strlen(str)+1);
+ memcpy(dup, str, strlen(str));
+ vector_alloc_slot(elements);
+ vector_set_slot(elements, dup);
+ }
+ free_strvec(vec);
+ }
+
+ return elements;
+}
+
+void *set_value(vector strvec)
+{
+ char *str = VECTOR_SLOT(strvec, 1);
+ int size = strlen(str);
+ void *alloc;
+
+ alloc = MALLOC(size+1);
+ memcpy(alloc, str, size);
+ return alloc;
+}
+
+/* data handlers */
+/* Global def handlers */
+static void lvsid_handler(vector strvec)
+{
+ conf_data->lvs_id = set_value(strvec);
+}
+static void emailfrom_handler(vector strvec)
+{
+ conf_data->email_from = set_value(strvec);
+}
+static void smtpto_handler(vector strvec)
+{
+ conf_data->smtp_connection_to = atoi(VECTOR_SLOT(strvec, 1));
+}
+static void smtpip_handler(vector strvec)
+{
+ conf_data->smtp_server = inet_addr(VECTOR_SLOT(strvec, 1));
+}
+static void email_handler(vector strvec)
+{
+ vector email = read_value_block();
+ int i;
+ char *str;
+
+ for (i = 0; i < VECTOR_SIZE(email); i++) {
+ str = VECTOR_SLOT(email, i);
+ alloc_email(str);
+ }
+
+ free_strvec(email);
+}
+
+/* SSL handlers */
+static void ssl_handler(vector strvec)
+{
+ conf_data->ssl = alloc_ssl();
+}
+static void sslpass_handler(vector strvec)
+{
+ conf_data->ssl->password = set_value(strvec);
+}
+static void sslca_handler(vector strvec)
+{
+ conf_data->ssl->cafile = set_value(strvec);
+}
+static void sslcert_handler(vector strvec)
+{
+ conf_data->ssl->certfile = set_value(strvec);
+}
+static void sslkey_handler(vector strvec)
+{
+ conf_data->ssl->keyfile = set_value(strvec);
+}
+
+/* VRRP handlers */
+static void vrrp_handler(vector strvec)
+{
+ alloc_vrrp(VECTOR_SLOT(strvec, 1));
+}
+static void vrrp_isync_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->isync = set_value(strvec);
+}
+static void vrrp_state_handler(vector strvec)
+{
+ char *str = VECTOR_SLOT(strvec, 1);
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp_rt *rt = vrrp->vsrv;
+
+ if (!strcmp(str, "MASTER")) {
+ rt->wantstate = VRRP_STATE_MAST;
+ rt->init_state = VRRP_STATE_MAST;
+ } else {
+ rt->wantstate = VRRP_STATE_BACK;
+ rt->init_state = VRRP_STATE_BACK;
+ }
+}
+static void vrrp_int_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->vif->ifname = set_value(strvec);
+}
+static void vrrp_vrid_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->vrid = atoi(VECTOR_SLOT(strvec, 1));
+
+ if (VRRP_IS_BAD_VID(vrrp->vsrv->vrid)) {
+ syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
+ syslog(LOG_INFO, " must be between 1 & 255. reconfigure !\n");
+ }
+}
+static void vrrp_prio_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->priority = atoi(VECTOR_SLOT(strvec, 1));
+
+ if (VRRP_IS_BAD_PRIORITY(vrrp->vsrv->priority)) {
+ syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
+ syslog(LOG_INFO, " must be between 1 & 255. reconfigure !\n");
+ syslog(LOG_INFO, " Using default value : 100\n");
+ vrrp->vsrv->priority = 100;
+ }
+}
+static void vrrp_adv_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->adver_int = atoi(VECTOR_SLOT(strvec, 1));
+
+ if (VRRP_IS_BAD_ADVERT_INT(vrrp->vsrv->adver_int)) {
+ syslog(LOG_INFO, "VRRP Error : Advert intervall not valid !\n");
+ syslog(LOG_INFO, " must be between less than 1sec.\n");
+ syslog(LOG_INFO, " Using default value : 1sec\n");
+ vrrp->vsrv->adver_int = 1;
+ }
+ vrrp->vsrv->adver_int *= TIMER_HZ;
+}
+static void vrrp_debug_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->debug = atoi(VECTOR_SLOT(strvec, 1));
+
+ if (VRRP_IS_BAD_DEBUG_INT(vrrp->vsrv->debug)) {
+ syslog(LOG_INFO, "VRRP Error : Debug intervall not valid !\n");
+ syslog(LOG_INFO, " must be between 0-4\n");
+ vrrp->vsrv->debug = 0;
+ }
+}
+static void vrrp_preempt_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ vrrp->vsrv->preempt = !vrrp->vsrv->preempt;
+}
+static void vrrp_notify_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ char *str = VECTOR_SLOT(strvec, 1);
+ int size = sizeof(vrrp->vsrv->notify_file);
+
+ memcpy(vrrp->vsrv->notify_file, str, size);
+ vrrp->vsrv->notify_exec = 1;
+}
+static void vrrp_auth_type_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ char *str = VECTOR_SLOT(strvec, 1);
+
+ if (!strcmp(str, "AH"))
+ vrrp->vsrv->vif->auth_type = VRRP_AUTH_AH;
+ else
+ vrrp->vsrv->vif->auth_type = VRRP_AUTH_PASS;
+}
+static void vrrp_auth_pass_handler(vector strvec)
+{
+ vrrp_instance *vrrp = LIST_TAIL_DATA(conf_data->vrrp);
+ char *str = VECTOR_SLOT(strvec, 1);
+ int size = sizeof(vrrp->vsrv->vif->auth_data);
+
+ memcpy(vrrp->vsrv->vif->auth_data, str, size);
+}
+static void vrrp_vip_handler(vector strvec)
+{
+ vector vips = read_value_block();
+ int i;
+ char *str;
+
+ for (i = 0; i < VECTOR_SIZE(vips); i++) {
+ str = VECTOR_SLOT(vips, i);
+ alloc_vrrp_vip(str);
+ }
+
+ free_strvec(vips);
+}
+
+/* Virtual Servers handlers */
+static void vs_handler(vector strvec)
+{
+ alloc_vs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+static void delay_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1));
+}
+static void lbalgo_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ char *str = VECTOR_SLOT(strvec, 1);
+ int size = sizeof(vs->sched);
+
+ memcpy(vs->sched, str, size);
+}
+static void lbkind_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ char *str = VECTOR_SLOT(strvec, 1);
+
+#ifdef _KRNL_2_2_
+ if (!strcmp(str, "NAT"))
+ vs->loadbalancing_kind = 0;
+ else
+ if (!strcmp(str, "DR"))
+ vs->loadbalancing_kind = IP_MASQ_F_VS_DROUTE;
+ else
+ if (!strcmp(str, "TUN"))
+ vs->loadbalancing_kind = IP_MASQ_F_VS_TUNNEL;
+#else
+ if (!strcmp(str, "NAT"))
+ vs->loadbalancing_kind = IP_VS_CONN_F_MASQ;
+ else
+ if (!strcmp(str, "DR"))
+ vs->loadbalancing_kind = IP_VS_CONN_F_DROUTE;
+ else
+ if (!strcmp(str, "TUN"))
+ vs->loadbalancing_kind = IP_VS_CONN_F_TUNNEL;
+#endif
+ else
+ syslog(LOG_DEBUG, "PARSER : unknown [%s] routing method."
+ , str);
+}
+static void natmask_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ vs->nat_mask = inet_addr(VECTOR_SLOT(strvec, 1));
+}
+static void pto_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ char *str = VECTOR_SLOT(strvec, 1);
+ int size = sizeof(vs->timeout_persistence);
+
+ memcpy(vs->timeout_persistence, str, size);
+
+}
+static void proto_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ char *str = VECTOR_SLOT(strvec, 1);
+ vs->service_type = (!strcmp(str, "TCP"))?IPPROTO_TCP:IPPROTO_UDP;
+}
+
+/* Sorry Servers handlers */
+static void ssvr_handler(vector strvec)
+{
+ alloc_ssvr(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+
+/* Real Servers handlers */
+static void rs_handler(vector strvec)
+{
+ alloc_rs(VECTOR_SLOT(strvec, 1), VECTOR_SLOT(strvec, 2));
+}
+static void weight_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(conf_data->vs);
+ real_server *rs = LIST_TAIL_DATA(vs->rs);
+ rs->weight = atoi(VECTOR_SLOT(strvec, 1));
+}
+
+/* recursive configuration stream handler */
+static void process_stream(vector keywords)
+{
+ int i;
+ struct keyword *keyword;
+ char *str;
+ char buf[BUFSIZ];
+ vector strvec;
+
+ if (!read_line(buf, BUFSIZ))
+ return;
+
+ strvec = alloc_strvec(buf);
+
+ if (!strvec) {
+ process_stream(keywords);
+ return;
+ }
+
+ str = VECTOR_SLOT(strvec, 0);
+
+ if (!strcmp(str, EOB)) {
+ free_strvec(strvec);
+ return;
+ }
+
+ for (i = 0; i < VECTOR_SIZE(keywords); i++) {
+ keyword = VECTOR_SLOT(keywords, i);
+
+ if (!strcmp(keyword->string, str)) {
+ if (keyword->handler)
+ (*keyword->handler) (strvec);
+
+ if (keyword->sub)
+ process_stream(keyword->sub);
+ break;
+ }
+ }
+
+ free_strvec(strvec);
+ process_stream(keywords);
+}
+
+void init_keywords(void)
+{
+ keywords = vector_alloc();
+
+ /* global definitions mapping */
+ install_keyword_root("global_defs", NULL);
+ install_keyword("lvs_id", &lvsid_handler);
+ install_keyword("notification_email_from", &emailfrom_handler);
+ install_keyword("smtp_server", &smtpip_handler);
+ install_keyword("smtp_connect_timeout", &smtpto_handler);
+ install_keyword("notification_email", &email_handler);
+
+ /* SSL mapping */
+ install_keyword_root("SSL", &ssl_handler);
+ install_keyword("password", &sslpass_handler);
+ install_keyword("ca", &sslca_handler);
+ install_keyword("certificate", &sslcert_handler);
+ install_keyword("key", &sslkey_handler);
+
+ /* VRRP Instance mapping */
+ install_keyword_root("vrrp_instance", &vrrp_handler);
+ install_keyword("state", &vrrp_state_handler);
+ install_keyword("interface", &vrrp_int_handler);
+ install_keyword("virtual_router_id", &vrrp_vrid_handler);
+ install_keyword("priority", &vrrp_prio_handler);
+ install_keyword("advert_int", &vrrp_adv_handler);
+ install_keyword("virtual_ipaddress", &vrrp_vip_handler);
+ install_keyword("sync_instance", &vrrp_isync_handler);
+ install_keyword("preempt", &vrrp_preempt_handler);
+ install_keyword("debug", &vrrp_debug_handler);
+ install_keyword("notify", &vrrp_notify_handler);
+ install_keyword("authentication", NULL);
+ install_sublevel();
+ install_keyword("auth_type", &vrrp_auth_type_handler);
+ install_keyword("auth_pass", &vrrp_auth_pass_handler);
+ install_sublevel_end();
+
+ /* Virtual server mapping */
+ install_keyword_root("virtual_server", &vs_handler);
+ install_keyword("delay_loop", &delay_handler);
+ install_keyword("lb_algo", &lbalgo_handler);
+ install_keyword("lb_kind", &lbkind_handler);
+ install_keyword("nat_mask", &natmask_handler);
+ install_keyword("persistence_timeout", &pto_handler);
+ install_keyword("protocol", &proto_handler);
+
+ /* Real server mapping */
+ install_keyword("sorry_server", &ssvr_handler);
+ install_keyword("real_server", &rs_handler);
+ install_sublevel();
+ install_keyword("weight", &weight_handler);
+
+ /* Checkers mapping */
+ install_checkers_keyword();
+}
+
+void init_data(char *conf_file)
+{
+ conf_data = NULL;
+ stream = fopen((conf_file)?conf_file:CONF, "r");
+ if (!stream) {
+ syslog(LOG_INFO, "Configuration file open problem...\n");
+ return;
+ }
+
+ /* Init data structure */
+ conf_data = alloc_data();
+
+ /* Stream handling */
+ process_stream(keywords);
+
+/* Dump configuration *
+
+ vector_dump(keywords);
+ dump_keywords(keywords, 0);
+ free_keywords(keywords);
+*/
+
+ fclose(stream);
+ free_keywords(keywords);
+}
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: cfreader.c include file.
+ *
+ * Version: $Id: parser.h,v 0.5.3 2002/02/24 23:50:11 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 _PARSER_H
+#define _PARSER_H
+
+/* system includes */
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <ctype.h>
+
+/* local includes */
+#include "data.h"
+#include "vector.h"
+
+/* Global definitions */
+#define CONF "/etc/keepalived/keepalived.conf"
+#define EOB "}"
+
+/* ketword definition */
+struct keyword {
+ char *string;
+ void (*handler) (vector);
+ vector sub;
+};
+
+
+/* Prototypes */
+extern void init_keywords(void);
+extern void init_data(char *conf_file);
+extern void install_keyword(char *string, void (*handler)(vector));
+extern void install_sublevel(void);
+extern void install_sublevel_end(void);
+extern void *set_value(vector strvec);
+
+#endif
*
* Part: pidfile utility.
*
- * Version: $Id: pidfile.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: pidfile.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile.c include file.
*
- * Version: $Id: pidfile.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: pidfile.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* the thread management routine (thread.c) present in the
* very nice zebra project (http://www.zebra.org).
*
- * Version: $Id: scheduler.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
thread_master *new;
new = (thread_master *)MALLOC(sizeof(thread_master));
-
- return new;
-}
-
-/* Make a new http thread arg */
-http_thread_arg *thread_http_checker_arg_new(void)
-{
- http_thread_arg *new;
-
- /* Allocate & prepare the thread argument structure */
- new = (http_thread_arg *)MALLOC(sizeof(http_thread_arg));
-
- return new;
-}
-
-/* Make a new global thread arg */
-thread_arg *thread_arg_new(configuration_data *root
- , virtualserver *vserver
- , realserver *rserver)
-{
- thread_arg *new;
-
- /* Allocate & prepare the thread argument structure */
- new = (thread_arg *)MALLOC(sizeof(thread_arg));
-
- /* Assign structure elements */
- new->root = root;
- new->vs = vserver;
- new->svr = rserver;
- new->checker_arg = NULL;
-
return new;
}
list->count++;
}
-/* timer compare */
-int thread_timer_cmp(TIMEVAL a, TIMEVAL b)
-{
- if (a.tv_sec > b.tv_sec)
- return 1;
- if (a.tv_sec < b.tv_sec)
- return -1;
- if (a.tv_usec > b.tv_usec)
- return 1;
- if (a.tv_usec < b.tv_usec)
- return -1;
- return 0;
-}
-
/* Add a thread in the list sorted by timeval */
void thread_list_add_timeval(thread_list *list, thread *thread)
{
struct _thread *tt;
for (tt = list->head; tt; tt = tt->next)
- if (thread_timer_cmp (thread->sands, tt->sands) <= 0)
+ if (timer_cmp (thread->sands, tt->sands) <= 0)
break;
if (tt)
thread = m->unuse.head;
while (thread) {
struct _thread *t;
- thread_arg *ta;
t = thread;
thread = t->next;
thread_list_delete(&m->unuse, t);
- ta = t->arg;
-
- /* thread_arg memory cleanup */
- if (ta) {
- if (ta->checker_arg)
- FREE(ta->checker_arg);
- /* Free the arg if it is a thread_arg entry. */
- if (ta->vs)
- FREE(ta);
- }
/* free the thread */
FREE(t);
, long timer)
{
thread *thread;
- TIMEVAL timer_now;
+ TIMEVAL time_now;
assert(m != NULL);
thread->u.fd = fd;
/* Compute read timeout value */
- gettimeofday(&timer_now, NULL);
+ time_now = timer_now();
if (timer >= TIMER_MAX_SEC) {
- timer_now.tv_sec += timer / TIMER_SEC_MICRO;
- timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+ time_now.tv_sec += timer / TIMER_HZ;
+ time_now.tv_usec += timer % TIMER_HZ;
} else
- timer_now.tv_sec += timer;
+ time_now.tv_sec += timer;
- thread->sands = timer_now;
+ thread->sands = time_now;
/* Sort the thread. */
thread_list_add_timeval(&m->read, thread);
, long timer)
{
thread *thread;
- TIMEVAL timer_now;
+ TIMEVAL time_now;
assert(m != NULL);
thread->u.fd = fd;
/* Compute write timeout value */
- gettimeofday(&timer_now,NULL);
+ time_now = timer_now();
if (timer >= TIMER_MAX_SEC) {
- timer_now.tv_sec += timer / TIMER_SEC_MICRO;
- timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+ time_now.tv_sec += timer / TIMER_HZ;
+ time_now.tv_usec += timer % TIMER_HZ;
} else
- timer_now.tv_sec += timer;
+ time_now.tv_sec += timer;
- thread->sands = timer_now;
+ thread->sands = time_now;
/* Sort the thread. */
thread_list_add_timeval(&m->write, thread);
, long timer)
{
thread *thread;
- TIMEVAL timer_now;
+ TIMEVAL time_now;
assert(m != NULL);
thread->arg = arg;
/* Do we need jitter here? */
- gettimeofday (&timer_now, NULL);
+ time_now = timer_now();
if (timer >= TIMER_MAX_SEC) {
- timer_now.tv_sec += timer / TIMER_SEC_MICRO;
- timer_now.tv_usec += timer % TIMER_SEC_MICRO;
+ time_now.tv_sec += timer / TIMER_HZ;
+ time_now.tv_usec += timer % TIMER_HZ;
} else
- timer_now.tv_sec += timer;
+ time_now.tv_sec += timer;
- thread->sands = timer_now;
+ thread->sands = time_now;
/* Sort by timeval. */
thread_list_add_timeval(&m->timer, thread);
}
}
-/* timer sub */
-TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b)
-{
- TIMEVAL ret;
-
- ret.tv_usec = a.tv_usec - b.tv_usec;
- ret.tv_sec = a.tv_sec - b.tv_sec;
-
- if (ret.tv_usec < 0) {
- ret.tv_usec += TIMER_SEC_MICRO;
- ret.tv_sec--;
- }
-
- return ret;
-}
-
-static int thread_timer_null(TIMEVAL timer)
-{
- if (timer.tv_sec == 0 && timer.tv_usec == 0)
- return 1;
- else
- return 0;
-}
-
/* Compute the wait timer. Take care of timeouted fd */
TIMEVAL *thread_compute_timer(thread_master *m, TIMEVAL *timer_wait)
{
- TIMEVAL timer_now;
+ TIMEVAL time_now;
TIMEVAL timer_min;
- timer_min.tv_sec = 0;
- timer_min.tv_usec = 0;
- gettimeofday (&timer_now, NULL);
+ TIMER_RESET(timer_min);
+ time_now = timer_now();
if (m->timer.head)
timer_min = m->timer.head->sands;
if (m->write.head) {
- if (!thread_timer_null(timer_min)) {
- if (thread_timer_cmp(m->write.head->sands, timer_min) <= 0)
+ if (!TIMER_ISNULL(timer_min)) {
+ if (timer_cmp(m->write.head->sands, timer_min) <= 0)
timer_min = m->write.head->sands;
} else
timer_min = m->write.head->sands;
}
if (m->read.head) {
- if (!thread_timer_null(timer_min)) {
- if (thread_timer_cmp(m->read.head->sands, timer_min) <= 0)
+ if (!TIMER_ISNULL(timer_min)) {
+ if (timer_cmp(m->read.head->sands, timer_min) <= 0)
timer_min = m->read.head->sands;
} else
timer_min = m->read.head->sands;
}
- if (!thread_timer_null(timer_min)) {
- timer_min = thread_timer_sub (timer_min, timer_now);
+ if (!TIMER_ISNULL(timer_min)) {
+ timer_min = timer_sub (timer_min, time_now);
if (timer_min.tv_sec < 0) {
timer_min.tv_sec = 0;
timer_min.tv_usec = 10;
fd_set readfd;
fd_set writefd;
fd_set exceptfd;
- TIMEVAL timer_now;
+ TIMEVAL time_now;
TIMEVAL *timer_wait;
assert(m != NULL);
timer_wait = thread_compute_timer(m, timer_wait);
/* Call select function. */
- readfd = m->readfd;
- writefd = m->writefd;
+ readfd = m->readfd;
+ writefd = m->writefd;
exceptfd = m->exceptfd;
ret = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
}
/* Read thead. */
- gettimeofday (&timer_now, NULL);
+ time_now = timer_now();
thread = m->read.head;
while (thread) {
thread_list_add (&m->ready, t);
t->type = THREAD_READY;
} else {
- if (thread_timer_cmp(timer_now, t->sands) >= 0) {
+ if (timer_cmp(time_now, t->sands) >= 0) {
FD_CLR(t->u.fd, &m->readfd);
thread_list_delete (&m->read, t);
thread_list_add (&m->ready, t);
}
/* Write thead. */
- gettimeofday (&timer_now, NULL);
+ time_now = timer_now();
thread = m->write.head;
while (thread) {
thread_list_add (&m->ready, t);
t->type = THREAD_READY;
} else {
- if (thread_timer_cmp(timer_now, t->sands) >= 0) {
+ if (timer_cmp(time_now, t->sands) >= 0) {
FD_CLR(t->u.fd, &m->writefd);
thread_list_delete (&m->write, t);
thread_list_add (&m->ready, t);
/*...*/
/* Timer update. */
- gettimeofday (&timer_now, NULL);
+ time_now = timer_now();
thread = m->timer.head;
while (thread) {
t = thread;
thread = t->next;
- if (thread_timer_cmp (timer_now, t->sands) >= 0) {
+ if (timer_cmp (time_now, t->sands) >= 0) {
thread_list_delete (&m->timer, t);
thread_list_add (&m->ready, t);
t->type = THREAD_READY;
void thread_call(thread *thread)
{
thread->id = thread_get_id ();
- (*thread->func)(thread);
-}
-
-/* Register worker thread. One per realserver of each virtualserver */
-void register_vs_worker_thread(thread_master *master
- , configuration_data *root
- , virtualserver *lstptr)
-{
- realserver *pointersvr;
- thread_arg *thread_arg;
-
- pointersvr = lstptr->svr;
-
- while (lstptr->svr) {
-
- switch (lstptr->svr->method->type) {
- /* Implemented section */
- case TCP_CHECK_ID:
- case HTTP_GET_ID:
- case SSL_GET_ID:
- case MISC_CHECK_ID:
- thread_arg = thread_arg_new(root, lstptr, lstptr->svr);
-
- switch (lstptr->svr->method->type ) {
- case TCP_CHECK_ID:
- thread_add_timer(master, tcp_connect_thread, thread_arg
- , BOOTSTRAP_DELAY);
- break;
- case HTTP_GET_ID:
- case SSL_GET_ID:
- thread_arg->checker_arg = (http_thread_arg *)thread_http_checker_arg_new();
- thread_add_timer(master, http_connect_thread, thread_arg
- , BOOTSTRAP_DELAY);
- break;
- case MISC_CHECK_ID:
- thread_add_timer(master, misc_check_thread, thread_arg
- , BOOTSTRAP_DELAY);
- break;
- }
-
- break;
-
- /* Not yet implemented section */
- case LDAP_GET_ID:
- break;
- default:
- break;
- }
-
- lstptr->svr = (realserver *)lstptr->svr->next;
- }
-
- lstptr->svr = pointersvr;
-}
-
-/* Register each virtualserver realservers worker thread */
-void register_worker_thread(thread_master *master, configuration_data *lstptr)
-{
- virtualserver *pointervs;
-
- /* register VRRP instances dispatcher */
- if (lstptr->vrrp)
- thread_add_event(master, vrrp_dispatcher_init_thread,
- lstptr->vrrp, VRRP_DISPATCHER);
-
- /* register VS specifics threads */
- pointervs = lstptr->lvstopology;
- while (lstptr->lvstopology) {
- register_vs_worker_thread(master, lstptr, lstptr->lvstopology);
-
- lstptr->lvstopology = (virtualserver *)lstptr->lvstopology->next;
- }
- lstptr->lvstopology = pointervs;
+ (*thread->func) (thread);
}
*
* Part: scheduler.c include file.
*
- * Version: $Id: scheduler.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
-
-/* local includes */
-#include "cfreader.h"
-#include "check.h"
+#include <syslog.h>
+#include "timer.h"
/* Thread itself. */
-typedef struct timeval TIMEVAL;
typedef struct _thread {
unsigned long id;
unsigned char type; /* thread type */
#define THREAD_TERMINATE 8
/* MICRO SEC def */
-#define TIMER_SEC_MICRO 1000000
-#define TIMER_MAX_SEC 1000
#define BOOTSTRAP_DELAY 1
/* Macros. */
#define THREAD_ARG(X) ((X)->arg)
-#define THREAD_ARG_CHECKER_ARG(X) ((X)->checker_arg)
#define THREAD_FD(X) ((X)->u.fd)
#define THREAD_VAL(X) ((X)->u.val)
/* Prototypes. */
thread_master *thread_make_master(void);
-
thread *thread_add_terminate_event(thread_master *m);
-
void thread_destroy_master(thread_master *m);
-
-thread_arg *thread_arg_new(configuration_data *root
- , virtualserver *vserver
- , realserver *rserver);
-
thread *thread_add_read(thread_master *m
, int (*func)(thread *)
, void *arg
, int fd
, long timeout);
-
thread *thread_add_write(thread_master *m
, int (*func)(thread *)
, void *arg
, int fd
, long timeout);
-
thread *thread_add_timer(thread_master *m
, int (*func)(thread *)
, void *arg
, long timer);
-
thread *thread_add_event(thread_master *m
, int (*func)(thread *)
, void *arg
, int val);
-
void thread_cancel(thread *thread);
-
void thread_cancel_event(thread_master *m, void *arg);
-
thread *thread_fetch(thread_master *m, thread *fetch);
-
void thread_call(thread *thread);
-int thread_timer_cmp(TIMEVAL a, TIMEVAL b);
-
-TIMEVAL thread_timer_sub(TIMEVAL a, TIMEVAL b);
-
-void register_worker_thread(thread_master *master
- , configuration_data *lstptr);
-
-/* extern prototypes */
-extern int tcp_connect_thread(thread *thread);
-extern int http_connect_thread(thread *thread);
-extern int ssl_connect_thread(thread *thread);
-extern int misc_check_thread(thread *thread);
-extern int vrrp_dispatcher_init_thread(thread *thread);
-
#endif
* 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.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: smtp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "smtp.h"
#include "memory.h"
+#include "list.h"
+
+extern data *conf_data;
/* static prototype */
-static int smtp_send_cmd_thread(thread *thread);
+static int smtp_send_cmd_thread(thread *);
-static void free_smtp_arg(smtp_thread_arg *smtp_arg)
+static void free_smtp_all(smtp_thread_arg *smtp_arg)
{
FREE(smtp_arg->subject);
FREE(smtp_arg->body);
FREE(smtp_arg);
}
-static void free_smtp_all(thread_arg *thread_arg)
+static char *fetch_next_email(smtp_thread_arg *smtp_arg)
{
- free_smtp_arg(THREAD_ARG_CHECKER_ARG(thread_arg));
- FREE(thread_arg);
-}
-
-static char *fetch_next_email(thread_arg *thread_arg)
-{
- smtp_thread_arg *smtp_arg;
- int i = 0;
-
- smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
-
- for (i=0; i<smtp_arg->email_it; i++)
- thread_arg->root->email = (notification_email *)thread_arg->root->email->next;
-
- if (thread_arg->root->email)
- return thread_arg->root->email->addr;
-
- return NULL;
+ return list_element(conf_data->email, smtp_arg->email_it);
}
static int smtp_read_cmd_thread(thread *thread)
{
- thread_arg *thread_arg;
smtp_thread_arg *smtp_arg;
- notification_email *pointeremail;
char *fetched_email;
long total_length = 0;
int rcv_buffer_size = 0;
char *buffer;
char *buffer_tmp;
- thread_arg = THREAD_ARG(thread);
- smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+ smtp_arg = THREAD_ARG(thread);
if (thread->type == THREAD_READ_TIMEOUT) {
#ifdef _DEBUG_
syslog(LOG_DEBUG, "Timeout reading data to remote SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
+ ip_ntoa(conf_data->smtp_server),
SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
return 0;
}
/* Allocate the get buffers */
- buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
+ buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
buffer_tmp = (char *)MALLOC(SMTP_BUFFER_LENGTH);
/* Cleanup the room */
if (rcv_buffer_size == -1) {
if (errno == EAGAIN) goto end;
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Error reading data to remote SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Error reading data to remote SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
FREE(buffer);
FREE(buffer_tmp);
if (total_length >= SMTP_BUFFER_MAX) {
#ifdef _DEBUG_
syslog(LOG_DEBUG, "Received buffer from remote SMTP server [%s:%d]"
- " overflow our get read buffer length.",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ " overflow our get read buffer length."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
FREE(buffer);
FREE(buffer_tmp);
/* setting the next stage */
switch (smtp_arg->stage) {
- case connection:
+ case CONNECTION:
if (memcmp(buffer, SMTP_CONNECT, 3) == 0) {
- smtp_arg->stage = helo;
+ smtp_arg->stage = HELO;
} else {
syslog(LOG_DEBUG, "Error connecting smtp server : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case helo:
+ case HELO:
if (memcmp(buffer, SMTP_HELO, 3) == 0) {
- smtp_arg->stage = mail;
+ smtp_arg->stage = MAIL;
} else {
syslog(LOG_DEBUG, "Error processing HELO cmd : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case mail:
+ case MAIL:
if (memcmp(buffer, SMTP_MAIL_FROM, 3) == 0) {
- smtp_arg->stage = rcpt;
+ smtp_arg->stage = RCPT;
} else {
syslog(LOG_DEBUG, "Error processing MAIL FROM cmd : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case rcpt:
+ case RCPT:
if (memcmp(buffer, SMTP_RCPT_TO, 3) == 0) {
smtp_arg->email_it++;
- pointeremail = thread_arg->root->email;
- fetched_email = fetch_next_email(thread_arg);
- thread_arg->root->email = pointeremail;
+ fetched_email = fetch_next_email(smtp_arg);
if (!fetched_email)
- smtp_arg->stage = data;
+ smtp_arg->stage = DATA;
} else {
syslog(LOG_DEBUG, "Error processing RCPT TO cmd : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case data:
+ case DATA:
if (memcmp(buffer, SMTP_DATA, 3) == 0) {
- smtp_arg->stage = body;
+ smtp_arg->stage = BODY;
} else {
syslog(LOG_DEBUG, "Error processing DATA cmd : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case body:
+ case BODY:
if (memcmp(buffer, SMTP_DOT, 3) == 0) {
- smtp_arg->stage = quit;
+ smtp_arg->stage = QUIT;
syslog(LOG_INFO, "SMTP alert successfully sent.");
} else {
syslog(LOG_DEBUG, "Error processing DOT cmd : [%s]", buffer);
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
}
break;
- case quit:
+ case QUIT:
/* final state, we are disconnected from the remote host */
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
FREE(buffer);
FREE(buffer_tmp);
return 0;
break;
- case error:
+ case ERROR:
break;
}
/* Registering next smtp command processing thread */
- thread_add_write(thread->master, smtp_send_cmd_thread, thread_arg, thread->u.fd,
- thread_arg->root->smtp_connection_to);
+ thread_add_write(thread->master, smtp_send_cmd_thread
+ , smtp_arg
+ , thread->u.fd
+ , conf_data->smtp_connection_to);
FREE(buffer);
FREE(buffer_tmp);
static int smtp_send_cmd_thread(thread *thread)
{
- thread_arg *thread_arg;
smtp_thread_arg *smtp_arg;
- notification_email *pointeremail;
char *fetched_email;
char *buffer;
- thread_arg = THREAD_ARG(thread);
- smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+ smtp_arg = THREAD_ARG(thread);
if (thread->type == THREAD_WRITE_TIMEOUT) {
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Timeout sending data to remote SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Timeout sending data to remote SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
return 0;
}
buffer = (char *)MALLOC(SMTP_BUFFER_MAX);
switch (smtp_arg->stage) {
- case connection:
+ case CONNECTION:
break;
- case helo:
- snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_HELO_CMD, get_local_name());
+ case HELO:
+ snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HELO_CMD, get_local_name());
if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case mail:
- snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_MAIL_CMD, thread_arg->root->email_from);
+ case MAIL:
+ snprintf(buffer, SMTP_BUFFER_MAX, SMTP_MAIL_CMD, conf_data->email_from);
if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case rcpt:
+ case RCPT:
/* We send RCPT TO command multiple time to add all our email receivers.
* --rfc821.3.1
*/
- pointeremail = thread_arg->root->email;
- fetched_email = fetch_next_email(thread_arg);
- thread_arg->root->email = pointeremail;
+ fetched_email = fetch_next_email(smtp_arg);
- snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_RCPT_CMD, fetched_email);
+ snprintf(buffer, SMTP_BUFFER_MAX, SMTP_RCPT_CMD, fetched_email);
if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case data:
+ case DATA:
if (send(thread->u.fd, SMTP_DATA_CMD, strlen(SMTP_DATA_CMD), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case body:
- snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_SUBJECT_CMD, smtp_arg->subject);
+ case BODY:
+ snprintf(buffer, SMTP_BUFFER_MAX, SMTP_HEADERS_CMD
+ , conf_data->email_from
+ , smtp_arg->subject);
/* send the subject field */
if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
memset(buffer, 0, SMTP_BUFFER_MAX);
- snprintf(buffer, TEMP_BUFFER_LENGTH, SMTP_BODY_CMD, smtp_arg->body);
+ snprintf(buffer, SMTP_BUFFER_MAX, SMTP_BODY_CMD, smtp_arg->body);
/* send the the body field */
if (send(thread->u.fd, buffer, strlen(buffer), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
/* send the sending dot */
if (send(thread->u.fd, SMTP_SEND_CMD, strlen(SMTP_SEND_CMD), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case quit:
+ case QUIT:
if (send(thread->u.fd, SMTP_QUIT_CMD, strlen(SMTP_QUIT_CMD), 0) == -1)
- smtp_arg->stage = error;
+ smtp_arg->stage = ERROR;
break;
- case error:
+ case ERROR:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Can not send data to remote SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
/* we just cleanup the room */
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(thread->u.fd);
FREE(buffer);
return 0;
//printf("Sending : %s", buffer);
/* Registering next smtp command processing thread */
- thread_add_read(thread->master, smtp_read_cmd_thread, thread_arg, thread->u.fd,
- thread_arg->root->smtp_connection_to);
+ thread_add_read(thread->master, smtp_read_cmd_thread
+ , smtp_arg
+ , thread->u.fd
+ , conf_data->smtp_connection_to);
FREE(buffer);
return 0;
/* SMTP checkers threads */
static int smtp_check_thread(thread *thread)
{
- thread_arg *thread_arg;
smtp_thread_arg *smtp_arg;
int status;
- thread_arg = THREAD_ARG(thread);
- smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+ smtp_arg = THREAD_ARG(thread);
- status = tcp_socket_state(thread->u.fd, thread, smtp_check_thread);
+ status = tcp_socket_state(thread->u.fd, thread
+ , conf_data->smtp_server
+ , htons(SMTP_PORT)
+ , smtp_check_thread);
switch (status) {
case connect_error:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Error connecting SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Error connecting SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
break;
case connect_timeout:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Timeout writing data to SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
break;
case connect_success:
* Register the next step thread smtp_cmd_thread.
*/
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected.",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Remote SMTP server [%s:%d] connected."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
-
- thread_add_write(thread->master, smtp_send_cmd_thread, thread_arg, thread->u.fd,
- thread_arg->root->smtp_connection_to);
+ thread_add_write(thread->master, smtp_send_cmd_thread
+ , smtp_arg
+ , thread->u.fd
+ , conf_data->smtp_connection_to);
break;
}
static int smtp_connect_thread(thread *thread)
{
- thread_arg *thread_arg;
smtp_thread_arg *smtp_arg;
enum connect_result status;
int fd;
- thread_arg = THREAD_ARG(thread);
- smtp_arg = THREAD_ARG_CHECKER_ARG(thread_arg);
+ smtp_arg = THREAD_ARG(thread);
if ( (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 ) {
#ifdef _DEBUG_
return 0;
}
- status = tcp_connect(fd, thread_arg->root->smtp_server.s_addr, htons(SMTP_PORT));
+ status = tcp_connect(fd, conf_data->smtp_server, htons(SMTP_PORT));
switch (status) {
case connect_error:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "SMTP connection ERROR to [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "SMTP connection ERROR to [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(fd);
return 0;
break;
case connect_timeout:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "Timeout connecting SMTP server [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "Timeout connecting SMTP server [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
- free_smtp_all(thread_arg);
- thread_arg->checker_arg = NULL;
+ free_smtp_all(smtp_arg);
close(fd);
return 0;
break;
case connect_success:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "SMTP connection SUCCESS to [%s:%d].",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "SMTP connection SUCCESS to [%s:%d]."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
break;
/* Checking non-blocking connect, we wait until socket is writable */
case connect_in_progress:
#ifdef _DEBUG_
- syslog(LOG_DEBUG, "SMTP connection to [%s:%d] now IN_PROGRESS.",
- inet_ntoa(thread_arg->root->smtp_server),
- SMTP_PORT);
+ syslog(LOG_DEBUG, "SMTP connection to [%s:%d] now IN_PROGRESS."
+ , ip_ntoa(conf_data->smtp_server)
+ , SMTP_PORT);
#endif
break;
}
/* connection have succeeded or still in progress */
- thread_add_write(thread->master, smtp_check_thread, thread_arg, fd,
- thread_arg->root->smtp_connection_to);
-
+ thread_add_write(thread->master, smtp_check_thread
+ , smtp_arg
+ , fd
+ , conf_data->smtp_connection_to);
return 1;
}
void smtp_alert(thread_master *master
- , configuration_data *root
- , realserver *rserver
+ , real_server *rs
, const char *subject
, const char *body)
{
- thread_arg *thread_arg;
smtp_thread_arg *smtp_arg;
/* Only send mail if email specified */
- if (root->email) {
- /* allocate a new thread_arg */
- thread_arg = thread_arg_new(root, NULL, NULL);
-
+ if (!LIST_ISEMPTY(conf_data->email)) {
/* allocate & initialize smtp argument data structure */
- smtp_arg = (smtp_thread_arg *)MALLOC(sizeof(smtp_thread_arg));
- smtp_arg->subject = (char *)MALLOC(MAX_SUBJECT_LENGTH);
- smtp_arg->body = (char *)MALLOC(MAX_BODY_LENGTH);
+ smtp_arg = (smtp_thread_arg *)MALLOC(sizeof(smtp_thread_arg));
+ smtp_arg->subject = (char *)MALLOC(MAX_HEADERS_LENGTH);
+ smtp_arg->body = (char *)MALLOC(MAX_BODY_LENGTH);
- smtp_arg->stage = connection; /* first smtp command set to HELO */
+ smtp_arg->stage = CONNECTION; /* first smtp command set to HELO */
/* format subject if rserver is specified */
- if (rserver)
- snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s:%d - %s",
- root->lvs_id, inet_ntoa(rserver->addr_ip), ntohs(rserver->addr_port), subject);
+ if (rs)
+ snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] %s:%d - %s"
+ , conf_data->lvs_id
+ , ip_ntoa(SVR_IP(rs))
+ , ntohs(SVR_PORT(rs))
+ , subject);
else
- snprintf(smtp_arg->subject, MAX_SUBJECT_LENGTH, "[%s] %s", root->lvs_id, subject);
+ snprintf(smtp_arg->subject, MAX_HEADERS_LENGTH, "[%s] %s"
+ , conf_data->lvs_id
+ , subject);
strncpy(smtp_arg->body, body, MAX_BODY_LENGTH);
- thread_arg->checker_arg = smtp_arg;
-
- thread_add_event(master, smtp_connect_thread, thread_arg, 0);
+ thread_add_event(master, smtp_connect_thread, smtp_arg, 0);
}
}
*
* Part: smtp.c include file.
*
- * Version: $Id: smtp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: smtp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* 2 of the License, or (at your option) any later version.
*/
-#ifndef _HTTP_H
-#define _HTTP_H
+#ifndef _SMTP_H
+#define _SMTP_H
/* globales includes */
#include <netdb.h>
#include <sys/utsname.h>
/* local includes */
-#include "cfreader.h"
+#include "data.h"
#include "scheduler.h"
#include "layer4.h"
/* command stage */
enum smtp_cmd {
- connection,
- helo,
- mail,
- rcpt,
- data,
- body,
- quit,
- error
+ CONNECTION,
+ HELO,
+ MAIL,
+ RCPT,
+ DATA,
+ BODY,
+ QUIT,
+ ERROR
};
/* SMTP thread argument structure */
-#define MAX_SUBJECT_LENGTH 256
+#define MAX_HEADERS_LENGTH 256
#define MAX_BODY_LENGTH 512
typedef struct _smtp_thread_arg {
/* Smtp command string processing */
#define SMTP_HELO_CMD "HELO %s\n"
-#define SMTP_MAIL_CMD "MAIL FROM:%s\n"
-#define SMTP_RCPT_CMD "RCPT TO:%s\n"
+#define SMTP_MAIL_CMD "MAIL FROM:<%s>\n"
+#define SMTP_RCPT_CMD "RCPT TO:<%s>\n"
#define SMTP_DATA_CMD "DATA\n"
-#define SMTP_SUBJECT_CMD "Subject: %s\nX-Mailer: Keepalived\n\n"
+#define SMTP_HEADERS_CMD "From: %s\nSubject: %s\nX-Mailer: Keepalived\n\n"
#define SMTP_BODY_CMD "\n\n%s\n\n"
#define SMTP_SEND_CMD "\n.\n"
#define SMTP_QUIT_CMD "QUIT\n"
/* Prototypes defs */
extern void smtp_alert(thread_master *
- , configuration_data *
- , realserver *
+ , real_server *
, const char *
, const char *);
-
#endif
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Timer manipulations.
+ *
+ * Version: $Id: timer.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include <string.h>
+#include "timer.h"
+
+/* set a timer to a specific value */
+TIMEVAL timer_dup(TIMEVAL b)
+{
+ TIMEVAL a;
+
+ TIMER_RESET(a);
+ a.tv_sec = b.tv_sec;
+ a.tv_usec = b.tv_usec;
+ return a;
+}
+
+/* timer compare */
+int timer_cmp(TIMEVAL a, TIMEVAL b)
+{
+ if (a.tv_sec > b.tv_sec)
+ return 1;
+ if (a.tv_sec < b.tv_sec)
+ return -1;
+ if (a.tv_usec > b.tv_usec)
+ return 1;
+ if (a.tv_usec < b.tv_usec)
+ return -1;
+ return 0;
+}
+
+/* timer sub */
+TIMEVAL timer_sub(TIMEVAL a, TIMEVAL b)
+{
+ TIMEVAL ret;
+
+ TIMER_RESET(ret);
+ ret.tv_usec = a.tv_usec - b.tv_usec;
+ ret.tv_sec = a.tv_sec - b.tv_sec;
+
+ if (ret.tv_usec < 0) {
+ ret.tv_usec += TIMER_HZ;
+ ret.tv_sec--;
+ }
+
+ return ret;
+}
+
+/* current time */
+TIMEVAL timer_now(void)
+{
+ TIMEVAL timer_now;
+
+ /* init timer */
+ TIMER_RESET(timer_now);
+ gettimeofday(&timer_now, NULL);
+
+ return timer_now;
+}
+
+/* timer sub from current time */
+TIMEVAL timer_sub_now(TIMEVAL a)
+{
+ return timer_sub(timer_now(), a);
+}
--- /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: timer.c include file.
+ *
+ * Version: $Id: timer.h,v 0.5.3 2002/02/24 23:50:11 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 _TIMER_H
+#define _TIMER_H
+
+#include <sys/time.h>
+
+typedef struct timeval TIMEVAL;
+
+/* macro utilities */
+#define TIMER_HZ 1000000
+#define TIMER_MAX_SEC 1000
+#define TIMER_SEC(T) ((T).tv_sec)
+#define TIMER_ISNULL(T) ((T).tv_sec == 0 && (T).tv_usec == 0)
+#define TIMER_RESET(T) (memset(&(T), 0, sizeof(struct timeval)))
+
+/* prototypes */
+extern TIMEVAL timer_now(void);
+extern TIMEVAL timer_dup(TIMEVAL b);
+extern int timer_cmp(TIMEVAL a, TIMEVAL b);
+extern TIMEVAL timer_sub(TIMEVAL a, TIMEVAL b);
+extern TIMEVAL timer_sub_now(TIMEVAL a);
+
+#endif
*
* Part: General program utils.
*
- * Version: $Id: utils.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: utils.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: utils.h include file.
*
- * Version: $Id: utils.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: utils.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
--- /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: Vector structure manipulation.
+ *
+ * Version: $Id: vector.c,v 0.5.3 2002/02/24 23:50:11 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.
+ */
+
+#include "vector.h"
+#include "memory.h"
+
+/*
+ * Initialize vector struct.
+ * allocalted 'size' slot elements then return vector.
+ */
+vector vector_alloc(void)
+{
+ vector v = (vector)MALLOC(sizeof(struct _vector));
+ return v;
+}
+
+/* allocated one slot */
+void vector_alloc_slot(vector v)
+{
+ v->allocated += VECTOR_DEFAULT_SIZE;
+ if (v->slot)
+ v->slot = REALLOC(v->slot, sizeof(void *) * v->allocated);
+ else
+ v->slot = (void *)MALLOC(sizeof(void *) * v->allocated);
+}
+
+/* Free memory vector allocation */
+void vector_free(vector v)
+{
+ FREE(v->slot);
+ FREE(v);
+}
+
+/* Set a vector slot value */
+void vector_set_slot(vector v, void *value)
+{
+ unsigned int i = v->allocated-1;
+
+ v->slot[i] = value;
+}
+
+/* dump vector slots */
+void vector_dump(vector v)
+{
+ int i;
+
+ printf("Vector Size : %d\n", v->allocated);
+
+ for (i = 0; i < v->allocated; i++)
+ if (v->slot[i] != NULL)
+ printf(" Slot [%d]: %p\n", i, VECTOR_SLOT(v, i));
+}
--- /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: vector.c include file.
+ *
+ * Version: $Id: vector.h,v 0.5.3 2002/02/24 23:50:11 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 _VECTOR_H
+#define _VECTOR_H
+
+/* vector definition */
+struct _vector {
+ unsigned int allocated;
+ void **slot;
+};
+typedef struct _vector *vector;
+
+#define VECTOR_DEFAULT_SIZE 1
+#define VECTOR_SLOT(V,E) ((V)->slot[(E)])
+#define VECTOR_SIZE(V) ((V)->allocated)
+
+/* Prototypes */
+extern vector vector_alloc(void);
+extern void vector_alloc_slot(vector v);
+extern void vector_free(vector v);
+extern void vector_set_slot(vector v, void *value);
+extern void vector_dump(vector v);
+
+#endif
* master fails, a backup server takes over.
* The original implementation has been made by jerome etienne.
*
- * Version: $Id: vrrp.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_scheduler.h"
#include "vrrp.h"
#include "memory.h"
+#include "list.h"
/* Close all FDs >= a specified value */
void closeall(int fd)
exit(0);
}
-
/* compute checksum */
static u_short in_csum( u_short *addr, int len, u_short csum)
{
int i, err = 0;
int retry;
int ifidx = ifname_to_idx(vsrv->vif->ifname);
- struct in_addr in;
for(i = 0; i < vsrv->naddr; i++ ) {
vip_addr *vadd = &vsrv->vaddr[i];
retry ^= retry;
if(!cmd && !vadd->deletable) continue;
retry:
- if (netlink_address_ipv4(ifidx , vadd->addr, cmd) < 0) {
+ if (netlink_address_ipv4(ifidx , ntohl(vadd->addr), cmd) < 0) {
err = 1;
vadd->deletable = 0;
- in.s_addr = htonl(vadd->addr);
syslog(LOG_INFO, "cant %s the address %s to %s\n"
, cmd ? "set" : "remove"
- , inet_ntoa(in)
+ , ip_ntoa(vadd->addr)
, vsrv->vif->ifname);
if (cmd == VRRP_IPADDRESS_ADD) {
syslog(LOG_INFO, "try to delete eventual stalled ip");
- netlink_address_ipv4(ifidx, vadd->addr, VRRP_IPADDRESS_DEL);
+ netlink_address_ipv4(ifidx, ntohl(vadd->addr), VRRP_IPADDRESS_DEL);
if (!retry) {
retry++;
goto retry;
* MUST verify that the Adver Interval in the packet is the same as
* the locally configured for this virtual router
*/
- if (vsrv->adver_int/VRRP_TIMER_HZ != hd->adver_int) {
+ if (vsrv->adver_int/TIMER_HZ != hd->adver_int) {
syslog(LOG_INFO, "advertissement interval mismatch mine=%d rcved=%d"
, vsrv->adver_int, hd->adver_int);
/* to prevent concurent VRID running => multiple master in 1 VRID */
hd->priority = prio;
hd->naddr = vsrv->naddr;
hd->auth_type = vsrv->vif->auth_type;
- hd->adver_int = vsrv->adver_int/VRRP_TIMER_HZ;
+ hd->adver_int = vsrv->adver_int/TIMER_HZ;
/* copy the ip addresses */
for( i = 0; i < vsrv->naddr; i++ ){
memset(&from, 0 , sizeof(from));
strcpy(from.sa_data, vsrv->vif->ifname);
+//print_buffer(buflen, buffer);
+
/* send the data */
len = sendto(fd, buffer, buflen, 0, &from, sizeof(from));
return 1;
}
-/* compute vrrp structure */
-int complete_vrrp_init(vrrp_rt *vsrv)
-{
- vrrp_if *vif = vsrv->vif;
-
- /* complete the VMAC address */
- vsrv->hwaddr[0] = 0x00;
- vsrv->hwaddr[1] = 0x00;
- vsrv->hwaddr[2] = 0x5E;
- vsrv->hwaddr[3] = 0x00;
- vsrv->hwaddr[4] = 0x01;
- vsrv->hwaddr[5] = vsrv->vrid;
-
- /* get the ip address */
- vif->ipaddr = ifname_to_ip(vif->ifname);
- if (!vif->ipaddr) {
- syslog(LOG_INFO, "VRRP Error : no interface found : %s !\n", vif->ifname);
- return 0;
- }
- /* get the hwaddr */
- if (hwaddr_get(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr))) {
- syslog(LOG_INFO, "VRRP Error : Unreadable MAC"
- "address for interface : %s !\n", vif->ifname);
- return 0;
- }
-
- vsrv->state = VRRP_STATE_INIT;
- if (!vsrv->adver_int) vsrv->adver_int = VRRP_ADVER_DFL * VRRP_TIMER_HZ;
- if (!vsrv->priority) vsrv->priority = VRRP_PRIO_DFL;
- if (!vsrv->preempt) vsrv->preempt = VRRP_PREEMPT_DFL;
-
- return(chk_min_cfg(vsrv));
-}
-
/* open the socket and join the multicast group. */
int open_vrrp_socket(const int proto, const int index)
{
return fd;
}
+
+extern data *conf_data;
+
/* handle terminate state */
-void vrrp_state_stop_instance(vrrp_rt *vsrv)
+void shutdown_vrrp_instances(void)
+{
+ list l = conf_data->vrrp;
+ element e;
+ vrrp_instance *vrrp;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+
+ /* remove VIPs */
+ if (vrrp->vsrv->state == VRRP_STATE_MAST)
+ vrrp_restore_interface(vrrp->vsrv, 1);
+ }
+}
+
+/* complete vrrp structure */
+static int vrrp_complete_instance(vrrp_rt *vsrv)
{
- /* restore MAC, routing table & remove VIPs */
- if (vsrv->state == VRRP_STATE_MAST)
- vrrp_restore_interface(vsrv, 1);
+ vrrp_if *vif = vsrv->vif;
+
+ /* complete the VMAC address */
+ vsrv->hwaddr[0] = 0x00;
+ vsrv->hwaddr[1] = 0x00;
+ vsrv->hwaddr[2] = 0x5E;
+ vsrv->hwaddr[3] = 0x00;
+ vsrv->hwaddr[4] = 0x01;
+ vsrv->hwaddr[5] = vsrv->vrid;
+
+ /* get the ip address */
+ vif->ipaddr = ifname_to_ip(vif->ifname);
+ if (!vif->ipaddr) {
+ syslog(LOG_INFO, "VRRP Error : no interface found : %s !\n", vif->ifname);
+ return 0;
+ }
+ /* get the hwaddr */
+ if (hwaddr_get(vif->ifname, vif->hwaddr, sizeof(vif->hwaddr))) {
+ syslog(LOG_INFO, "VRRP Error : Unreadable MAC"
+ "address for interface : %s !\n", vif->ifname);
+ return 0;
+ }
+
+ vsrv->state = VRRP_STATE_INIT;
+ if (!vsrv->adver_int) vsrv->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
+ if (!vsrv->priority) vsrv->priority = VRRP_PRIO_DFL;
+ if (!vsrv->preempt) vsrv->preempt = VRRP_PREEMPT_DFL;
+
+ return(chk_min_cfg(vsrv));
+}
+
+void vrrp_complete_init(void)
+{
+ list l = conf_data->vrrp;
+ element e;
+ vrrp_instance *vrrp;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ vrrp_complete_instance(vrrp->vsrv);
+ }
}
*
* Part: vrrp.c program include file.
*
- * Version: $Id: vrrp.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Based on the Jerome Etienne, <jetienne@arobas.net> code.
#include <unistd.h>
/* local include */
-#include "cfreader.h"
#include "vrrp_ipaddress.h"
#include "vrrp_ipsecah.h"
+#include "timer.h"
#include "utils.h"
uint32_t ipaddr; /* the address of the interface */
char hwaddr[6]; /* hardcoded for ethernet */
- char ifname[10]; /* the device name for this ipaddr */
+ char *ifname; /* the device name for this ipaddr */
/*
* To have my own ip_id creates collision with kernel ip->id
* but it should be ok because the packets are unlikely to be
int debug; /* Debug level 0-4 */
int notify_exec;
- char notify_file[FILENAME_MAX ];
-
+ char notify_file[FILENAME_MAX];
/* rfc2336.6.2 */
uint32_t ms_down_timer;
#define VRRP_IS_BAD_DEBUG_INT(d) ((d)<0 || (d)>4)
-#define VRRP_TIMER_HZ 1000000
-#define VRRP_TIMER_SKEW(srv) ((256-(srv)->priority)*VRRP_TIMER_HZ/256)
+#define VRRP_TIMER_SKEW(srv) ((256-(srv)->priority)*TIMER_HZ/256)
#define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
#define VRRP_MAX(a, b) ((a) > (b)?(a):(b))
/* prototypes */
extern int vrrp_ipsecah_len(void);
-extern int complete_vrrp_init(vrrp_rt *vsrv);
-extern void vrrp_state_stop_instance(vrrp_rt *vsrv);
+extern void vrrp_complete_init(void);
+extern void shutdown_vrrp_instances(void);
#endif
*
* Part: NETLINK IPv4 address manipulation.
*
- * Version: $Id: vrrp_ipaddress.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_ipaddress.c include file.
*
- * Version: $Id: vrrp_ipaddress.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.h,v 0.5.3 2002/02/24 23:50:11 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.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_ipsecah.c include file.
*
- * Version: $Id: vrrp_ipsecah.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK kernel command channel.
*
- * Version: $Id: vrrp_netlink.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_netlink.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_netlink.c include file.
*
- * Version: $Id: vrrp_netlink.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_netlink.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Sheduling framework for vrrp code.
*
- * Version: $Id: vrrp_scheduler.c,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_scheduler.c,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_ipsecah.h"
#include "vrrp.h"
#include "memory.h"
+#include "list.h"
+
+extern thread_master *master;
+extern data *conf_data;
/*
* Initialize state handling
* --rfc2338.6.4.1
*/
-static void vrrp_init_state(vrrp_instance *instance)
+static void vrrp_init_state(list l)
{
- vrrp_instance *vrrpptr = instance;
+ vrrp_instance *vrrp;
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
- while (instance) {
- if (instance->vsrv->priority == VRRP_PRIO_OWNER ||
- instance->vsrv->wantstate == VRRP_STATE_MAST) {
- instance->vsrv->state = VRRP_STATE_GOTO_MASTER;
+ if (vrrp->vsrv->priority == VRRP_PRIO_OWNER ||
+ vrrp->vsrv->wantstate == VRRP_STATE_MAST) {
+ vrrp->vsrv->state = VRRP_STATE_GOTO_MASTER;
} else {
- instance->vsrv->ms_down_timer = 3 * instance->vsrv->adver_int
- + VRRP_TIMER_SKEW(instance->vsrv);
- instance->vsrv->state = VRRP_STATE_BACK;
+ vrrp->vsrv->ms_down_timer = 3 * vrrp->vsrv->adver_int
+ + VRRP_TIMER_SKEW(vrrp->vsrv);
+ vrrp->vsrv->state = VRRP_STATE_BACK;
}
-
- instance = (vrrp_instance *)instance->next;
}
- instance = vrrpptr;
}
-static void vrrp_init_instance_sands(vrrp_instance *instance)
+static void vrrp_init_instance_sands(vrrp_instance *vrrp)
{
- struct timeval timer_now;
+ TIMEVAL timer;
- gettimeofday(&timer_now, NULL);
+ timer = timer_now();
- if (instance->vsrv->state == VRRP_STATE_BACK) {
- instance->vsrv->sands.tv_sec = timer_now.tv_sec +
- instance->vsrv->ms_down_timer / VRRP_TIMER_HZ;
- instance->vsrv->sands.tv_usec = timer_now.tv_usec +
- instance->vsrv->ms_down_timer % VRRP_TIMER_HZ;
+ if (vrrp->vsrv->state == VRRP_STATE_BACK) {
+ vrrp->vsrv->sands.tv_sec = timer.tv_sec +
+ vrrp->vsrv->ms_down_timer / TIMER_HZ;
+ vrrp->vsrv->sands.tv_usec = timer.tv_usec +
+ vrrp->vsrv->ms_down_timer % TIMER_HZ;
}
- if (instance->vsrv->state == VRRP_STATE_GOTO_MASTER ||
- instance->vsrv->state == VRRP_STATE_MAST) {
- instance->vsrv->sands.tv_sec = timer_now.tv_sec +
- instance->vsrv->adver_int / VRRP_TIMER_HZ;
- instance->vsrv->sands.tv_usec = timer_now.tv_usec;
+ if (vrrp->vsrv->state == VRRP_STATE_GOTO_MASTER ||
+ vrrp->vsrv->state == VRRP_STATE_MAST) {
+ vrrp->vsrv->sands.tv_sec = timer.tv_sec +
+ vrrp->vsrv->adver_int / TIMER_HZ;
+ vrrp->vsrv->sands.tv_usec = timer.tv_usec;
}
}
-static void vrrp_init_sands(vrrp_instance *instance)
+static void vrrp_init_sands(list l)
{
- vrrp_instance *vrrpptr = instance;
+ vrrp_instance *vrrp;
+ element e;
- while (instance) {
- vrrp_init_instance_sands(instance);
-
- instance = (vrrp_instance *)instance->next;
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ vrrp_init_instance_sands(vrrp);
}
- instance = vrrpptr;
}
/* Timer functions */
-static TIMEVAL vrrp_compute_timer(const int fd, vrrp_instance *vrrp)
+static TIMEVAL vrrp_compute_timer(const int fd)
{
- vrrp_instance *ptr = vrrp;
+ vrrp_instance *vrrp;
TIMEVAL timer;
+ element e;
+ list l = conf_data->vrrp;
/* clean the memory */
- memset(&timer, 0, sizeof(struct timeval));
+ TIMER_RESET(timer);
- while (vrrp) {
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
if (vrrp->vsrv->fd == fd) {
- if (thread_timer_cmp(vrrp->vsrv->sands, timer) < 0 ||
- (timer.tv_sec == 0 && timer.tv_usec == 0)) {
- timer.tv_sec = vrrp->vsrv->sands.tv_sec;
- timer.tv_usec = vrrp->vsrv->sands.tv_usec;
- }
+ if (timer_cmp(vrrp->vsrv->sands, timer) < 0 ||
+ TIMER_ISNULL(timer))
+ timer = timer_dup(vrrp->vsrv->sands);
}
-
- vrrp = (vrrp_instance *)vrrp->next;
}
- vrrp = ptr;
return timer;
}
-static TIMEVAL vrrp_timer_delta(TIMEVAL timer)
-{
- TIMEVAL timer_now;
-
- /* init timer */
- memset(&timer_now, 0, sizeof(struct timeval));
- gettimeofday(&timer_now, NULL);
-
- return(thread_timer_sub(timer, timer_now));
-}
-
-static long vrrp_timer_fd(const int fd, vrrp_instance *instance)
+static long vrrp_timer_fd(const int fd)
{
- TIMEVAL timer;
- long vrrp_timer = 0;
+ TIMEVAL timer, vrrp_timer, now;
- timer = vrrp_compute_timer(fd, instance);
- timer = vrrp_timer_delta(timer);
- vrrp_timer = timer.tv_sec * VRRP_TIMER_HZ + timer.tv_usec;
+ timer = vrrp_compute_timer(fd);
+ now = timer_now();
+ vrrp_timer = timer_sub(timer, now);
+// vrrp_timer = timer_sub_now(timer);
- return vrrp_timer;
+ return (vrrp_timer.tv_sec*TIMER_HZ + vrrp_timer.tv_usec);
}
-static int vrrp_timer_vrid_timeout(const int fd, vrrp_instance *vrrp)
+static int vrrp_timer_vrid_timeout(const int fd)
{
- vrrp_instance *ptr = vrrp;
+ vrrp_instance *vrrp;
+ list l = conf_data->vrrp;
+ element e;
TIMEVAL vrrp_timer;
int vrid = 0;
/* clean the memory */
memset(&vrrp_timer, 0, sizeof(struct timeval));
- vrrp_timer = vrrp_compute_timer(fd, vrrp);
+ vrrp_timer = vrrp_compute_timer(fd);
- while (vrrp) {
- if (thread_timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ if (timer_cmp(vrrp->vsrv->sands, vrrp_timer) == 0)
vrid = vrrp->vsrv->vrid;
-
- vrrp = (vrrp_instance *)vrrp->next;
}
- vrrp = ptr;
-
return vrid;
}
long vrrp_timer = 0;
memset(&timer, 0, sizeof(struct timeval));
- memset(&timer_now, 0, sizeof(struct timeval));
- gettimeofday(&timer_now, NULL);
while (vrrp) {
- timer = thread_timer_sub(vrrp->vsrv->sands, timer_now);
- vrrp_timer = timer.tv_sec * VRRP_TIMER_HZ + timer.tv_usec;
+ timer = timer_sub_now(vrrp->vsrv->sands);
+ vrrp_timer = timer.tv_sec * TIMER_HZ + timer.tv_usec;
syslog(LOG_DEBUG, "Timer(vrid,value) : (%d,%d)", vrrp->vsrv->vrid, vrrp_timer);
vrrp = (vrrp_instance *)vrrp->next;
*/
/* Thread functions */
-static void vrrp_register_workers(thread_master *master
- , vrrp_instance *instance
- , sockpool *pool)
+static void vrrp_register_workers(list l)
{
- sockpool *poolptr = pool;
+ sock *sock;
TIMEVAL timer;
long vrrp_timer = 0;
+ element e;
- /* init compute timer */
+ /* Init compute timer */
memset(&timer, 0, sizeof(struct timeval));
/* Init the VRRP instances state */
- vrrp_init_state(instance);
+ vrrp_init_state(conf_data->vrrp);
/* Init VRRP instances sands */
- vrrp_init_sands(instance);
+ vrrp_init_sands(conf_data->vrrp);
- while (pool) {
+ /* Register VRRP workers threads */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ sock = ELEMENT_DATA(e);
/* jump to asynchronous handling */
- vrrp_timer = vrrp_timer_fd(pool->fd, instance);
- thread_add_read(master, vrrp_read_dispatcher_thread,
- instance, pool->fd, vrrp_timer);
-
- pool = (sockpool *)pool->next;
+ vrrp_timer = vrrp_timer_fd(sock->fd);
+ thread_add_read(master, vrrp_read_dispatcher_thread
+ , NULL
+ , sock->fd
+ , vrrp_timer);
}
- pool = poolptr;
}
/* VRRP dispatcher functions */
-static int already_exist_sock(sockpool *lstptr, int ifindex, int proto)
+static int already_exist_sock(list l, int ifindex, int proto)
{
- sockpool *ptrpool = lstptr;
+ sock *sock;
+ element e;
- while (lstptr) {
- if ((lstptr->ifindex == ifindex) && (lstptr->proto == proto)) {
- lstptr = ptrpool;
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ sock = ELEMENT_DATA(e);
+ if ((sock->ifindex == ifindex) && (sock->proto == proto))
return 1;
- }
- lstptr = (sockpool *)lstptr->next;
}
- lstptr = ptrpool;
return 0;
}
-static sockpool *add_sock(sockpool *lstsock, sockpool *sock)
+/* sockpool list primitives */
+void free_sock(void *data)
{
- sockpool *ptrpool = lstsock;
-
- if (lstsock) {
- while (lstsock->next) lstsock = (sockpool *)lstsock->next;
- lstsock->next = (struct sockpool *)sock;
- return ptrpool;
- } else {
- lstsock = sock;
- return lstsock;
- }
+ FREE(data);
}
-
-static sockpool *remove_sock(sockpool *pool)
+void dump_sock(void *data)
{
- sockpool *t;
-
- t = (sockpool *)pool->next;
- FREE(pool);
- return t;
+ sock *sock = data;
+ syslog(LOG_DEBUG, "sockpool -> ifindex(%d), proto(%d), fd(%d)"
+ , sock->ifindex
+ , sock->proto
+ , sock->fd);
}
-
-static void clear_sockpool(sockpool *pool)
+void alloc_sock(list l, int ifindex, int proto)
{
- while (pool)
- pool = remove_sock(pool);
+ sock *new;
+
+ new = (sock *)MALLOC(sizeof(sock));
+ new->ifindex = ifindex;
+ new->proto = proto;
+
+ list_add(l, new);
}
-static sockpool *vrrp_create_sockpool(vrrp_instance *instance, sockpool *pool)
+static void vrrp_create_sockpool(list l)
{
- vrrp_instance *ptr = instance;
- sockpool *sock;
+ vrrp_instance *vrrp;
+ list p = conf_data->vrrp;
+ element e;
int ifindex;
int proto;
- while (instance) {
- ifindex = ifname_to_idx(instance->vsrv->vif->ifname);
- if (instance->vsrv->vif->auth_type == VRRP_AUTH_AH)
+ for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ ifindex = ifname_to_idx(vrrp->vsrv->vif->ifname);
+ if (vrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)
proto = IPPROTO_IPSEC_AH;
else
proto = IPPROTO_VRRP;
- if (!already_exist_sock(pool, ifindex, proto)) {
- /* allocate & clean the new struct */
- sock = (sockpool *)MALLOC(sizeof(sockpool));
-
- /* fill in the new sock structure */
- sock->ifindex = ifindex;
- sock->proto = proto;
- pool = add_sock(pool, sock);
- }
-
- instance = (vrrp_instance *)instance->next;
+ /* add the vrrp element if not exist */
+ if (!already_exist_sock(l, ifindex, proto))
+ alloc_sock(l, ifindex, proto);
}
-
- instance = ptr;
- return pool;
}
-static void vrrp_open_sockpool(sockpool *pool)
+static void vrrp_open_sockpool(list l)
{
- sockpool *ptr = pool;
+ sock *sock;
+ element e;
- while (pool) {
- pool->fd = open_vrrp_socket(pool->proto, pool->ifindex);
- syslog(LOG_DEBUG, "sockpool -> ifindex %d, proto %d, fd %d",
- pool->ifindex, pool->proto, pool->fd);
- pool = (sockpool *)pool->next;
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ sock = ELEMENT_DATA(e);
+ sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
}
- pool = ptr;
}
-static void vrrp_set_fds(vrrp_instance *instance, sockpool *pool)
+static void vrrp_set_fds(list l)
{
- sockpool *ptr = pool;
- vrrp_instance *ptrvrrp = instance;
+ sock *sock;
+ vrrp_instance *vrrp;
+ list p = conf_data->vrrp;
+ element e_sock;
+ element e_vrrp;
int proto;
- while (pool) {
- while (instance) {
- if (instance->vsrv->vif->auth_type == VRRP_AUTH_AH)
+ for (e_sock = LIST_HEAD(l); e_sock; ELEMENT_NEXT(e_sock)) {
+ sock = ELEMENT_DATA(e_sock);
+ for (e_vrrp = LIST_HEAD(p); e_vrrp; ELEMENT_NEXT(e_vrrp)) {
+ vrrp = ELEMENT_DATA(e_vrrp);
+ if (vrrp->vsrv->vif->auth_type == VRRP_AUTH_AH)
proto = IPPROTO_IPSEC_AH;
else
proto = IPPROTO_VRRP;
- if ((pool->ifindex == ifname_to_idx(instance->vsrv->vif->ifname)) &&
- (pool->proto == proto))
- instance->vsrv->fd = pool->fd;
-
- instance = (vrrp_instance *)instance->next;
+ if ((sock->ifindex == ifname_to_idx(vrrp->vsrv->vif->ifname)) &&
+ (sock->proto == proto))
+ vrrp->vsrv->fd = sock->fd;
}
- instance = ptrvrrp;
-
- pool = (sockpool *)pool->next;
}
- pool = ptr;
}
/*
* are multiplexed through this fds. So our design can handle 2*n
* multiplexing points.
*/
-int vrrp_dispatcher_init_thread(thread *thread)
+int vrrp_dispatcher_init(thread *thread)
{
- vrrp_instance *instance = THREAD_ARG(thread);
- sockpool *pool;
+ list pool;
- /* init */
- pool = NULL;
+ /* allocate the sockpool */
+ pool = alloc_list(free_sock, dump_sock);
/* create the VRRP socket pool list */
- pool = vrrp_create_sockpool(instance, pool);
+ vrrp_create_sockpool(pool);
/* open the VRRP socket pool */
vrrp_open_sockpool(pool);
/* set VRRP instance fds to sockpool */
- vrrp_set_fds(instance, pool);
+ vrrp_set_fds(pool);
/* register read dispatcher worker thread */
- vrrp_register_workers(thread->master, instance, pool);
+ vrrp_register_workers(pool);
/* cleanup the temp socket pool */
- clear_sockpool(pool);
+ dump_list(pool);
+ free_list(pool);
return 0;
}
-static vrrp_instance *vrrp_search_instance_isync(char *isync, vrrp_instance *instance)
+static vrrp_instance *vrrp_search_instance_isync(char *isync)
{
- while (instance) {
- if (strcmp(instance->iname, isync) == 0) /* FIXME: handle buffer overflow */
- return instance;
- instance = (vrrp_instance *)instance->next;
+ vrrp_instance *vrrp;
+ list l = conf_data->vrrp;
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ if (strcmp(vrrp->iname, isync) == 0)
+ return vrrp;
}
-
return NULL;
}
-static vrrp_instance *vrrp_search_instance(const int vrid, vrrp_instance *instance)
+static vrrp_instance *vrrp_search_instance(const int vrid)
{
- while (instance) {
- if (instance->vsrv->vrid == vrid)
- return instance;
- instance = (vrrp_instance *)instance->next;
+ vrrp_instance *vrrp;
+ list l = conf_data->vrrp;
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ if (vrrp->vsrv->vrid == vrid)
+ return vrrp;
}
-
return NULL;
}
{
if (vrrp_state_master_rx(instance, vrrp_buffer, len)) {
syslog(LOG_INFO, "VRRP_Instance(%s) Received higher prio advert"
- , instance->iname);
+ , instance->iname);
vrrp_state_leave_master(instance);
}
}
/* Our read packet dispatcher */
int vrrp_read_dispatcher_thread(thread *thread)
{
- vrrp_instance *instance = THREAD_ARG(thread);
- vrrp_instance *ptr = instance;
vrrp_instance *vrrp_isync;
vrrp_instance *vrrp_instance;
long vrrp_timer = 0;
if (thread->type == THREAD_READ_TIMEOUT) {
/* Searching for matching instance */
- vrid = vrrp_timer_vrid_timeout(thread->u.fd, instance);
- vrrp_instance = vrrp_search_instance(vrid, instance);
- instance = ptr;
-
-// syslog(LOG_DEBUG, "Dispatcher timeout on (fd,vrid) : (%d,%d)", thread->u.fd, vrid);
+ vrid = vrrp_timer_vrid_timeout(thread->u.fd);
+ vrrp_instance = vrrp_search_instance(vrid);
previous_state = vrrp_handle_state_timeout(vrrp_instance);
/* handle master instance synchronization */
- if (previous_state == VRRP_STATE_BACK &&
- strlen(vrrp_instance->isync) > 0) {
- vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync, instance);
- instance = ptr;
+ if (previous_state == VRRP_STATE_BACK && vrrp_instance->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
if (vrrp_isync->vsrv->state == VRRP_STATE_BACK) {
syslog(LOG_INFO, "VRRP_Instance(%s) must be sync with %s"
iph = (struct iphdr *)vrrp_buffer;
/* GCC bug : Workaround */
- hd = (vrrp_pkt *) ((char *)iph + (iph->ihl<<2));
+ hd = (vrrp_pkt *) ((char *)iph + (iph->ihl << 2));
if (iph->protocol == IPPROTO_IPSEC_AH)
hd = (vrrp_pkt *) ((char *)hd + vrrp_ipsecah_len());
/* GCC bug : end */
/* Searching for matching instance */
- vrrp_instance = vrrp_search_instance(hd->vrid, instance);
- instance = ptr;
+ vrrp_instance = vrrp_search_instance(hd->vrid);
if (vrrp_instance) {
-//syslog(LOG_DEBUG, "VRRP packet received: on fd:%d", thread->u.fd);
-
previous_state = vrrp_handle_state(vrrp_instance, vrrp_buffer, len);
/* handle backup instance synchronization */
if (previous_state == VRRP_STATE_MAST &&
vrrp_instance->vsrv->state == VRRP_STATE_BACK &&
- strlen(vrrp_instance->isync) > 0) {
- vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync, instance);
- instance = ptr;
+ vrrp_instance->isync) {
+ vrrp_isync = vrrp_search_instance_isync(vrrp_instance->isync);
/* synchronized instance probably failed */
if (vrrp_isync->vsrv->state == VRRP_STATE_MAST &&
}
/* register next dispatcher thread */
- vrrp_timer = vrrp_timer_fd(thread->u.fd, instance);
- thread_add_read(thread->master, vrrp_read_dispatcher_thread,
- instance, thread->u.fd, vrrp_timer);
-
-//syslog(LOG_DEBUG, "VRRP new timer: %lu on fd:%d", vrrp_timer, thread->u.fd);
-
+ vrrp_timer = vrrp_timer_fd(thread->u.fd);
+ thread_add_read(thread->master, vrrp_read_dispatcher_thread
+ , NULL
+ , thread->u.fd
+ , vrrp_timer);
return 0;
}
+
+/* Register VRRP thread */
+void register_vrrp_thread(void)
+{
+ if (!LIST_ISEMPTY(conf_data->vrrp))
+ thread_add_event(master, vrrp_dispatcher_init
+ , NULL
+ , VRRP_DISPATCHER);
+}
*
* Part: vrrp_scheduler.c include file.
*
- * Version: $Id: vrrp_scheduler.h,v 0.4.9a 2001/12/20 17:14:25 acassen Exp $
+ * Version: $Id: vrrp_scheduler.h,v 0.5.3 2002/02/24 23:50:11 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include "scheduler.h"
+#include "data.h"
/*
* Our instance dispatcher use a socket pool.
int ifindex;
int proto;
int fd;
-
- struct sockpool *next;
-} sockpool;
+} sock;
/* extern prototypes */
extern int open_vrrp_socket(const int proto, const int index);