crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs | LICENSE

commit d0519fb4de3209440707333ce6b49d0f2d7c7f42
parent ef4ca38c2c1690a176c16ad85b07087adda25611
Author: finwo <finwo@pm.me>
Date:   Sat,  3 Jan 2026 19:31:37 +0100

1.41

Diffstat:
MChangeLog | 4++++
MMakefile | 1+
Metc/Makefile.conf | 29+++++++++++++++++++----------
Metc/Makefile.def | 2+-
Metc/svnrev.txt | 2+-
Msrc/Makefile | 2+-
Asrc/crossroads-daemon/Makefile | 23+++++++++++++++++++++++
Asrc/crossroads-daemon/main.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/configread.c | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/configwrite.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/lib/data.c | 35+++++++++++++++++++++++++++++++++++
Asrc/lib/xcalloc.c | 18++++++++++++++++++
Mtools/c-conf | 49+++++++++++++++++++++++++++++++++++++++++++++----
13 files changed, 508 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,6 +1,10 @@ ChangeLog for Crossroads ------------------------------------------------------------------------------ +1.41 [KK 2007-05-18] + - Included c-conf 1.07 (caching provisions - way faster build) + - Fixed deliverable, version 1.40 lacked files (DISTRO WAS BROKEN) + 1.40 [KK 2007-05-16] - Added flag -m to control shared memory access mode. - Implemented flag -x for XML report of status. diff --git a/Makefile b/Makefile @@ -21,6 +21,7 @@ clean: BASE=$(BASE) $(MAKE) -C doc clean find $(BASE) -type f -name '*~' -exec rm {} \; find $(BASE) -type f -name .gdb_history -exec rm {} \; + rm -f src/c-conf.cache distclean: BASE=$(BASE) $(MAKE) -C src distclean diff --git a/etc/Makefile.conf b/etc/Makefile.conf @@ -1,8 +1,9 @@ # The used C compiler. -CC := $(shell $(BASE)/tools/c-conf c-compiler) +CC := $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache c-compiler) # Link time libraries. -LIBS := $(shell $(BASE)/tools/c-conf lib ucb nsl pthread socket 2>/dev/null) +LIBS := $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache lib \ + ucb nsl pthread socket 2>/dev/null) # Compiletime defines. Remember to update show_config() when changing # this list! @@ -13,11 +14,19 @@ DEFS := -DDEFAULT_CONF='"$(DEFAULT_CONF)"' -DMAX_BACKEND=$(MAX_BACKEND) \ -DTCP_BUFSZ=$(TCP_BUFSZ) -DRETRY_WAIT=$(RETRY_WAIT) \ -DREVVER='"$(REVVER)"' -DBINDIR='"$(BINDIR)"' \ -DEXTRALIBS='"$(EXTRALIBS)"' -DLIBS='"$(LIBS)"' \ - $(shell $(BASE)/tools/c-conf ifheader01 malloc.h HAVE_MALLOC_H) \ - $(shell $(BASE)/tools/c-conf ifheader01 stdint.h HAVE_STDINT_H) \ - $(shell $(BASE)/tools/c-conf libfunction01 flock HAVE_FLOCK) \ - $(shell $(BASE)/tools/c-conf libfunction01 lockf HAVE_LOCKF) \ - $(shell $(BASE)/tools/c-conf libfunction01 strlcat HAVE_STRLCAT) \ - $(shell $(BASE)/tools/c-conf libfunction01 sranddev HAVE_SRANDDEV) \ - $(shell $(BASE)/tools/c-conf libfunction01 vsyslog HAVE_VSYSLOG) \ - $(shell $(BASE)/tools/c-conf libfunction01 strcasestr HAVE_STRCASESTR) + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + ifheader01 malloc.h HAVE_MALLOC_H) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + ifheader01 stdint.h HAVE_STDINT_H) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 flock HAVE_FLOCK) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 lockf HAVE_LOCKF) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 strlcat HAVE_STRLCAT) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 sranddev HAVE_SRANDDEV) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 vsyslog HAVE_VSYSLOG) \ + $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache \ + libfunction01 strcasestr HAVE_STRCASESTR) diff --git a/etc/Makefile.def b/etc/Makefile.def @@ -6,7 +6,7 @@ # Versioning. This defines the overall version ID and must match the topmost # entry in the ChangeLog. -VER = 1.40 +VER = 1.41 # Revision version, auto-detected. REVVER = $(shell $(BASE)/etc/svnrev $(BASE)/ChangeLog $(BASE)/etc/svnrev.txt) diff --git a/etc/svnrev.txt b/etc/svnrev.txt @@ -1 +1 @@ -152 +153 diff --git a/src/Makefile b/src/Makefile @@ -23,7 +23,7 @@ clean: BASE=$(BASE) make -C $$d clean || exit 1; \ done -distclean: +distclean: clean for d in ${DIRS}; do \ echo "Making distclean in $$d"; \ echo BASE=$(BASE) make -C $$d distclean; \ diff --git a/src/crossroads-daemon/Makefile b/src/crossroads-daemon/Makefile @@ -0,0 +1,23 @@ +include $(BASE)/etc/Makefile.def +include $(BASE)/etc/Makefile.conf + +BIN = crossroads-daemon +all: $(BIN) + +install: all $(BINDIR)/$(BIN) + +clean: + rm -f *.o $(BIN) + +$(BINDIR)/$(BIN): $(BIN) ../lib/libcrossroads.a + cp $(BIN) $(BINDIR)/$(BIN) + strip $(BINDIR)/$(BIN) + +main.o: main.c + $(CC) -c -g -W -Wall $(DEFS) main.c + +$(BIN): main.o + $(CC) -o $(BIN) main.o -L$(BASE)/src/lib -lcrossroads + +# Extra deps: +main.o: main.c $(BASE)/src/crossroads.h $(BASE)/etc/Makefile.def diff --git a/src/crossroads-daemon/main.c b/src/crossroads-daemon/main.c @@ -0,0 +1,90 @@ +/************************************************************************* + * This file is part of Crosroads 1.40, a load balancer and fail over + * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. + * Visit http://crossroads.e-tunity.com for information. + *************************************************************************/ + +#include "../crossroads.h" + +int main (int argc, char **argv) { + int opt, i; + + /* Remember original ac/av/ep */ + org_argc = argc; + org_argv = argv; + + /* Parse options. */ + config_file = DEFAULT_CONF; + while ( (opt = getopt (argc, argv, "?c:fhvi:Val:stCm:x")) > 0 ) + switch (opt) { + case 'a': + log_activity++; + break; + case 'c': + config_file = optarg; + break; + case 'v': + flag_verbose++; + break; + case 'i': + iflag_present++; + break; + case 'l': + switch (atoi (optarg)) { + case 0: + log_facility = LOG_LOCAL0; + break; + case 1: + log_facility = LOG_LOCAL1; + break; + case 2: + log_facility = LOG_LOCAL2; + break; + case 3: + log_facility = LOG_LOCAL3; + break; + case 4: + log_facility = LOG_LOCAL4; + break; + case 5: + log_facility = LOG_LOCAL5; + break; + case 6: + log_facility = LOG_LOCAL6; + break; + case 7: + log_facility = LOG_LOCAL7; + break; + default: + error ("Bad invocation of crossroads-daemon"); + } + break; + case 'm': + shmperm = strtol (optarg, 0, 8); + break; + case 's': + sloppyportbind++; + break; + case 't': + tabular_status++; + break; + case 'x': + xml_status++; + break; + default: + error ("Bad invocation of crossroads-daemon"); + } + + /* We're the daemon executable. We know what to do -- serve. */ + create_commandline_space(); + config_read (0); + msg ("Starting services"); + for (i = 0; i < nservice; i++) { + /* Start the service. */ + activeservice = service + i; + runservice (); + } + + /* All done. */ + return (0); +} diff --git a/src/lib/configread.c b/src/lib/configread.c @@ -0,0 +1,159 @@ +/************************************************************************* + * This file is part of Crosroads 1.40, a load balancer and fail over + * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. + * Visit http://crossroads.e-tunity.com for information. + *************************************************************************/ + +#include "../crossroads.h" + +static void rd (int fd, void *buf, unsigned sz) { + int res; + int toread = (int) sz; + + if ( (res = read (fd, buf, sz)) != toread ) + error ("Failed to fetch %d bytes (%d)", toread, res); +} + +static int rd_int (int fd) { + int res; + + rd (fd, &res, sizeof(int)); + return (res); +} + +static int rd_uns (int fd) { + unsigned res; + + rd (fd, &res, sizeof(unsigned)); + return (res); +} + +static char *rd_str (int fd) { + char *buf; + int len; + + len = rd_int (fd); + if (!len) + return (0); + if (len > 1024) + error ("Maximum string length exceeded, attempt for %d", len); + buf = xcalloc (len + 1); + rd (fd, buf, len); + return (buf); +} + + +void config_read (int fd) { + int i, j, k; + + msg ("Reading binary service definition from fd %d", fd); + + nservice = rd_int (fd); + msg ("Configured services: %d", nservice); + service = xcalloc (nservice * sizeof(Service)); + for (i = 0; i < nservice; i++) { + /* Basic stuff */ + service[i].name = rd_str (fd); + msg (" Scanning service %d (%s)", i + 1, service[i].name); + service[i].bind = rd_str (fd); + service[i].port = rd_uns (fd); + service[i].verbosity = rd_uns (fd); + service[i].dispatchtype = (Dispatchtype)rd_int (fd); + service[i].dispatchover = rd_uns (fd); + service[i].dispatchext = rd_str (fd); + service[i].rev_interval = rd_uns (fd); + service[i].backlog = rd_uns (fd); + service[i].shmkey = rd_uns (fd); + service[i].connectiontimeout = rd_uns (fd); + service[i].maxconnections = rd_uns (fd); + service[i].type = (Dispatchtype)rd_int (fd); + service[i].allowfile = rd_str (fd); + service[i].denyfile = rd_str (fd); + service[i].uid = rd_int (fd); + service[i].gid = rd_int (fd); + + /* Deny chain */ + service[i].ndenychain = rd_int (fd); + service[i].denychain = xcalloc (service[i].ndenychain * + sizeof(IpFilter)); + for (j = 0; j < service[i].ndenychain; j++) { + service[i].denychain[j].ip = rd_int (fd); + service[i].denychain[j].mask = rd_int (fd); + } + + /* Allow chain */ + service[i].nallowchain = rd_int (fd); + service[i].allowchain = xcalloc (service[i].nallowchain * + sizeof(IpFilter)); + for (j = 0; j < service[i].nallowchain; j++) { + service[i].allowchain[j].ip = rd_int (fd); + service[i].allowchain[j].mask = rd_int (fd); + } + + /* Back ends */ + service[i].nbackend = rd_int (fd); + msg (" Configured back ends: %d", service[i].nbackend); + service[i].backend = xcalloc (service[i].nbackend * + sizeof(Backend)); + for (j = 0; j < service[i].nbackend; j++) { + service[i].backend[j].name = rd_str (fd); + msg (" Backend %d: %s", j + i, service[i].backend[j].name); + service[i].backend[j].port = rd_int (fd); + service[i].backend[j].server = rd_str (fd); + service[i].backend[j].verbosity = rd_int (fd); + service[i].backend[j].weight = rd_int (fd); + service[i].backend[j].decay = rd_int (fd); + service[i].backend[j].onstart = rd_str (fd); + service[i].backend[j].onend = rd_str (fd); + service[i].backend[j].dumpfile = rd_str (fd); + service[i].backend[j].thruputfile = rd_str (fd); + service[i].backend[j].maxconnections = rd_uns (fd); + service[i].backend[j].stickycookie = rd_str (fd); + service[i].backend[j].retries = rd_int (fd); + + service[i].backend[j].naddclientheader = rd_int (fd); + service[i].backend[j].addclientheader = + xcalloc (service[i].backend[j].naddclientheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].naddclientheader; k++) + service[i].backend[j].addclientheader[k] = rd_str (fd); + + service[i].backend[j].nsetclientheader = rd_int (fd); + service[i].backend[j].setclientheader = + xcalloc (service[i].backend[j].nsetclientheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].nsetclientheader; k++) + service[i].backend[j].setclientheader[k] = rd_str (fd); + + service[i].backend[j].nappendclientheader = rd_int (fd); + service[i].backend[j].appendclientheader = + xcalloc (service[i].backend[j].nappendclientheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].nappendclientheader; k++) + service[i].backend[j].appendclientheader[k] = rd_str (fd); + + service[i].backend[j].naddserverheader = rd_int (fd); + service[i].backend[j].addserverheader = + xcalloc (service[i].backend[j].naddserverheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].naddserverheader; k++) + service[i].backend[j].addserverheader[k] = rd_str (fd); + + service[i].backend[j].nsetserverheader = rd_int (fd); + service[i].backend[j].setserverheader = + xcalloc (service[i].backend[j].nsetserverheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].nsetserverheader; k++) + service[i].backend[j].setserverheader[k] = rd_str (fd); + + service[i].backend[j].nappendserverheader = rd_int (fd); + service[i].backend[j].appendserverheader = + xcalloc (service[i].backend[j].nappendserverheader * + sizeof(char*)); + for (k = 0; k < service[i].backend[j].nappendserverheader; k++) + service[i].backend[j].appendserverheader[k] = rd_str (fd); + } + } + + msg ("Configuration scanned."); +} diff --git a/src/lib/configwrite.c b/src/lib/configwrite.c @@ -0,0 +1,111 @@ +/************************************************************************* + * This file is part of Crosroads 1.40, a load balancer and fail over + * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. + * Visit http://crossroads.e-tunity.com for information. + *************************************************************************/ + +#include "../crossroads.h" + +static void wr (int fd, void const *buf, unsigned len) { + int res; + int towrite = (int)len; + + if ( (res = write (fd, buf, len)) != towrite ) + error ("Failed to transmit %d bytes (%d)", towrite, res); +} + +static void wr_int (int fd, int x) { + wr (fd, &x, sizeof(int)); +} + +static void wr_uns (int fd, unsigned x) { + wr (fd, &x, sizeof(unsigned)); +} + +static void wr_str (int fd, char const *s) { + if (!s || !*s) + wr_int (fd, 0); + else { + wr_int (fd, strlen(s)); + wr (fd, s, strlen(s)); + } +} + +void config_write (int fd) { + int i, j, k; + + msg ("Writing binary service definition to fd %d", fd); + wr_int (fd, nservice); + for (i = 0; i < nservice; i++) { + /* Basic stuff */ + wr_str (fd, service[i].name); + wr_str (fd, service[i].bind); + wr_uns (fd, service[i].port); + wr_uns (fd, service[i].verbosity); + wr_int (fd, (int)service[i].dispatchtype); + wr_uns (fd, service[i].dispatchover); + wr_str (fd, service[i].dispatchext); + wr_uns (fd, service[i].rev_interval); + wr_uns (fd, service[i].backlog); + wr_uns (fd, service[i].shmkey); + wr_uns (fd, service[i].connectiontimeout); + wr_uns (fd, service[i].maxconnections); + wr_int (fd, (int)service[i].type); + wr_str (fd, service[i].allowfile); + wr_str (fd, service[i].denyfile); + wr_int (fd, service[i].uid); + wr_int (fd, service[i].gid); + + /* Deny chain */ + wr_int (fd, service[i].ndenychain); + for (j = 0; j < service[i].ndenychain; j++) { + wr_uns (fd, service[i].denychain[j].ip); + wr_uns (fd, service[i].denychain[j].mask); + } + + /* Allow chain */ + wr_int (fd, service[i].nallowchain); + for (j = 0; j < service[i].nallowchain; j++) { + wr_uns (fd, service[i].allowchain[j].ip); + wr_uns (fd, service[i].allowchain[j].mask); + } + + /* Back ends */ + wr_int (fd, service[i].nbackend); + for (j = 0; j < service[i].nbackend; j++) { + wr_str (fd, service[i].backend[j].name); + wr_int (fd, service[i].backend[j].port); + wr_str (fd, service[i].backend[j].server); + wr_int (fd, service[i].backend[j].verbosity); + wr_int (fd, service[i].backend[j].weight); + wr_int (fd, service[i].backend[j].decay); + wr_str (fd, service[i].backend[j].onstart); + wr_str (fd, service[i].backend[j].onend); + wr_str (fd, service[i].backend[j].dumpfile); + wr_str (fd, service[i].backend[j].thruputfile); + wr_uns (fd, service[i].backend[j].maxconnections); + wr_str (fd, service[i].backend[j].stickycookie); + wr_int (fd, service[i].backend[j].retries); + + wr_int (fd, service[i].backend[j].naddclientheader); + for (k = 0; k < service[i].backend[j].naddclientheader; k++) + wr_str (fd, service[i].backend[j].addclientheader[k]); + wr_int (fd, service[i].backend[j].nsetclientheader); + for (k = 0; k < service[i].backend[j].nsetclientheader; k++) + wr_str (fd, service[i].backend[j].setclientheader[k]); + wr_int (fd, service[i].backend[j].nappendclientheader); + for (k = 0; k < service[i].backend[j].nappendclientheader; k++) + wr_str (fd, service[i].backend[j].appendclientheader[k]); + + wr_int (fd, service[i].backend[j].naddserverheader); + for (k = 0; k < service[i].backend[j].naddserverheader; k++) + wr_str (fd, service[i].backend[j].addserverheader[k]); + wr_int (fd, service[i].backend[j].nsetserverheader); + for (k = 0; k < service[i].backend[j].nsetserverheader; k++) + wr_str (fd, service[i].backend[j].setserverheader[k]); + wr_int (fd, service[i].backend[j].nappendserverheader); + for (k = 0; k < service[i].backend[j].nappendserverheader; k++) + wr_str (fd, service[i].backend[j].appendserverheader[k]); + } + } +} diff --git a/src/lib/data.c b/src/lib/data.c @@ -0,0 +1,35 @@ +/************************************************************************* + * This file is part of Crosroads 1.40, a load balancer and fail over + * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. + * Visit http://crossroads.e-tunity.com for information. + *************************************************************************/ + +#define EXTERN +#include "../crossroads.h" + +/* Global data for all Crossroads programs */ + +int log_facility = LOG_DAEMON; +int shmperm = 0644; + +StateStringMap statestringmap[] = { + { st_available, "available" }, + { st_available, "up" }, + { st_unavailable, "UNAVAILABLE" }, + { st_down, "DOWN" }, + { st_waking, "WAKING" }, + { st_intermediate, "INTERMEDIATE" }, + { st_unknown, "UNKNOWN" }, + { st_unknown, 0 } +}; + +int relevant_sigs[] = { /* signals relevant to this app */ + SIGHUP, /* either caught or ignored, */ + SIGINT, /* depending on the stage */ + SIGQUIT, + SIGABRT, + SIGKILL, + SIGPIPE, + SIGTERM, + 0, +}; diff --git a/src/lib/xcalloc.c b/src/lib/xcalloc.c @@ -0,0 +1,18 @@ +/************************************************************************* + * This file is part of Crosroads 1.40, a load balancer and fail over + * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. + * Visit http://crossroads.e-tunity.com for information. + *************************************************************************/ + +#include "../crossroads.h" + +void *xcalloc (unsigned sz) { + void *ret; + + if (!sz) + return (0); + + ret = xmalloc (sz); + memset (ret, 0, sz); + return (ret); +} diff --git a/tools/c-conf b/tools/c-conf @@ -4,7 +4,8 @@ use strict; use Getopt::Std; # Globals -my $VER = "1.06"; +my $VER = "1.07"; +# 1.07 [KK 2007-05-18] Flag -c for caching implemented # 1.06 [KK 2007-04-27] Added ifheader01 and libfunction01 # 1.05 [KK 2006-09-28] Flag -s (silent) implemented. Usage text updated. # 1.04 [KK 2006-09-05] C-compilers: gcc/g++ get selected first, instead of @@ -36,6 +37,8 @@ my @warnings; my $printed; my @headerdirs; my @libdirs; +my $cachekey; +my $cacheval; # Show usage and croak sub usage { @@ -70,6 +73,8 @@ Usage: $base [flags] c++-compiler: Returns name of C++ compiler Optional flags: + -c CACHE: settings will be dynamically determined unless present in + CACHE; new settings will be added to CACHE -h: to show short help for an action, e.g. try '$base -h so-name' -s: to suppress showing of warnings -v: to show verbose messages @@ -187,10 +192,16 @@ sub subfiles ($$$) { } } -# Output stuff +# Output stuff, update $cacheval incase we'll add it to the cache later. sub output { - print (' ') if ($printed++); + if ($printed++) { + print (' '); + $cacheval .= ' '; + } print (@_); + for my $a (@_) { + $cacheval .= $a; + } } # Find a header, output a define if found. @@ -506,7 +517,29 @@ sub test_libfunction { $base = $0; $base =~ s{.*/}{}; -usage () unless (getopts ('vhI:L:s', \%opts)); +usage () unless (getopts ('vhI:L:sc:', \%opts)); + +# See if we got a cache with the requests in it. +# If we can match the request, return the result. +if ($opts{c}) { + $cachekey = ''; + for my $a (@ARGV) { + $cachekey .= ' ' if ($cachekey ne ''); + $cachekey .= $a; + } + if (open (my $if, $opts{c})) { + while (my $line = <$if>) { + chomp ($line); + my ($key, $val) = split (/\t/, $line); + if ($key eq $cachekey) { + output ($val); + print ("\n"); + exit (0); + } + } + } +} + foreach my $d (split (/,/, $opts{L})) { push (@libdirs, $d); } @@ -547,6 +580,14 @@ if ($action eq 'header') { } print ("\n") if ($printed); + +# Add to the cache if necessary. +if ($opts{c}) { + open (my $of, ">>$opts{c}") + or die ("Cannot append to cache file $opts{c}: $!\n"); + print $of ("$cachekey\t$cacheval\n"); +} + if ($#warnings > -1) { foreach my $w (@warnings) { print STDERR ("$base WARNING: $w") unless ($opts{s});