commit 1869b862162fc85e367a7c3bfa05e57c54fcac60
parent ff111edf4c8234ee53cd2ec85bd06f133c97eb50
Author: finwo <finwo@pm.me>
Date: Sat, 3 Jan 2026 19:31:43 +0100
1.44
Diffstat:
231 files changed, 5793 insertions(+), 3414 deletions(-)
diff --git a/ChangeLog b/ChangeLog
@@ -1,6 +1,25 @@
ChangeLog for Crossroads
------------------------------------------------------------------------------
+1.44 [KK 2007-06-12]
+ - Small bugfix in -b flag handling (useful during debugging only).
+
+1.43 [KK 2007-05-22]
+ - Changed the way that shmkeys are computed; the old way would
+ cause more collisions.
+ - Implemented DNS caching. By default 20 gethostbyname() results
+ can be cached, with a ttl of 1 hour per entry; though the ttl
+ has a default of 0 (no caching). Flag -d can overrule the TTL.
+ - Fixed makefile dependency for crossroads-daemon.
+ - Upped c-conf to 1.08.
+ - Reorganized docs. Key variables (author, maintainer, ...) are
+ passed from the Makefile.
+ - Added a small test run to the making: test/t*conf should parse
+ OK, test/bad*conf should fail. These tests are auto-run on
+ 'make local'.
+ - Added #include to the grammar. Shell-style #-comments are no
+ longer allowed. Added #define to the grammar.
+
1.42 [KK 2007-05-21]
- Fixed small portability issue for gcc 4.0.3 (library dependency
with libm.a)
diff --git a/Makefile b/Makefile
@@ -9,9 +9,11 @@ foo:
local:
BASE=$(BASE) $(MAKE) -C src
+ make -C test
-install:
+install: local
BASE=$(BASE) $(MAKE) -C src install
+ BASE=$(BASE) $(MAKE) -C doc install
documentation:
BASE=$(BASE) $(MAKE) -C doc
diff --git a/doc/Makefile b/doc/Makefile
@@ -1,14 +1,35 @@
include ../etc/Makefile.def
-foo:
- ../tools/untab *.yo
- yo2html -dVER=$(VER) crossroads
- yo2man -dVER=$(VER) crossroads
- yo2pdf -dVER=$(VER) crossroads
- $(MAKE) clean
+YODLINC = -I.:/usr/local/share/yodl:/usr/share/yodl:$(BASE)/doc/main
+
+foo: defs
+ find main -type f -name '*.yo' -exec ../tools/untab {} \;
+ cd man && yo2man crossroads
+ mv man/crossroads.man crossroads.1
+ cd man && yo2man $(YODLINC) crossroads.conf
+ mv man/crossroads.conf.man crossroads.conf.7
+ cd main && yo2pdf crossroads
+ mv main/crossroads.pdf .
+ rm -f main/*.aux main/*.latex main/*.log main/*.toc
+ cd main && yo2html crossroads
+ mv main/*.html .
+
+defs:
+ echo 'redef(VER)(1)($(VER))' > crossroads-defs.yo
+ echo 'redef(YEARS)(1)($(YEARS))' >> crossroads-defs.yo
+ echo 'redef(DEFAULTCONF)(1)($(DEFAULT_CONF))' >> crossroads-defs.yo
+ echo 'redef(AUTHORNAME)(1)($(AUTHORNAME))' >> crossroads-defs.yo
+ echo 'redef(DNSCACHETTL)(1)($(DNS_CACHETTL))' >> crossroads-defs.yo
+ echo 'redef(MAINTAINERNAME)(1)($(MAINTAINERNAME))' \
+ >> crossroads-defs.yo
+ echo 'redef(MAINTAINEREMAIL)(1)($(MAINTAINEREMAIL))' \
+ >> crossroads-defs.yo
+
+install:
+ $(BASE)/tools/installdoc $(PREFIX) crossroads.1 crossroads.conf.7
clean:
- rm -f *.aux *.latex *.log *.toc
+ rm -f crossroads-defs.yo
distclean: clean
rm -f *.html *.pdf *.man
diff --git a/doc/compiling.yo b/doc/compiling.yo
@@ -1,172 +0,0 @@
-subsect(Prerequisites)
-
-The creation of crossroads requires:
-
-itemization(
- it() Standard Unix tools, such as tt(sed), tt(awk), tt(Perl)
- (5.00 or better);
-
- it() A POSIX-compliant C compiler;
-
- it() Support for SYSV IPC, networking and so on.
-)
-
-Basically a Linux or Apple MacOSX box will do nicely. To compile and install
-crossroads, follow these steps.
-
-
-subsect(Compiling and installing)
-
-itemization(
- it() Obtain the source distribution. It can be found on
- lurl(http://crossroads.e-tunity.com). The distribution comes as an
- archive tt(crossroads-)em(type)tt(.tar.gz), where em(type) is
- tt(stable) or tt(devel).
-
- it() Unpack the archive in a sources directory using tt(tar
- xzf crossroads-)em(X.YY)tt(.tar.gz). The contents spill into a
- subdirectory tt(crossroads-)em(X.YY/).
-
- it() Change-dir into the directory.
-
- it() Next, edit tt(etc/Makefile.def) and verify that all
- compilation settings are to your likings. The settings are
- explained in the file. bf(Note that) the default distribution
- of tt(Makefile.def) is suited for Linux or Apple MacOSX
- systems. On other Unices, or on non-Unix systems, you must
- particularly pay attention to tt(SET_PROC_TITLE_BY...). When
- in doubt, set the tt(SET_PROC_TITLE...)
- settings to 0. Crossroads will work nevertheless, but it won't show
- nice titles in tt(ps) listings. Also there's a macro
- tt(EXTRA_LIBS) to add linkage flags (an example for a Solaris
- build is included).
-
- it() Now crossroads is ready for compilation. Do a tt(make
- local) followed by tt(make install). The latter step may have
- to be done by the user tt(root) if the tt(BINDIR) setting of
- tt(etc/Makefile.def) points to a root-owned directory.
-
- it() The documentation doesn't install in this process. If you
- want to install the documentation, then proceed as follows:
-
- itemization(
- it() Optionally, tt(cp doc/crossroads.html)
- em(htmldirectory/); where em(htmldirectory) is the destination
- directory for your HTML manuals;
-
- it() Optionally, tt(cp doc/crossroads.pdf)
- em(pdfdirectory/); where em(pdfdirectory) is the
- destination directory for your PDF manuals;
-
- it() Optionally, tt(cp doc/crossroads.man)
- em(manualdirectory)tt(/crossroads.1), where
- em(manualdirectory) is e.g. tt(/usr/man/man1),
- tt(/usr/share/man1), tt(/usr/local/man/man1),
- tt(/usr/local/share/man1). Any possibility is valid, as
- long as em(manualdirectory) is one of the directories
- where manual pages are stored;
-
- it() If your manual page system supports compressed
- manual pages, then you can save some space with
- tt(gzip) em(manualdirectory)tt(/crossroads.1).)
-
-)
-
-
-subsect(Configuring crossroads)
-
-Now that the binary is available on your system, you need to create a
-suitable tt(/etc/crossroads.conf). Use this manual or the output of
-tt(crossroads samplconf) to get started.
-
-Once you have the configuration ready, start crossroads with
-tt(crossroads start). Test the availability of your services and back
-ends. Monitor how crossroads is doing with:
-
-itemization(
- it() In one terminal, run the script:
- verb(\
-while [ 1 ] ; do
- tput clear
- crossroads status
- sleep 3
-done)
-
- bf(Note) that depending on your system you might need
- tt(sleep 3s), i.e., with an tt(s) appended.
-
- it() In another terminal, run:
- verb(\
-while [ 1 ] ; do
- tput clear
- ps ax | grep crossroads | grep -v grep
- sleep 3
-done)
-
- bf(Note) that depending on your system you might need
- tt(ps -ef) instead of tt(ps ax).
-
- it() In yet another terminal, run tt(tail -f
- /var/log/messages) (supply the appropriate system log file if
- tt(/var/log/messages) doesn't work for you).)
-
-Now thoroughly test the availability of your back ends through
-crossroads. The status display will show an updated view of which back
-ends are selected and how busy they are. The process list will show
-which crossroads daemons are running. Finally, the tailing of
-tt(/var/log/messages) shows what's going on -- especially if you have
-tt(verbosity true) statements in the configuration.
-
-
-subsect(A boot script)
-
-Finally, you may want to create a boot-time startup script. The exact
-procedure depends on the used Unix flavor.
-
-subsubsect(SysV Style Startup)
-
-On SysV style systems, there's a startup script directory
-tt(/etc/init.d) where bootscripts for all utilities are located.
-You may have the tt(chkconfig) utility to automate the task of
-inserting scripts into the boot sequence, but
-otherwise the steps will resemble the following.
-
-itemization(
- it() Create a script tt(crossroads) in tt(/etc/init.d) similar to the
- following:
-
-verb(\
-#!/bin/sh
-/usr/local/bin/crossroads -v $@)
-
- The stated directory tt(/usr/local/bin) must correspond with
- the installation path. The flag tt(-v) causes the startup to
- be more 'verbose'. However, once daemonized, the verbosity is
- controlled by the appropriate statements in the configuration.
-
- it() Determine your 'runlevel': usually 3 when your system is
- running in text-mode only, or 5 when you are using a graphical
- interface. If your runlevel is 3, then:
-
-verb(\
-root> cd /etc/rc.d/rc3.d
-root> ln -s /etc/init.d/crossroads S99crossroads
-root> ln -s /etc/init.d/crossroads K99crossroads)
-
- This creates startup (tt(S*)) and stop (tt(K*)) links that
- will be run when the system enters or leaves a given runlevel.
-
- If your runlevel is 5, then the right tt(cd) command is to
- tt(/etc/rc.d/rc5.d). Alternatively, you can create the
- symlinks in both runlevel directories.)
-
-subsubsect(BSD Style Startup)
-
-On BSD style systems, daemons are booted directly from tt(/etc/rc) and
-related scripts. Incase you have a file tt(/etc/rc.local), edit it,
-and add the statement:
-
-verb(/usr/local/bin/crossroads start)
-
-If your BSD system lacks tt(/etc/rc.local), then you may need to start
-Crossroads from tt(/etc/rc). Your mileage may vary.
diff --git a/doc/conf/addclientheader.yo b/doc/conf/addclientheader.yo
@@ -1,142 +0,0 @@
-conf(HTTP Header Modification Directives)
- (Crossroads understands the following
- header modification directives: tt(addclientheader),
- tt(appendclientheader), tt(setclientheader), tt(addserverheader),
- tt(appendserverheader), tt(setserverheader).
-
- The directive names always consist of
- em(Action)em(Destination)tt(header), where:
-
- itemization(
- it() The action is tt(add), tt(append) or tt(insert).
-
- itemization(
- it() Action tt(add) adds a header, even when headers with
- the same name already are present in an HTTP
- message. Adding headers is useful for e.g. tt(Set-Cookie)
- headers; a message may contain several of such headers.
-
- it() Action tt(append) adds a header if it isn't present
- yet in an HTTP message. If such a header is already
- present, then the value is appended to the pre-existing
- header. This is useful for e.g. tt(Via) headers. Imagine
- an HTTP message with a header tt(Via: someproxy). Then the
- directive tt(appendclientheader "Via: crossroads") will
- rewrite the header to tt(Via: someproxy; crossroads).
-
- it() Action tt(set) overwrites headers with the same
- name; or adds a new header if no pre-existing is found.
- This is useful for e.g. tt(Host) headers.)
-
- it() The destination is one of tt(client) or tt(server). When
- the destination is tt(server), then Crossroads will apply such
- directives to HTTP messages that originate from the browser
- and are being forwarded to back ends. When the destination is
- tt(client), then Crossroads will apply such directives to
- backend responses that are shuttled to the browser.)
-
- The format of the directives is e.g. tt(addclientheader
- "X-Processed-By: Crossroads"). The directives expect one
- argument; a string, consisting of a header name, a colon, and a
- header value. As usual, the directive must end with a semicolon.
-
- The header value may contain one of the following formatting
- directives:
-
- INCLUDEFILE(formattable.yo)
-
- The following examples show common uses of header modifications.
-
- description(
- dit(Enforcing session stickiness:) By combining
- tt(stickycookie) and tt(addclientheader), HTTP session
- stickiness is enforced. Consider the following configuration:
-
- verb(\
-service ... {
- ...
- backend one {
- ...
- addclientheader "Set-Cookie: BalancerID=first; path=/";
- stickycookie "BalancerID=first";
- }
- backend two {
- ...
- addclientheader "Set-Cookie: BalancerID=second; path=/";
- stickycookie "BalancerID=second";
- }
-})
-
- The first request of an HTTP session is balanced to either
- backend tt(one) or tt(two). The server response is enriched
- using tt(addclientheader) with an appropriate cookie. A
- subsequent request from the same browser now has that cookie
- in place; and is therefore sent to the same back end where the
- its predecessors went.
-
- dit(Hiding the server software version:) Many servers
- (e.g. Apache) advertize their version, as in tt(Server: Apache
- 1.27). This potentially provides information to attackers. The
- following configuration hides such information:
-
- verb(\
-service ... {
- ...
- backend one {
- ...
- setclientheader "Server: WWW-Server";
- }
-})
-
- dit(Informing the server of the clients' IP address:) Since
- Crossroads sits 'in the middle' between a client and a back
- end, the back end perceives Crossroads as its client. The
- following sends the true clients' IP address to the server, in
- a header tt(X-Real-IP):
-
- verb(\
-service ... {
- ...
- backend one {
- ...
- setserverheader "X-Real-IP: %r";
- }
-})
-
- dit(Keep-Alive Downgrading:) The directives
- tt(setclientheader) and tt(setserverheader) also play a key
- role in downgrading Keep-Alive connections to
- 'single-shot'. E.g., the following configuration makes sure
- that no Keep-Alive connections occur.
-
- verb(\
-service ... {
- ...
- backend one {
- ...
- setserverheader "Connection: close";
- setclientheader "Connection: close";
- }
-})))
- (itemization(
- it() tt(addclientheader) em(Headername: headervalue) to add a
- header in the traffic towards the client, even when another
- header em(Headername) exists;
- it() tt(appendclientheader) em(Headername: headervalue) to
- append em(headervalue) to an existing header em(Headername)
- in the traffic towards the client,
- or to add the whole header alltogether;
- it() tt(setclientheader) em(Headername: headervalue) to
- overwrite an existing header in the traffic towards the
- client, or to add such a header;
- it() tt(addserverheader) em(Headername: headervalue) to add a
- header in the traffic towards the server, even when another
- header em(Headername) exists;
- it() tt(appendserverheader) em(Headername: headervalue) to
- append em(headervalue) to an existing header em(Headername)
- in the traffic towards the server,
- or to add the whole header alltogether;
- it() tt(setserverheader) em(Headername: headervalue) to
- overwrite an existing header in the traffic towards the
- server, or to add such a header.))
- (There is no default.)
diff --git a/doc/conf/allow.yo b/doc/conf/allow.yo
@@ -1,65 +0,0 @@
-conf(allow* and deny* - Allowing or denying connections)
- (Crossroads can allow or deny
- connections based on the IP address of a client. There are four
- directives that are relevant: tt(allowfrom), tt(allowfile),
- tt(denyfrom) and tt(denyfile). When using tt(allowfrom) and
- tt(denyfrom) then the IP addresses to allow or deny connections are
- stated in tt(/etc/crossroads.conf).
-
- When tt(allow*) directives are used, then all connections are denied
- unless they match the stated allowed IP's. When tt(deny*) directives
- are used, then all connections are allowed unless they match the
- stated disallowed IP's. When denying and allowing is both used,
- then the Crossroads checks the deny list first.
-
- The statements tt(allowfrom) and tt(denyfrom) are followed by a
- list of filter specifications. The statements tt(allowfile) and
- tt(denyfile) are followed by a filename; Crossroads will read
- filter specifications from those external files. In both cases,
- Crossroads obtains filter specifications and places them in its
- lists of allowed or denied IP addresses. The difference between
- specifying filters in tt(/etc/crossroads.conf) or in external
- files, is that Crossroads will reload the external files when it
- receives signal 1 (tt(SIGHUP)), as in tt(killall -1 crossroads).
-
- The filter specifications must obey the following syntax: it
- consists of up to
- four numbers ranging from 0 to 255 and separated by a decimal
- sign. Optionally a slash follows, with a bitmask which is also a
- decimal number.
-
- This is probably best explained by a few examples:
-
- itemization(
- it() tt(allowfrom 10/8;) will allow connections from
- tt(10.*.*.*) (a full Class A network). The mask tt(/8) means
- that the first 8 bits of the number (ie., only the tt(10)) are
- significant. On the last 3 positions of the IP address, all
- numbers are allowed. Given this directive, client connections
- from e.g. 10.1.1.1 and 10.2.3.4 will be allowed.
-
- it() tt(allowfrom 10.3/16;) will allow all IP addresses that
- start with tt(10.3).
-
- it() tt(allowfrom 10.3.1/16;) is the same as above. The third
- byte of the IP address is superfluous because the netmask
- specifies that only the first 16 bits (2 numbers) are taken
- into account.
-
- it() tt(allowfrom 10.3.1.15;) allows traffic from only the
- specified IP address. There is no bitmask; all four numbers
- are relevant.
-
- it() tt(allowfrom 10.3.1.15 10.2/16;) allows traffic from one
- IP address tt(10.3.1.15) or from a complete Class B network
- tt(10.2.*.*)
-
- it() tt(allowfile /tmp/myfile.txt;) in combination with a file
- tt(/tmp/myfile.txt), with the contents tt(10.3.1.15 10.2/16),
- is the same as above.))
- (itemization(
- it() tt(allowfrom) em(filter-specificication(s))
- it() tt(denyfrom) em(filter-specificication(s))
- it() tt(allowfile) em(filename)
- it() tt(denyfile) em(filename)))
- (In absence of these statements, all client IP's are accepted.)
diff --git a/doc/conf/dispatchmode.yo b/doc/conf/dispatchmode.yo
@@ -1,84 +0,0 @@
-conf(dispatchmode - How are back ends selected)
- (The dispatch mode controls how crossroads selects a back end from
- a list of active back ends. The below text shows the bare
- syntax. See section ref(howselected) for a textual explanation.
-
- The settings can be:
-
- itemization(
- it() tt(dispatchmode roundrobin): Simply the 'next in line' is
- chosen. E.g, when 3 back ends are active, then the usage
- series is 1, 2, 3, 1, 2, 3, and so on.
-
- Roundrobin dispatching is the default method, when no
- tt(dispatchmode) statement occurs.
-
- it() tt(dispatchmode random): Random selection. Probably only
- for stress testing, though when used with weights (see below)
- it is a good distributor of new connections too.
-
- it() tt(dispatchmode bysize [ over) em(connections) tt(]):
- The next back end is the one
- that has transferred the least number of bytes. This
- selection mechanism assumes that the more bytes, the heavier
- the load.
-
- The modifier tt(over) em(connections) is optional. (The square
- brackets shown above are not part of the statement but
- indicate optionality.) When given,
- the load is computed as an average of the last stated number of
- connections. When this modifier is absent, then the load is
- computed over all connections since startup.
-
- it() tt(dispatchmode byduration [ over) em(connections) tt(]):
- The next back end is the one
- that served connections for the shortest time. This mechanism
- assumes that the longer the connection, the heavier the load.
-
- it() tt(dispatchmode byconnections): The next back end is the one
- with the least active connections. This mechanism assumes that
- each connection to a back end represents load. It is usable
- for e.g. database connections.
-
- it() tt(dispatchmode byorder): The first back end is selected
- every time, unless it's unavailable. In that case the second
- is taken, and so on.
-
- it() tt(dispatchmode byclientip): The client's IP address is
- 'hashed' into a number, which is used to pick a back end. The
- same client IP address will therefore always be dispatched to
- the same back end. When the back end of choice is down,
- tt(dispatchmode byconnections) is used.
-
- it() tt(dispatchmode externalhandler) em(program arguments):
- This is a special mode, where an external program is delegated
- the responsibility to say which back end should be used
- next. In this case, Crossroads will call the external program,
- and this will of course be slower than one of the 'built-in'
- dispatch modes. However, this is the ultimate escape when
- custom-made dispatch modes are needed.
-
- The dispatch mode that uses an tt(externalhandler) is
- discussed separately in section ref(externalhandler).)
-
- The selection algorithm is only used when clients are serviced that
- aren't part of a sticky HTTP session. This is the case during:
-
- itemization(
- it() all client requests of a service type tt(any);
- it() new sessions of a service type tt(http).)
-
- When type tt(http) is in effect and a session is underway, then the
- previously used back end is always selected -- regardless of
- dispatching mode.
-
- Your 'right' dispatch mode will depend on the type of service. Given
- the fact that crossroads doesn't know (and doesn't care) how to
- estimate load from a network traffic stream, you have to choose an
- appropriate dispatch mode to optimize load balancing. In most cases,
- tt(roundrobin) or tt(byconnections) will do the job just fine.)
- (tt(dispatchmode) em(mode) (see above for the modes), optionally
- followed by tt(over) em(number), or when the em(mode) is
- tt(externalhandler), followed by em(program).)
- (tt(roundrobin))
-
diff --git a/doc/conf/onhooks.yo b/doc/conf/onhooks.yo
@@ -1,25 +0,0 @@
-conf(onstart, onend, onfail - Action Hooks)
- (The three directives tt(onstart), tt(onend) and tt(onfail) can be
- specified to start system commands (external programs) when a
- connection to a back end starts, fails or ends:
- itemization(
- it() tt(onstart) commands will be run when Crossroads
- successfully connects to a back end, and starts servicing;
- it() tt(onend) commands will be run when a (previously
- established) connection stops;
- it() tt(onfail) commands will be run when Crossroads tries to
- contact a back end to serve a client, but the back end can't
- be reached.)
-
- The format is always tt(on)em(type) em(command). The em(command)
- is an external program, optionally followed by arguments. The
- command is expanded according to the following table:
-
- INCLUDEFILE(formattable))
- (itemization(
- it() tt(onstart) em(commandline)
- it() tt(onend) em(commandline)
- it() tt(onfail) em(commandline)
- it() tt(onsuccess) em(commandline)))
- (There is no default. Normally no external programs are run upon
- connection, success or failure of a back end.)
diff --git a/doc/conf/server.yo b/doc/conf/server.yo
@@ -1,10 +0,0 @@
-conf(server - Specifying the back end address)
- (Each back end must be identified by the network name
- (server name) where it is located. For example: tt(server
- 10.1.1.23), or tt(server web.mydomain.org). A TCP port specifier
- can follow the server name, as in tt(server web.mydomain.org:80).)
- (itemization(
- it() tt(server) em(servername), where em(servername) is a
- network name or IP address;
- it() tt(server) em(servername:port)))
- (There is no default. This is a required setting.)
diff --git a/doc/conf/shmkey.yo b/doc/conf/shmkey.yo
@@ -1,17 +0,0 @@
-conf(shmkey - Shared Memory Access)
- (Different Crossroads
- invocations must 'know' of each others activity. E.g, tt(crossroad
- status) must be able to get to the actual state information of all
- running services. This is internally implemented through shared
- memory, which is reserved using a key.
-
- Normally crossroads will supply a shared memory key, based on the
- service port and bitwise or-ed with a magic number. In situations
- where this conflicts with existing keys (of other programs, having
- their own keys), you may supply a chosen value.
-
- The actual key value doesn't matter much, as long as it's unique
- and as long as each invocation of crossroads uses it.)
- (tt(shmkey) em(number))
- (0, which means that crossroads will 'guess' its
- own key, based on TCP port and a magic number.)
diff --git a/doc/conf/trafficlog.yo b/doc/conf/trafficlog.yo
@@ -1,17 +0,0 @@
-conf(trafficlog and throughputlog - Debugging and Performance Aids)
- (Two directives are available
- to log network traffic to files. They are tt(trafficlog) and
- tt(throughputlog).
-
- The tt(trafficlog) statement causes all traffic to be logged in
- hexadecimal format. Each line is prefixed by tt(B) or tt(C),
- depending on whether the information was received from the back
- end or from the client.
-
- The tt(throughputlog) statement writes shorthand transmissions to
- its log, accompanied by timings.)
- (itemization(
- it() tt(trafficlog) em(filename)
- it() tt(throughputlog) em(filename)))
- (none)
-
diff --git a/doc/conf/useraccount.yo b/doc/conf/useraccount.yo
@@ -1,14 +0,0 @@
-conf(useraccount - Limiting the effective ID of external processes)
- (Using the directive tt(useraccount), the effective user and group
- ID can be restricted. This comes into effect when Crossroads runs
- external commands, such as:
- itemization(
- it() Hooks for tt(onstart), tt(onend) or tt(onfail);
- it() External dispatchers, when tt(dispatchmode
- externalhandler) is in effect.)
- Once a user name for external commands is specified, Crossroads
- assumes the associated user ID and group ID before running those
- commands.)
- (tt(useraccount) em(username))
- (None; when unspecified, external commands are run with the
- ID that was in effect when Crossroads was started.)
-\ No newline at end of file
diff --git a/doc/conf/verbose-backend.yo b/doc/conf/verbose-backend.yo
@@ -1,10 +0,0 @@
-conf(verbosity - Controlling verbosity at the back end level)
- (Similar to tt(service) specifications, a
- tt(backend) can have its own verbosity (tt(on) or tt(off)). When
- tt(on), traffic to and fro this back end is reported.)
- (itemization(
- it() tt(verbosity) em(setting), or
- it() tt(verbose) em(setting), where em(setting) is tt(true),
- tt(yes) or tt(on), or tt(false), tt(no), tt(off) to turn it
- off.))
- (tt(off))
diff --git a/doc/config.yo b/doc/config.yo
@@ -1,151 +0,0 @@
-The configuration that crossroads uses is normally stored in the file
-tt(/etc/crossroads.conf). This location can be overruled using the
-command line flag tt(-c).
-
-This section explains the syntax of the configuration file, and what
-all settings do.
-
-subsect(General language elements)
-
-This section describes the general elements of the crossroads
-configuration language.
-
-
-subsubsect(Empty lines and comments)
-
-Empty lines are of course allowed in the
-configuration. Crossroads recognizes three formats of comment:
-
-itemization(
- it() C-style, between tt(/*) and tt(*/),
- it() C++-style, starting with tt(//) and ending with the end
- of the text line;
- it() Shell-style, starting with tt(#) and ending with the end
- of the text line.)
-
-Simply choose your favorite editor and use the comment that 'looks
-best'.footnote(I favor C or C++ comment. My favorite editor em(emacs)
-can be put in tt(cmode) and nicely highlight what's comment and what's
-not. And as a bonus it will auto-indent the configuration!)
-
-
-subsubsect(Keywords, numbers, identifiers, generic strings)
-
-In a configuration file, statements are identified by em(keywords),
-such as tt(service), tt(verbosity). These are reserved words.
-
-Many keywords require an em(identifier) as the argument. E.g, a
-service has a unique name, which must start with a letter or
-underscore, followed by zero or more letters, underscores, or
-digits. Therefore, in the statement tt(service myservice), the keyword is
-tt(service) and the identifier is tt(myservice).
-
-Other keywords require a numeric argument. Crossroads knows only
-non-negative integer numbers, as in tt(port 8000). Here, tt(port) is
-the keyword and tt(8000) is the number.
-
-Yet other keywords require 'generic strings', such as hostname
-specifications or system commands. Such generic strings contain any
-characters (including white space) up to the terminating statement
-character tt(;). If a string must contain a semicolon, then it must
-be enclosed in single or double quotes:
-
-itemization(
- it() tt(This is a string;) is a string that starts at tt(T)
- and ends with tt(g)
- it() tt("This is a string";) is the same, the double quotes
- are not necessary
- it() tt("This is ; a string";) has double quotes to protect
- the inner ;)
-
-Finally, an argument can be a 'boolean' value. Crossroads knows
-tt(true), tt(false), tt(yes), tt(no), tt(on), tt(off). The keywords
-tt(true), tt(yes) and tt(on) all mean the same and can be used
-interchangeably; as can the keywords tt(false), tt(no) and tt(off).
-
-
-subsect(Service definitions) label(servicedef)
-
-Service definitions are blocks in the configuration file that
-state what is for each service. A service definition starts with
-tt(service), followed by a unique identifier, and by statements in
-tt({) and tt(}). For example:
-
-verb(\
-// Definition of service 'www':
-service www {
- ...
- ... // statements that define the
- ... // service named 'www'
- ...
-})
-
-The configuration file can contain many service blocks, as long as the
-identifying names differ. The following list shows possible
-statements. Each statement must end with a semicolon, except for the
-tt(backend) statement, which has is own block (more on this later).
-
-redef(conf)(4)(\
- subsubsect(ARG1) label(confARG1)
- startdit()
- dit(Description:) ARG2
- dit(Syntax:) ARG3
- dit(Default:) ARG4
- enddit())
-
-
-includefile(conf/type)
-includefile(conf/port)
-includefile(conf/bindto)
-includefile(conf/verbose)
-includefile(conf/dispatchmode)
-includefile(conf/revivinginterval)
-includefile(conf/maxconnections)
-includefile(conf/backlog)
-includefile(conf/shmkey)
-includefile(conf/allow)
-includefile(conf/useraccount)
-
-
-subsect(Backend definitions)
-
-Inside the service definitions as are described in the previous
-section, em(backend definitions) must also occur. Backend definitions
-are started by the keyword tt(backend), followed by an identifier
-(the back end name) , and statements inside tt({) and tt(}):
-
-verb(\
-service myservice {
- ...
- ... // statements that define the
- ... // service named 'myservice'
- ...
-
- backend mybackend {
- ...
- ... // statements that define the
- ... // backend named 'mybackend'
- ...
- }
-})
-
-Each service definition must have at least one backend
-definition. There may be more (and probably will, if you want
-balancing and fail over) as long as the backend names differ.
-The statements in the backend definition blocks are described in the
-following sections.
-
-Some directives (tt(stickycookie) etc.) only have effect when
-Crossroads treats the network traffic as a stream of HTTP messages;
-i.e., when the service is declared with tt(type http). Incase of
-tt(type any), the HTTP-specific directives have no effect.
-
-includefile(conf/server.yo)
-includefile(conf/verbose-backend.yo)
-includefile(conf/retries.yo)
-includefile(conf/weight)
-includefile(conf/decay)
-includefile(conf/onhooks)
-includefile(conf/trafficlog)
-includefile(conf/stickycookie)
-includefile(conf/addclientheader)
diff --git a/doc/crossroads.1 b/doc/crossroads.1
@@ -0,0 +1,134 @@
+.SH "e-tunity"
+.TH "crossroads" "1" "2005-2007" "crossroads" ""
+.SH "NAME"
+crossroads \- Load balancer and fail over utility
+.PP
+.SH "SYNOPSIS"
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBstart\fP: starts Crossroads
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBstop\fP: stops Crossroads
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBrestart\fP: restarts Crossroads
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBconfigtest\fP: verifies
+configuration
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBservices\fP: shows configured
+services
+.IP o
+\fBcrossroads\fP \fI[flags]\fP \fBtell\fP \fIservice\fP
+\fIbackend\fP \fIstate\fP: sets a back end state
+.PP
+.SH "DESCRIPTION"
+
+.PP
+\fBcrossroads\fP is the main control program of Crossroads, a
+balancing and fail over utility\&. The Crossroads utility consists
+of two binaries: \fBcrossroads\fP and \fBcrossroads-daemon\fP\&. The
+latter is controlled by the front end \fBcrossroads\fP\&.
+.PP
+Recognized states in \fBcrossroads tell\fP are:
+.PP
+.IP o
+\fBavailable\fP or \fBup\fP when a backend is working;
+.IP o
+\fBunavailable\fP when a back end is temporarily down, but
+can be woken up;
+.IP o
+\fBdown\fP when a back end is permanently down (e\&.g\&., for
+maintenance)\&. Crossroads itself will never activate a
+backend in this state\&.
+.IP o
+\fBwaking\fP when the live status of a back end is being checked\&.
+.PP
+.SH "OPTIONS"
+
+.PP
+Crossroads recognizes the following flags:
+.PP
+.IP o
+\fB-a\fP: Logs start and end times of activity to
+\fIsyslog\fP\&.
+.IP
+.IP o
+\fB-b\fP: Writes a binary representation of the
+configuration to \fIstdout\fP\&. For debugging only\&.
+.IP
+.IP o
+\fB-C\fP: Writes the compile time configuration to
+\fIstdout\fP and stops\&. Useful when submitting bug reports\&.
+.IP
+.IP o
+\fB-c\fP \fIconfig\fP: Uses \fIconfig\fP as the configuration
+file\&. The default is \fB/etc/crossroads\&.conf\fP\&.
+.IP
+.IP o
+\fB-d\fP \fIsec\fP: Sets the DNS cache time-to-live to
+\fIsec\fP seconds\&. Value 0 suppresses DNS entry
+caching\&. The default is \fB0\fP\&.
+.IP
+.IP o
+\fB-l\fP \fIfacility\fP: Specifies the openlog (3) facility,
+default is \fBLOG_DAEMON\fP\&. Values can be 0 to 7, meaning
+\fBLOG_LOCAL0\fP to \fBLOG_LOCAL9\fP\&.
+.IP
+.IP o
+\fB-m\fP \fIpermissions\fP: Specifies shared memory
+permissions, default is \fB0644\fP\&.
+.IP
+.IP o
+\fB-s\fP: Requests \&'sloppy\&' binding to TCP ports\&. When a
+port is busy, Crossroads will retry periodically to get
+it\&. Default is to stop when a listening port cannot be
+obtained\&.
+.IP
+.IP o
+\fB-t\fP: Output of \fBcrossroads status\fP is shown as a
+tabular view, in one or more lines of:
+.IP
+\fIservice\fP \fIbackend=state\fP \fI[backend=state\&.\&.\&.]\fP
+.IP
+.IP o
+\fB-x\fP: Output of \fBcrossroads status\fP is shown as an
+XML document\&.
+.IP
+.IP o
+\fB-v\fP: Initial actions of Crossroads are more
+\&'verbose\&'\&. (Once daemonized, the verbosity is controlled
+using \fBverbosity\fP statements in the configuration\&.)
+.IP
+.IP o
+\fB-V\fP: Shows the version ID and stops\&.
+.IP
+.IP o
+\fB-?, -h\fP: Shows an overview of the usage\&.
+.PP
+.SH "FILES"
+\fB/etc/crossroads\&.conf\fP, the default configuration file
+.PP
+.SH "SEE ALSO"
+.IP o
+crossroads\&.conf (7)
+.IP o
+The full Crossroads documentation in html or pdf format,
+distributed with the sources\&.
+.PP
+.SH "BUGS"
+Crossroads is of course bug free (haha)\&. When submitting bugs to
+the maintainer\&. please always include the following information:
+.PP
+.IP o
+The configuration file that Crossroads uses;
+.IP o
+The compile-time configuration, which is the output of
+\fBcrossroads -C\fP;
+.IP o
+A good description of the bug, and of the conditions
+under which it occurs\&.
+.PP
+.SH "AUTHOR"
+.IP o
+Author: Karel Kubat
+.IP o
+ Maintainer: Karel Kubat karel@kubat\&.nl
+\ No newline at end of file
diff --git a/doc/crossroads.conf.7 b/doc/crossroads.conf.7
@@ -0,0 +1,937 @@
+.SH "e-tunity"
+.TH "crossroads\&.conf" "7" "2005-2007" "crossroads" ""
+.SH "NAME"
+crossroads\&.conf \- Crossroads configuration
+.PP
+.SH "SYNOPSIS"
+This manpage describes the configuration of Crossroads, normally the
+file \fB/etc/crossroads\&.conf\fP\&. Crossroads can however be started with a flag
+\fB-c\fP to overrule this name\&.
+.PP
+.SH "DESCRIPTION"
+The configuration that crossroads uses is normally stored in the file
+/etc/crossroads\&.conf\&. This location can be overruled using the
+command line flag \f(CW-c\fP\&.
+.PP
+This section explains the syntax of the configuration file, and what
+all settings do\&.
+.PP
+.SH "General language elements"
+
+.PP
+This section describes the general elements of the crossroads
+configuration language\&.
+.PP
+\fBEmpty lines and comments\fP
+.PP
+Empty lines are of course allowed in the
+configuration\&. Crossroads recognizes three formats of comment:
+.PP
+.IP o
+C-style, between \f(CW/*\fP and \f(CW*/\fP,
+.IP o
+C++-style, starting with \f(CW//\fP and ending with the end
+of the text line\&.
+.PP
+Simply choose your favorite editor and use the comment that \&'looks
+best\&'\&.\e (I favor C or C++ comment\&. My favorite editor \fIemacs\fP
+can be put in \f(CWcmode\fP and nicely highlight what\&'s comment and what\&'s
+not\&. And as a bonus it will auto-indent the configuration!)
+.PP
+\fBPreprocessor directives\fP
+.PP
+Similar to \fBC\fP or \fBC++\fP, the Crossroads grammar knows \f(CW#include\fP
+and \f(CW#define\fP\&. Both directives must start at the first column of the
+line (ie\&., the \f(CW#\fP sign must occur at the leftmost line
+position)\&.
+.PP
+.IP o
+\f(CW#include\fP \f(CW"\fP\fIfilename\fP\f(CW"\fP includes the stated file
+name at the place of the statement\&.
+.IP o
+\f(CW#define\fP \fISYMBOL\fP \fIDEFINITION\fP defines \fISYMBOL\fP
+as placeholder for \fIDEFINITION\fP\&.
+.PP
+For example, one may use the configuration:
+.PP
+.nf
+#define SERVICEPORT 80
+service web {
+ port SERVICEPORT;
+ \&.
+ \&. /* More statements follow here */
+ \&.
+}
+.fi
+
+.PP
+The \f(CWport\fP statement is then read as \f(CWport 80\fP\&.
+.PP
+\fBKeywords, numbers, identifiers, generic strings\fP
+.PP
+In a configuration file, statements are identified by \fIkeywords\fP,
+such as \f(CWservice\fP, \f(CWverbosity\fP\&. These are reserved words\&.
+.PP
+Many keywords require an \fIidentifier\fP as the argument\&. E\&.g, a
+service has a unique name, which must start with a letter or
+underscore, followed by zero or more letters, underscores, or
+digits\&. Therefore, in the statement \f(CWservice myservice\fP, the keyword is
+\f(CWservice\fP and the identifier is \f(CWmyservice\fP\&.
+.PP
+Other keywords require a numeric argument\&. Crossroads knows only
+non-negative integer numbers, as in \f(CWport 8000\fP\&. Here, \f(CWport\fP is
+the keyword and \f(CW8000\fP is the number\&.
+.PP
+Yet other keywords require \&'generic strings\&', such as hostname
+specifications or system commands\&. Such generic strings contain any
+characters (including white space) up to the terminating statement
+character \f(CW;\fP\&. If a string must contain a semicolon, then it must
+be enclosed in single or double quotes:
+.PP
+.IP o
+\f(CWThis is a string;\fP is a string that starts at \f(CWT\fP
+and ends with \f(CWg\fP
+.IP o
+\f(CW"This is a string";\fP is the same, the double quotes
+are not necessary
+.IP o
+\f(CW"This is ; a string";\fP has double quotes to protect
+the inner ;
+.PP
+Finally, an argument can be a \&'boolean\&' value\&. Crossroads knows
+\f(CWtrue\fP, \f(CWfalse\fP, \f(CWyes\fP, \f(CWno\fP, \f(CWon\fP, \f(CWoff\fP\&. The keywords
+\f(CWtrue\fP, \f(CWyes\fP and \f(CWon\fP all mean the same and can be used
+interchangeably; as can the keywords \f(CWfalse\fP, \f(CWno\fP and \f(CWoff\fP\&.
+.PP
+.SH "Service definitions"
+
+.PP
+Service definitions are blocks in the configuration file that
+state what is for each service\&. A service definition starts with
+\f(CWservice\fP, followed by a unique identifier, and by statements in
+\f(CW{\fP and \f(CW}\fP\&. For example:
+.PP
+.nf
+// Definition of service \&'www\&':
+service www {
+ \&.\&.\&.
+ \&.\&.\&. // statements that define the
+ \&.\&.\&. // service named \&'www\&'
+ \&.\&.\&.
+}
+.fi
+
+.PP
+The configuration file can contain many service blocks, as long as the
+identifying names differ\&. The following list shows possible
+statements\&. Each statement must end with a semicolon, except for the
+\f(CWbackend\fP statement, which has is own block (more on this later)\&.
+.PP
+\fBtype - Defining the service type\fP
+.IP "Description:"
+The \f(CWtype\fP statement defines how crossroads handles the stated
+service\&. There are currently two types: \f(CWany\fP and
+\f(CWhttp\fP\&. The type \f(CWany\fP means that crossroads doesn\&'t
+interpret the contents of a TCP stream, but only distributes streams
+over back ends\&. The type \f(CWhttp\fP means that crossroads has to
+analyze what\&'s in the messages, does magical HTTP header tricks, and
+so on -- all to ensure that multiple connections are treated as one
+session, or that the back end is notified of the client\&'s IP
+address\&.
+.IP
+Unless you really need such special features, use the type \f(CWany\fP (the
+default), even for HTTP protocols\&.
+.IP "Syntax:"
+\f(CWtype\fP \fIspecifier\fP, where \fIspecifier\fP is \f(CWany\fP or
+\f(CWhttp\fP
+.IP "Default:"
+\f(CWany\fP
+
+.PP
+\fBport - Specifying the listen port\fP
+.IP "Description:"
+The \f(CWport\fP statement defines to which TCP port a service
+\&'listens\&'\&. E\&.g\&. \f(CWport 8000\fP says that this service will accept
+connections on port 8000\&.
+.IP "Syntax:"
+\f(CWport\fP \fInumber\fP
+.IP "Default:"
+There is no default\&. This is a required setting\&.
+
+.PP
+\fBbindto - Binding to a specific IP address\fP
+.IP "Description:"
+The \f(CWbindto\fP statement is used in situations where crossroads
+should only listen to the stated port at a given IP address\&. E\&.g\&.,
+\f(CWbindto 127\&.0\&.0\&.1\fP causes crossroads to \&'bind\&' the service only to
+the local IP address\&. Network connections from other hosts won\&'t be
+serviced\&. By default, crossroads binds a service to all presently
+active IP addresses at the invoking host\&.
+.IP "Syntax:"
+\f(CWbindto\fP \fIaddress\fP, where \fIaddress\fP is a numeric IP
+address, such as 127\&.0\&.0\&.1, or the keyword \f(CWany\fP\&.
+.IP "Default:"
+\f(CWany\fP
+
+.PP
+\fBverbosity - Controlling debug output\fP
+.IP "Description:"
+Verbosity statements come in two forms: \f(CWverbosity on\fP or
+\f(CWverbosity off\fP\&. When \&'on\&', log messages to \f(CW/var/log/messages\fP
+are generated that show what\&'s going on\&.\e (Actually, the
+messages go to \f(CWsyslog(3)\fP, using facility \f(CWLOG_DAEMON\fP and
+priority \f(CWLOG_INFO\fP\&. In most (Linux) cases this will mean: output to
+\f(CW/var/log/messages\fP\&. On Mac OSX the messages go to
+\f(CW/var/log/system\&.log\fP\&.) The keyword \f(CWverbose\fP is an alias for
+\f(CWverbosity\fP\&.
+.IP "Syntax:"
+\f(CWverbosity\fP \fIsetting\fP or \f(CWverbose\fP \fIsetting\fP, where
+\fIsetting\fP is \f(CWtrue\fP, \f(CWyes\fP or \f(CWon\fP to turn
+verbosity on; or \f(CWfalse\fP, \f(CWno\fP, \f(CWoff\fP to turn it off\&.
+.IP "Default:"
+\f(CWoff\fP
+
+.PP
+\fBdispatchmode - How are back ends selected\fP
+.IP "Description:"
+ The dispatch mode controls how crossroads selects a back end from
+ a list of active back ends\&. The below text shows the bare
+ syntax\&. See section ?? for a textual explanation\&.
+.IP
+The settings can be:
+.IP
+.IP o
+\f(CWdispatchmode roundrobin\fP: Simply the \&'next in line\&' is
+chosen\&. E\&.g, when 3 back ends are active, then the usage
+series is 1, 2, 3, 1, 2, 3, and so on\&.
+.IP
+Roundrobin dispatching is the default method, when no
+\f(CWdispatchmode\fP statement occurs\&.
+.IP
+.IP o
+\f(CWdispatchmode random\fP: Random selection\&. Probably only
+for stress testing, though when used with weights (see below)
+it is a good distributor of new connections too\&.
+.IP
+.IP o
+\f(CWdispatchmode bysize [ over\fP \fIconnections\fP \f(CW]\fP:
+The next back end is the one
+that has transferred the least number of bytes\&. This
+selection mechanism assumes that the more bytes, the heavier
+the load\&.
+.IP
+The modifier \f(CWover\fP \fIconnections\fP is optional\&. (The square
+brackets shown above are not part of the statement but
+indicate optionality\&.) When given,
+the load is computed as an average of the last stated number of
+connections\&. When this modifier is absent, then the load is
+computed over all connections since startup\&.
+.IP
+.IP o
+\f(CWdispatchmode byduration [ over\fP \fIconnections\fP \f(CW]\fP:
+The next back end is the one
+that served connections for the shortest time\&. This mechanism
+assumes that the longer the connection, the heavier the load\&.
+.IP
+.IP o
+\f(CWdispatchmode byconnections\fP: The next back end is the one
+with the least active connections\&. This mechanism assumes that
+each connection to a back end represents load\&. It is usable
+for e\&.g\&. database connections\&.
+.IP
+.IP o
+\f(CWdispatchmode byorder\fP: The first back end is selected
+every time, unless it\&'s unavailable\&. In that case the second
+is taken, and so on\&.
+.IP
+.IP o
+\f(CWdispatchmode byclientip\fP: The client\&'s IP address is
+\&'hashed\&' into a number, which is used to pick a back end\&. The
+same client IP address will therefore always be dispatched to
+the same back end\&. When the back end of choice is down,
+\f(CWdispatchmode byconnections\fP is used\&.
+.IP
+.IP o
+\f(CWdispatchmode externalhandler\fP \fIprogram arguments\fP:
+This is a special mode, where an external program is delegated
+the responsibility to say which back end should be used
+next\&. In this case, Crossroads will call the external program,
+and this will of course be slower than one of the \&'built-in\&'
+dispatch modes\&. However, this is the ultimate escape when
+custom-made dispatch modes are needed\&.
+.IP
+The dispatch mode that uses an \f(CWexternalhandler\fP is
+ discussed separately in section ??\&.
+.IP
+The selection algorithm is only used when clients are serviced that
+aren\&'t part of a sticky HTTP session\&. This is the case during:
+.IP
+.IP o
+all client requests of a service type \f(CWany\fP;
+.IP o
+new sessions of a service type \f(CWhttp\fP\&.
+.IP
+When type \f(CWhttp\fP is in effect and a session is underway, then the
+previously used back end is always selected -- regardless of
+dispatching mode\&.
+.IP
+Your \&'right\&' dispatch mode will depend on the type of service\&. Given
+the fact that crossroads doesn\&'t know (and doesn\&'t care) how to
+estimate load from a network traffic stream, you have to choose an
+appropriate dispatch mode to optimize load balancing\&. In most cases,
+\f(CWroundrobin\fP or \f(CWbyconnections\fP will do the job just fine\&.
+.IP "Syntax:"
+\f(CWdispatchmode\fP \fImode\fP (see above for the modes), optionally
+followed by \f(CWover\fP \fInumber\fP, or when the \fImode\fP is
+\f(CWexternalhandler\fP, followed by \fIprogram\fP\&.
+.IP "Default:"
+\f(CWroundrobin\fP
+
+.PP
+\fBrevivinginterval - Back end wakeup calls\fP
+.IP "Description:"
+A reviving interval definition is needed when crossroads
+determines that a back end is temporarily unavailable\&. This will
+happen when:
+.IP
+.IP o
+The back end cannot be reached (network connection
+fails);
+.IP o
+The network connection to the back end suddenly dies\&.
+.IP
+An example of the definition is \f(CWrevivinginterval 10\fP\&. When this
+reviving interval is given, crossroads will check each 10 seconds
+whether unavailable back ends have woken up yet\&. A back end is
+considered awake when a network connection to that back end can
+succesfully be established\&.
+.IP "Syntax:"
+\f(CWrevivinginterval\fP \fInumber\fP, where the number is the interval
+in seconds\&.
+.IP "Default:"
+0 (no wakeup calls)
+
+.PP
+\fBmaxconnections - Limiting concurrent clients at service level\fP
+.IP "Description:"
+The maximum number of connections is specified using
+\f(CWmaxconnections\fP\&. There is one argument; the number of concurrent
+established connections that may be active within one service\&.
+.IP
+\&'Throttling\&' the number of connections is a way of preventing Denial of
+Service (DOS) attacks\&. Without a limit, numerous network connections
+may spawn so many server instances, that the service ultimately breaks
+down and becomes unavailable\&.
+.IP "Syntax:"
+\f(CWmaxconnections\fP \fInumber\fP, where the number specifies the
+maximum of concurrent connections to the service\&.
+.IP "Default:"
+0, meaning that all connections will be accepted\&.
+
+.PP
+\fBbacklog - The TCP Back Log size\fP
+.IP "Description:"
+The TCP back log size is a number that controls how many
+\&'waiting\&' network connections may be queued, before a client simply
+cannot connect\&. The syntax is e\&.g\&. \f(CWbacklog 5\fP to cause crossroads
+to have 5 waiting connections for 1 active connection\&.
+The backlog queue shouldn\&'t be too
+high, or clients will experience timeouts before they can actually
+connect\&. The queue shouldn\&'t be too small either, because clients
+would be simply rejected\&. Your mileage may vary\&.
+.IP "Syntax:"
+\f(CWbacklog\fP \fInumber\fP
+.IP "Default:"
+0, which takes the operating system\&'s default
+value for socket back log size\&.
+
+.PP
+\fBshmkey - Shared Memory Access\fP
+.IP "Description:"
+Different Crossroads
+invocations must \&'know\&' of each others activity\&. E\&.g, \f(CWcrossroad
+status\fP must be able to get to the actual state information of all
+running services\&. This is internally implemented through shared
+memory, which is reserved using a key\&.
+.IP
+Normally crossroads will supply a shared memory key, based on the
+service name\&. In situations where this conflicts with existing
+keys (of other programs, having their own keys), you may supply a
+chosen value\&.
+.IP
+The actual key value doesn\&'t matter much, as long as it\&'s unique
+and as long as each invocation of crossroads uses it\&.
+.IP "Syntax:"
+\f(CWshmkey\fP \fInumber\fP
+.IP "Default:"
+0, which means that crossroads will \&'guess\&' its
+own key, based on the service name\&.
+\fBallow* and deny* - Allowing or denying connections\fP
+.IP "Description:"
+Crossroads can allow or deny
+connections based on the IP address of a client\&. There are four
+directives that are relevant: \f(CWallowfrom\fP, \f(CWallowfile\fP,
+\f(CWdenyfrom\fP and \f(CWdenyfile\fP\&. When using \f(CWallowfrom\fP and
+\f(CWdenyfrom\fP then the IP addresses to allow or deny connections are
+stated in /etc/crossroads\&.conf\&.
+.IP
+When \f(CWallow*\fP directives are used, then all connections are denied
+unless they match the stated allowed IP\&'s\&. When \f(CWdeny*\fP directives
+are used, then all connections are allowed unless they match the
+stated disallowed IP\&'s\&. When denying and allowing is both used,
+then the Crossroads checks the deny list first\&.
+.IP
+The statements \f(CWallowfrom\fP and \f(CWdenyfrom\fP are followed by a
+list of filter specifications\&. The statements \f(CWallowfile\fP and
+\f(CWdenyfile\fP are followed by a filename; Crossroads will read
+filter specifications from those external files\&. In both cases,
+Crossroads obtains filter specifications and places them in its
+lists of allowed or denied IP addresses\&. The difference between
+specifying filters in /etc/crossroads\&.conf or in external
+files, is that Crossroads will reload the external files when it
+receives signal 1 (\f(CWSIGHUP\fP), as in \f(CWkillall -1 crossroads\fP\&.
+.IP
+The filter specifications must obey the following syntax: it
+consists of up to
+four numbers ranging from 0 to 255 and separated by a decimal
+sign\&. Optionally a slash follows, with a bitmask which is also a
+decimal number\&.
+.IP
+This is probably best explained by a few examples:
+.IP
+.IP o
+\f(CWallowfrom 10/8;\fP will allow connections from
+\f(CW10\&.*\&.*\&.*\fP (a full Class A network)\&. The mask \f(CW/8\fP means
+that the first 8 bits of the number (ie\&., only the \f(CW10\fP) are
+significant\&. On the last 3 positions of the IP address, all
+numbers are allowed\&. Given this directive, client connections
+from e\&.g\&. 10\&.1\&.1\&.1 and 10\&.2\&.3\&.4 will be allowed\&.
+.IP
+.IP o
+\f(CWallowfrom 10\&.3/16;\fP will allow all IP addresses that
+start with \f(CW10\&.3\fP\&.
+.IP
+.IP o
+\f(CWallowfrom 10\&.3\&.1/16;\fP is the same as above\&. The third
+byte of the IP address is superfluous because the netmask
+specifies that only the first 16 bits (2 numbers) are taken
+into account\&.
+.IP
+.IP o
+\f(CWallowfrom 10\&.3\&.1\&.15;\fP allows traffic from only the
+specified IP address\&. There is no bitmask; all four numbers
+are relevant\&.
+.IP
+.IP o
+\f(CWallowfrom 10\&.3\&.1\&.15 10\&.2/16;\fP allows traffic from one
+IP address \f(CW10\&.3\&.1\&.15\fP or from a complete Class B network
+\f(CW10\&.2\&.*\&.*\fP
+.IP
+.IP o
+\f(CWallowfile /tmp/myfile\&.txt;\fP in combination with a file
+\f(CW/tmp/myfile\&.txt\fP, with the contents \f(CW10\&.3\&.1\&.15 10\&.2/16\fP,
+is the same as above\&.
+.IP "Syntax:"
+.IP o
+\f(CWallowfrom\fP \fIfilter-specificication(s)\fP
+.IP o
+\f(CWdenyfrom\fP \fIfilter-specificication(s)\fP
+.IP o
+\f(CWallowfile\fP \fIfilename\fP
+.IP o
+\f(CWdenyfile\fP \fIfilename\fP
+.IP "Default:"
+In absence of these statements, all client IP\&'s are accepted\&.
+
+.PP
+\fBuseraccount - Limiting the effective ID of external processes\fP
+.IP "Description:"
+Using the directive \f(CWuseraccount\fP, the effective user and group
+ID can be restricted\&. This comes into effect when Crossroads runs
+external commands, such as:
+.IP o
+Hooks for \f(CWonstart\fP, \f(CWonend\fP or \f(CWonfail\fP;
+.IP o
+External dispatchers, when \f(CWdispatchmode
+externalhandler\fP is in effect\&.
+Once a user name for external commands is specified, Crossroads
+assumes the associated user ID and group ID before running those
+commands\&.
+.IP "Syntax:"
+\f(CWuseraccount\fP \fIusername\fP
+.IP "Default:"
+None; when unspecified, external commands are run with the
+ID that was in effect when Crossroads was started\&.
+
+.PP
+.SH "Backend definitions"
+
+.PP
+Inside the service definitions as are described in the previous
+section, \fIbackend definitions\fP must also occur\&. Backend definitions
+are started by the keyword \f(CWbackend\fP, followed by an identifier
+(the back end name) , and statements inside \f(CW{\fP and \f(CW}\fP:
+.PP
+.nf
+service myservice {
+ \&.\&.\&.
+ \&.\&.\&. // statements that define the
+ \&.\&.\&. // service named \&'myservice\&'
+ \&.\&.\&.
+
+ backend mybackend {
+ \&.\&.\&.
+ \&.\&.\&. // statements that define the
+ \&.\&.\&. // backend named \&'mybackend\&'
+ \&.\&.\&.
+ }
+}
+.fi
+
+.PP
+Each service definition must have at least one backend
+definition\&. There may be more (and probably will, if you want
+balancing and fail over) as long as the backend names differ\&.
+The statements in the backend definition blocks are described in the
+following sections\&.
+.PP
+Some directives (\f(CWstickycookie\fP etc\&.) only have effect when
+Crossroads treats the network traffic as a stream of HTTP messages;
+i\&.e\&., when the service is declared with \f(CWtype http\fP\&. Incase of
+\f(CWtype any\fP, the HTTP-specific directives have no effect\&.
+.PP
+\fBserver - Specifying the back end address\fP
+.IP "Description:"
+Each back end must be identified by the network name
+(server name) where it is located\&. For example: \f(CWserver
+10\&.1\&.1\&.23\fP, or \f(CWserver web\&.mydomain\&.org\fP\&. A TCP port specifier
+can follow the server name, as in \f(CWserver
+web\&.mydomain\&.org:80\fP\&. \fBNote that\fP resolved host names are
+cached by Crossroads; there is no performance advantage in
+specifying decimal addresses\&. (The DNS cache timeout can be
+controlled using the invocation flag \f(CW-d\fP\&.)
+.IP "Syntax:"
+.IP o
+\f(CWserver\fP \fIservername\fP, where \fIservername\fP is a
+network name or IP address\&. In this case a separate \f(CWport\fP
+statement must be used to define the TCP port;
+.IP o
+\f(CWserver\fP \fIservername:port\fP
+.IP "Default:"
+There is no default\&. This is a required setting\&.
+
+.PP
+\fBverbosity - Controlling verbosity at the back end level\fP
+.IP "Description:"
+Similar to \f(CWservice\fP specifications, a
+\f(CWbackend\fP can have its own verbosity (\f(CWon\fP or \f(CWoff\fP)\&. When
+\f(CWon\fP, traffic to and fro this back end is reported\&.
+.IP "Syntax:"
+.IP o
+\f(CWverbosity\fP \fIsetting\fP, or
+.IP o
+\f(CWverbose\fP \fIsetting\fP, where \fIsetting\fP is \f(CWtrue\fP,
+\f(CWyes\fP or \f(CWon\fP, or \f(CWfalse\fP, \f(CWno\fP, \f(CWoff\fP to turn it
+off\&.
+.IP "Default:"
+\f(CWoff\fP
+
+.PP
+\fBretries - Specifying allowed failures\fP
+.IP "Description:"
+Back ends that are \&'flaky\&' or on a less reliable network can be
+marked as unavailable after not just one failure, but after
+e\&.g\&. three\&. You can use this configuration if you suspect that
+spurious errors cause otherwise \&'good\&' back ends to be marked as
+unavailable, while they in fact still could be used\&.
+.IP "Syntax:"
+\f(CWretries\fP \fInumber\fP; where \fInumber\fP is the threshold of bad
+connections\&. Once exceeded, Crossroads will mark a back end as
+unavailable\&.
+.IP "Default:"
+1; a back end is assumed to be unavailable after the first bad
+connection\&.
+
+.PP
+\fBweight - When a back end is more equal than others\fP
+.IP "Description:"
+To influence how backends are selected, a backend can specify its
+\&'weight\&' in the process\&. The higher the weight, the less likely a
+back end will be chosen\&. The default is 1\&.
+.IP
+The weighing mechanism only applies to the dispatch modes
+\f(CWrandom\fP, \f(CWbyconnections\fP, \f(CWbysize\fP and \f(CWbyduration\fP\&.
+The weight is in fact a penalty factor\&. E\&.g\&., if backend A has
+\f(CWweight 2\fP and backend B has \f(CWweight 1\fP, then backend B will
+be selected all the time, until its usage parameter is twice as
+large as the parameter of A\&. Think of it as a \&'sluggishness\&'
+statement\&.
+.IP "Syntax:"
+\f(CWweight\fP \fInumber\fP; the higher the number, the more \&'sluggish\&'
+a back end is
+.IP "Default:"
+1; all back ends have equal weight\&.
+
+.PP
+\fBdecay - Levelling out activity of a back end\fP
+.IP "Description:"
+To make sure that a \&'spike\&' of activity doesn\&'t
+influence the perceived load of a back end forever, you may
+specify a certain decay\&. E\&.g, the statement \f(CWdecay 10\fP makes
+sure that the load that crossroads computes for this back end (be
+it in seconds or in bytes) is decreased by 10% each time that
+\fBan other\fP back end is hit\&. Decays are not applied to the count
+of concurrent connections\&.
+.IP
+This means that when a given back end is hit, then its usage data
+of the transferred bytes and the connection duration are updated
+using the actual number of bytes and actual duration\&. However,
+when a different back end is hit, then the usage data are
+decreased by the specified decay\&.
+.IP "Syntax:"
+\f(CWdecay\fP \fInumber\fP, where \fInumber\fP is a percentage that
+decreases the back end usage data when other back ends are
+hit\&.
+.IP "Default:"
+0, meaning that no decay is applied to usage statistics\&.
+
+.PP
+\fBonstart, onend, onfail - Action Hooks\fP
+.IP "Description:"
+The three directives \f(CWonstart\fP, \f(CWonend\fP and \f(CWonfail\fP can be
+specified to start system commands (external programs) when a
+connection to a back end starts, fails or ends:
+.IP o
+\f(CWonstart\fP commands will be run when Crossroads
+successfully connects to a back end, and starts servicing;
+.IP o
+\f(CWonend\fP commands will be run when a (previously
+established) connection stops;
+.IP o
+\f(CWonfail\fP commands will be run when Crossroads tries to
+contact a back end to serve a client, but the back end can\&'t
+be reached\&.
+.IP
+The format is always \f(CWon\fP\fItype\fP \fIcommand\fP\&. The \fIcommand\fP
+is an external program, optionally followed by arguments\&. The
+command is expanded according to the following table:
+.IP
+.IP o
+\f(CW%a\fP is the availability of the current back end, when
+a current back end is established;
+.IP o
+\f(CW%1a\fP is the availability of the first back end (0 when
+unavailable, 1 if available); \f(CW%2a\fP is the availability of
+the second back end, and so on;
+.IP o
+\f(CW%b\fP is the name of the current back end, when one is
+established;
+.IP o
+\f(CW%1b\fP is the name of the first back end, \f(CW%2b\fP of the
+second back end, and so on;
+.IP o
+\f(CW%e\fP is the count of seconds since start of epoch
+(January 1st 1970 GMT);
+.IP o
+\f(CW%r\fP is the IP address of the client that requests a
+connection and for whom the external dispatcher should compute
+a back end;
+.IP o
+\f(CW%s\fP is the name of the current service that the client
+connected to;
+.IP o
+\f(CW%t\fP is the current local time in ASCII format, in
+\fIYYYY-MM-DD/hhh:mm:ss\fP;
+.IP o
+\f(CW%T\fP is the current GMT time in ASCIII format;
+.IP o
+\f(CW%v\fP is the Crossroads version;
+.IP o
+Any other chararacter following a \f(CW%\fP sign is taken
+literally; e\&.g\&. \f(CW%z\fP is just a z\&.
+.IP
+.IP "Syntax:"
+.IP o
+\f(CWonstart\fP \fIcommandline\fP
+.IP o
+\f(CWonend\fP \fIcommandline\fP
+.IP o
+\f(CWonfail\fP \fIcommandline\fP
+.IP o
+\f(CWonsuccess\fP \fIcommandline\fP
+.IP "Default:"
+There is no default\&. Normally no external programs are run upon
+connection, success or failure of a back end\&.
+
+.PP
+\fBtrafficlog and throughputlog - Debugging and Performance Aids\fP
+.IP "Description:"
+Two directives are available
+to log network traffic to files\&. They are \f(CWtrafficlog\fP and
+\f(CWthroughputlog\fP\&.
+.IP
+The \f(CWtrafficlog\fP statement causes all traffic to be logged in
+hexadecimal format\&. Each line is prefixed by \f(CWB\fP or \f(CWC\fP,
+depending on whether the information was received from the back
+end or from the client\&.
+.IP
+The \f(CWthroughputlog\fP statement writes shorthand transmissions to
+its log, accompanied by timings\&.
+.IP "Syntax:"
+.IP o
+\f(CWtrafficlog\fP \fIfilename\fP
+.IP o
+\f(CWthroughputlog\fP \fIfilename\fP
+.IP "Default:"
+none
+
+.PP
+\fBstickycookie - Back end selection with an HTTP cookie\fP
+.IP "Description:"
+The directive \f(CWstickycookie\fP \fIvalue\fP
+causes Crossroads to unpack clients\&' requests, to check for
+\fIvalue\fP in the cookies\&. When found, the message is routed to the
+back end having the appropriate \f(CWstickycookie\fP directive\&.
+.IP
+E\&.g\&., consider the following configuration:
+.IP
+.nf
+service \&.\&.\&. {
+ \&.\&.\&.
+ backend one {
+ \&.\&.\&.
+ stickycookie "BalancerID=first";
+ }
+ backend two {
+ \&.\&.\&.
+ stickycookie "BalancerID=second";
+ }
+}
+.fi
+
+.IP
+When clients\&' messages contain cookies named \f(CWBalancerID\fP with
+the value \f(CWfirst\fP, then such messages are routed to backend
+\f(CWone\fP\&. When the value is \f(CWsecond\fP then they are routed to the
+backend \f(CWtwo\fP\&.
+.IP
+There are basically to provide such cookies to a browser\&. First, a
+back end can insert such a cookie into the HTTP response\&. E\&.g\&.,
+the webserver of back end \f(CWone\fP might insert a cookie named
+\f(CWBalancerID\fP, having value \f(CWfirst\fP\&.
+Second, Crossroads can insert such cookies using a carefully
+crafted directive \f(CWaddclientheader\fP\&.
+.IP "Syntax:"
+\f(CWstickycookie\fP \fIcookievalue\fP
+.IP "Default:"
+There is no default\&.
+
+.PP
+\fBHTTP Header Modification Directives\fP
+.IP "Description:"
+Crossroads understands the following
+header modification directives: \f(CWaddclientheader\fP,
+\f(CWappendclientheader\fP, \f(CWsetclientheader\fP, \f(CWaddserverheader\fP,
+\f(CWappendserverheader\fP, \f(CWsetserverheader\fP\&.
+.IP
+The directive names always consist of
+\fIAction\fP\fIDestination\fP\f(CWheader\fP, where:
+.IP
+.IP o
+The action is \f(CWadd\fP, \f(CWappend\fP or \f(CWinsert\fP\&.
+.IP
+.IP o
+Action \f(CWadd\fP adds a header, even when headers with
+the same name already are present in an HTTP
+message\&. Adding headers is useful for e\&.g\&. \f(CWSet-Cookie\fP
+headers; a message may contain several of such headers\&.
+.IP
+.IP o
+Action \f(CWappend\fP adds a header if it isn\&'t present
+yet in an HTTP message\&. If such a header is already
+present, then the value is appended to the pre-existing
+header\&. This is useful for e\&.g\&. \f(CWVia\fP headers\&. Imagine
+an HTTP message with a header \f(CWVia: someproxy\fP\&. Then the
+directive \f(CWappendclientheader "Via: crossroads"\fP will
+rewrite the header to \f(CWVia: someproxy; crossroads\fP\&.
+.IP
+.IP o
+Action \f(CWset\fP overwrites headers with the same
+name; or adds a new header if no pre-existing is found\&.
+This is useful for e\&.g\&. \f(CWHost\fP headers\&.
+.IP
+.IP o
+The destination is one of \f(CWclient\fP or \f(CWserver\fP\&. When
+the destination is \f(CWserver\fP, then Crossroads will apply such
+directives to HTTP messages that originate from the browser
+and are being forwarded to back ends\&. When the destination is
+\f(CWclient\fP, then Crossroads will apply such directives to
+backend responses that are shuttled to the browser\&.
+.IP
+The format of the directives is e\&.g\&. \f(CWaddclientheader
+"X-Processed-By: Crossroads"\fP\&. The directives expect one
+argument; a string, consisting of a header name, a colon, and a
+header value\&. As usual, the directive must end with a semicolon\&.
+.IP
+The header value may contain one of the following formatting
+directives:
+.IP
+.IP o
+\f(CW%a\fP is the availability of the current back end, when
+a current back end is established;
+.IP o
+\f(CW%1a\fP is the availability of the first back end (0 when
+unavailable, 1 if available); \f(CW%2a\fP is the availability of
+the second back end, and so on;
+.IP o
+\f(CW%b\fP is the name of the current back end, when one is
+established;
+.IP o
+\f(CW%1b\fP is the name of the first back end, \f(CW%2b\fP of the
+second back end, and so on;
+.IP o
+\f(CW%e\fP is the count of seconds since start of epoch
+(January 1st 1970 GMT);
+.IP o
+\f(CW%r\fP is the IP address of the client that requests a
+connection and for whom the external dispatcher should compute
+a back end;
+.IP o
+\f(CW%s\fP is the name of the current service that the client
+connected to;
+.IP o
+\f(CW%t\fP is the current local time in ASCII format, in
+\fIYYYY-MM-DD/hhh:mm:ss\fP;
+.IP o
+\f(CW%T\fP is the current GMT time in ASCIII format;
+.IP o
+\f(CW%v\fP is the Crossroads version;
+.IP o
+Any other chararacter following a \f(CW%\fP sign is taken
+literally; e\&.g\&. \f(CW%z\fP is just a z\&.
+.IP
+The following examples show common uses of header modifications\&.
+.IP
+.IP "Enforcing session stickiness:"
+By combining
+\f(CWstickycookie\fP and \f(CWaddclientheader\fP, HTTP session
+stickiness is enforced\&. Consider the following configuration:
+.IP
+.nf
+service \&.\&.\&. {
+ \&.\&.\&.
+ backend one {
+ \&.\&.\&.
+ addclientheader "Set-Cookie: BalancerID=first; path=/";
+ stickycookie "BalancerID=first";
+ }
+ backend two {
+ \&.\&.\&.
+ addclientheader "Set-Cookie: BalancerID=second; path=/";
+ stickycookie "BalancerID=second";
+ }
+}
+.fi
+
+.IP
+The first request of an HTTP session is balanced to either
+backend \f(CWone\fP or \f(CWtwo\fP\&. The server response is enriched
+using \f(CWaddclientheader\fP with an appropriate cookie\&. A
+subsequent request from the same browser now has that cookie
+in place; and is therefore sent to the same back end where the
+its predecessors went\&.
+.IP
+.IP "Hiding the server software version:"
+Many servers
+(e\&.g\&. Apache) advertize their version, as in \f(CWServer: Apache
+1\&.27\fP\&. This potentially provides information to attackers\&. The
+following configuration hides such information:
+.IP
+.nf
+service \&.\&.\&. {
+ \&.\&.\&.
+ backend one {
+ \&.\&.\&.
+ setclientheader "Server: WWW-Server";
+ }
+}
+.fi
+
+.IP
+.IP "Informing the server of the clients\&' IP address:"
+Since
+Crossroads sits \&'in the middle\&' between a client and a back
+end, the back end perceives Crossroads as its client\&. The
+following sends the true clients\&' IP address to the server, in
+a header \f(CWX-Real-IP\fP:
+.IP
+.nf
+service \&.\&.\&. {
+ \&.\&.\&.
+ backend one {
+ \&.\&.\&.
+ setserverheader "X-Real-IP: %r";
+ }
+}
+.fi
+
+.IP
+.IP "Keep-Alive Downgrading:"
+The directives
+\f(CWsetclientheader\fP and \f(CWsetserverheader\fP also play a key
+role in downgrading Keep-Alive connections to
+\&'single-shot\&'\&. E\&.g\&., the following configuration makes sure
+that no Keep-Alive connections occur\&.
+.IP
+.nf
+service \&.\&.\&. {
+ \&.\&.\&.
+ backend one {
+ \&.\&.\&.
+ setserverheader "Connection: close";
+ setclientheader "Connection: close";
+ }
+}
+.fi
+.IP "Syntax:"
+.IP o
+\f(CWaddclientheader\fP \fIHeadername: headervalue\fP to add a
+header in the traffic towards the client, even when another
+header \fIHeadername\fP exists;
+.IP o
+\f(CWappendclientheader\fP \fIHeadername: headervalue\fP to
+append \fIheadervalue\fP to an existing header \fIHeadername\fP
+in the traffic towards the client,
+or to add the whole header alltogether;
+.IP o
+\f(CWsetclientheader\fP \fIHeadername: headervalue\fP to
+overwrite an existing header in the traffic towards the
+client, or to add such a header;
+.IP o
+\f(CWaddserverheader\fP \fIHeadername: headervalue\fP to add a
+header in the traffic towards the server, even when another
+header \fIHeadername\fP exists;
+.IP o
+\f(CWappendserverheader\fP \fIHeadername: headervalue\fP to
+append \fIheadervalue\fP to an existing header \fIHeadername\fP
+in the traffic towards the server,
+or to add the whole header alltogether;
+.IP o
+\f(CWsetserverheader\fP \fIHeadername: headervalue\fP to
+overwrite an existing header in the traffic towards the
+server, or to add such a header\&.
+.IP "Default:"
+There is no default\&.
+
+.PP
+.SH "SEE ALSO"
+.IP o
+crossroads (1)
+.IP o
+The full Crossroads documentation, in pdf and html
+format, distributed with the sources\&.
+.PP
+.SH "AUTHOR"
+
+ Crossroads is written by Karel Kubat and is maintained by
+ Karel Kubat (karel@kubat\&.nl)\&.
+\ No newline at end of file
diff --git a/doc/crossroads.html b/doc/crossroads.html
@@ -1,15 +1,16 @@
-<a name="defs.yo"></a><html><head>
-<title>Crossroads 1.42</title>
+<a name="../crossroads-defs"></a><a name="defs"></a><html><head>
+<title>Crossroads 1.44</title>
<link rel="stylesheet" type="text/css" href="http://www.e-tunity.com/css/yodl.css">
<link rel="stylesheet" type="text/css" href="http://www.e-tunity.com/css/yodl.css">
<link rev="made" href="mailto:info@e-tunity.com">
</head>
<body>
<hr>
-<h1>Crossroads 1.42</h1>
-<h2>Karel Kubat</h2>
+<h1>Crossroads 1.44</h1>
+<h2>Karel Kubat <br>
+ Maintained by Karel Kubat (karel@kubat.nl)</h2>
-<h2>e-tunity</h2><h2>2005, 2006, ff.</h2>
+<h2>e-tunity</h2><h2>2005-2007, ff.</h2>
<blockquote><em>Crossroads is a load balance and fail over utility for TCP
based services. It is a daemon program running in user
@@ -31,119 +32,125 @@
<dt><a href="#l3">1.2: Reporting bugs</a></dt>
<dt><a href="#l4">1.3: Copyright and Disclaimer</a></dt>
<dt><a href="#l5">1.4: Terminology</a></dt>
-<dt><a href="#l6">1.5: Porting issues for pre-1.21 installations</a></dt>
-<dt><a href="#l7">1.6: Porting issues for pre-0.26 installations</a></dt>
-<dt><a href="#l8">1.7: Porting issues for pre-1.08 installations</a></dt>
+<dt><a href="#l6">1.5: Porting Issues</a></dt>
+<dl>
+<dt><a href="#l7">1.5.1: Porting issues for pre-1.43 installations</a></dt>
+<dt><a href="#l8">1.5.2: Porting issues for pre-1.21 installations</a></dt>
+<dt><a href="#l9">1.5.3: Porting issues for pre-0.26 installations</a></dt>
+<dt><a href="#l10">1.5.4: Porting issues for pre-1.08 installations</a></dt>
+</dl>
</dl>
-<dt><h3><a href="#l9">2: Installation for the impatient</a></h3></dt>
-<dt><h3><a href="#l10">3: Using Crossroads</a></h3></dt>
+<dt><h3><a href="#l11">2: Installation for the impatient</a></h3></dt>
+<dt><h3><a href="#l12">3: Using Crossroads</a></h3></dt>
<dl>
-<dt><a href="#l11">3.1: General Commandline Syntax</a></dt>
-<dt><a href="#l12">3.2: Status Reporting</a></dt>
-<dt><a href="#l13">3.3: Logging-related options</a></dt>
-<dt><a href="#l14">3.4: Reloading Configurations</a></dt>
+<dt><a href="#l13">3.1: General Commandline Syntax</a></dt>
+<dt><a href="#l14">3.2: Status Reporting</a></dt>
+<dt><a href="#l15">3.3: Logging-related options</a></dt>
+<dt><a href="#l16">3.4: Reloading Configurations</a></dt>
</dl>
-<dt><h3><a href="#l15">4: The configuration</a></h3></dt>
+<dt><h3><a href="#l17">4: The configuration</a></h3></dt>
<dl>
-<dt><a href="#l16">4.1: General language elements</a></dt>
+<dt><a href="#l18">4.1: General language elements</a></dt>
<dl>
-<dt><a href="#l17">4.1.1: Empty lines and comments</a></dt>
-<dt><a href="#l18">4.1.2: Keywords, numbers, identifiers, generic strings</a></dt>
+<dt><a href="#l19">4.1.1: Empty lines and comments</a></dt>
+<dt><a href="#l20">4.1.2: Preprocessor directives</a></dt>
+<dt><a href="#l21">4.1.3: Keywords, numbers, identifiers, generic strings</a></dt>
</dl>
-<dt><a href="#l19">4.2: Service definitions</a></dt>
+<dt><a href="#l22">4.2: Service definitions</a></dt>
<dl>
-<dt><a href="#l20">4.2.1: type - Defining the service type</a></dt>
-<dt><a href="#l21">4.2.2: port - Specifying the listen port</a></dt>
-<dt><a href="#l22">4.2.3: bindto - Binding to a specific IP address</a></dt>
-<dt><a href="#l23">4.2.4: verbosity - Controlling debug output</a></dt>
-<dt><a href="#l24">4.2.5: dispatchmode - How are back ends selected</a></dt>
-<dt><a href="#l25">4.2.6: revivinginterval - Back end wakeup calls</a></dt>
-<dt><a href="#l26">4.2.7: maxconnections - Limiting concurrent clients at service level</a></dt>
-<dt><a href="#l27">4.2.8: backlog - The TCP Back Log size</a></dt>
-<dt><a href="#l28">4.2.9: shmkey - Shared Memory Access</a></dt>
-<dt><a href="#l29">4.2.10: allow* and deny* - Allowing or denying connections</a></dt>
-<dt><a href="#l30">4.2.11: useraccount - Limiting the effective ID of external processes</a></dt>
+<dt><a href="#l23">4.2.1: type - Defining the service type</a></dt>
+<dt><a href="#l24">4.2.2: port - Specifying the listen port</a></dt>
+<dt><a href="#l25">4.2.3: bindto - Binding to a specific IP address</a></dt>
+<dt><a href="#l26">4.2.4: verbosity - Controlling debug output</a></dt>
+<dt><a href="#l27">4.2.5: dispatchmode - How are back ends selected</a></dt>
+<dt><a href="#l28">4.2.6: revivinginterval - Back end wakeup calls</a></dt>
+<dt><a href="#l29">4.2.7: maxconnections - Limiting concurrent clients at service level</a></dt>
+<dt><a href="#l30">4.2.8: backlog - The TCP Back Log size</a></dt>
+<dt><a href="#l31">4.2.9: shmkey - Shared Memory Access</a></dt>
+<dt><a href="#l32">4.2.10: allow* and deny* - Allowing or denying connections</a></dt>
+<dt><a href="#l33">4.2.11: useraccount - Limiting the effective ID of external processes</a></dt>
</dl>
-<dt><a href="#l31">4.3: Backend definitions</a></dt>
+<dt><a href="#l34">4.3: Backend definitions</a></dt>
<dl>
-<dt><a href="#l32">4.3.1: server - Specifying the back end address</a></dt>
-<dt><a href="#l33">4.3.2: verbosity - Controlling verbosity at the back end level</a></dt>
-<dt><a href="#l34">4.3.3: retries - Specifying allowed failures</a></dt>
-<dt><a href="#l35">4.3.4: weight - When a back end is more equal than others</a></dt>
-<dt><a href="#l36">4.3.5: decay - Levelling out activity of a back end</a></dt>
-<dt><a href="#l37">4.3.6: onstart, onend, onfail - Action Hooks</a></dt>
-<dt><a href="#l38">4.3.7: trafficlog and throughputlog - Debugging and Performance Aids</a></dt>
-<dt><a href="#l39">4.3.8: stickycookie - Back end selection with an HTTP cookie</a></dt>
-<dt><a href="#l40">4.3.9: HTTP Header Modification Directives</a></dt>
+<dt><a href="#l35">4.3.1: server - Specifying the back end address</a></dt>
+<dt><a href="#l36">4.3.2: verbosity - Controlling verbosity at the back end level</a></dt>
+<dt><a href="#l37">4.3.3: retries - Specifying allowed failures</a></dt>
+<dt><a href="#l38">4.3.4: weight - When a back end is more equal than others</a></dt>
+<dt><a href="#l39">4.3.5: decay - Levelling out activity of a back end</a></dt>
+<dt><a href="#l40">4.3.6: onstart, onend, onfail - Action Hooks</a></dt>
+<dt><a href="#l41">4.3.7: trafficlog and throughputlog - Debugging and Performance Aids</a></dt>
+<dt><a href="#l42">4.3.8: stickycookie - Back end selection with an HTTP cookie</a></dt>
+<dt><a href="#l43">4.3.9: HTTP Header Modification Directives</a></dt>
</dl>
</dl>
-<dt><h3><a href="#l41">5: Tips, Tricks and Random Remarks</a></h3></dt>
+<dt><h3><a href="#l44">5: Tips, Tricks and Random Remarks</a></h3></dt>
<dl>
-<dt><a href="#l42">5.1: How back ends are selected in load balancing</a></dt>
+<dt><a href="#l45">5.1: How back ends are selected in load balancing</a></dt>
<dl>
-<dt><a href="#l43">5.1.1: Bysize, byduration or byconnections?</a></dt>
-<dt><a href="#l44">5.1.2: Averaging size and duration</a></dt>
-<dt><a href="#l45">5.1.3: Specifying decays</a></dt>
-<dt><a href="#l46">5.1.4: Adjusting the weights</a></dt>
+<dt><a href="#l46">5.1.1: Bysize, byduration or byconnections?</a></dt>
+<dt><a href="#l47">5.1.2: Averaging size and duration</a></dt>
+<dt><a href="#l48">5.1.3: Specifying decays</a></dt>
+<dt><a href="#l49">5.1.4: Adjusting the weights</a></dt>
</dl>
-<dt><a href="#l47">5.2: Throttling the number of concurrent connections</a></dt>
-<dt><a href="#l48">5.3: Using an external program to dispatch</a></dt>
+<dt><a href="#l50">5.2: Throttling the number of concurrent connections</a></dt>
+<dt><a href="#l51">5.3: Using an external program to dispatch</a></dt>
<dl>
-<dt><a href="#l49">5.3.1: Configuring the external handler</a></dt>
-<dt><a href="#l50">5.3.2: Writing the external handler</a></dt>
-<dt><a href="#l51">5.3.3: Examples of external handlers</a></dt>
+<dt><a href="#l52">5.3.1: Configuring the external handler</a></dt>
+<dt><a href="#l53">5.3.2: Writing the external handler</a></dt>
+<dt><a href="#l54">5.3.3: Examples of external handlers</a></dt>
</dl>
-<dt><a href="#l52">5.4: TCP Session Stickiness</a></dt>
-<dt><a href="#l53">5.5: HTTP Session Stickiness</a></dt>
+<dt><a href="#l55">5.4: TCP Session Stickiness</a></dt>
+<dt><a href="#l56">5.5: HTTP Session Stickiness</a></dt>
<dl>
-<dt><a href="#l54">5.5.1: Don't use stickiness!</a></dt>
-<dt><a href="#l55">5.5.2: But if you must..</a></dt>
+<dt><a href="#l57">5.5.1: Don't use stickiness!</a></dt>
+<dt><a href="#l58">5.5.2: But if you must..</a></dt>
</dl>
-<dt><a href="#l56">5.6: Passing the client's IP address</a></dt>
+<dt><a href="#l59">5.6: Passing the client's IP address</a></dt>
<dl>
-<dt><a href="#l57">5.6.1: Sample Crossroads configuration</a></dt>
-<dt><a href="#l58">5.6.2: Sample Apache configuration</a></dt>
+<dt><a href="#l60">5.6.1: Sample Crossroads configuration</a></dt>
+<dt><a href="#l61">5.6.2: Sample Apache configuration</a></dt>
</dl>
-<dt><a href="#l59">5.7: Debugging network traffic</a></dt>
-<dt><a href="#l60">5.8: IP filtering: Limiting Access by Client IP Address</a></dt>
+<dt><a href="#l62">5.7: Debugging network traffic</a></dt>
+<dt><a href="#l63">5.8: IP filtering: Limiting Access by Client IP Address</a></dt>
<dl>
-<dt><a href="#l61">5.8.1: General Examples</a></dt>
-<dt><a href="#l62">5.8.2: Using External Files</a></dt>
-<dt><a href="#l63">5.8.3: Mixing Directives</a></dt>
+<dt><a href="#l64">5.8.1: General Examples</a></dt>
+<dt><a href="#l65">5.8.2: Using External Files</a></dt>
+<dt><a href="#l66">5.8.3: Mixing Directives</a></dt>
</dl>
-<dt><a href="#l64">5.9: Configuration examples</a></dt>
+<dt><a href="#l67">5.9: Configuration examples</a></dt>
<dl>
-<dt><a href="#l65">5.9.1: A load balancer for three webserver back ends</a></dt>
-<dt><a href="#l66">5.9.2: An HTTP forwarder when travelling</a></dt>
-<dt><a href="#l67">5.9.3: SSH login with enforced idle logout</a></dt>
+<dt><a href="#l68">5.9.1: A load balancer for three webserver back ends</a></dt>
+<dt><a href="#l69">5.9.2: An HTTP forwarder when travelling</a></dt>
+<dt><a href="#l70">5.9.3: SSH login with enforced idle logout</a></dt>
</dl>
-<dt><a href="#l68">5.10: Linux and ip_conntrack_max</a></dt>
-<dt><a href="#l69">5.11: Marking back ends as bad after more than one try</a></dt>
-<dt><a href="#l70">5.12: Scripting Crossroads' back end availability</a></dt>
-<dt><a href="#l71">5.13: Rendering Crossroads' status in a web page</a></dt>
+<dt><a href="#l71">5.10: Linux and ip_conntrack_max</a></dt>
+<dt><a href="#l72">5.11: Marking back ends as bad after more than one try</a></dt>
+<dt><a href="#l73">5.12: Scripting Crossroads' back end availability</a></dt>
+<dt><a href="#l74">5.13: Rendering Crossroads' status in a web page</a></dt>
+<dt><a href="#l75">5.14: Crossroads and DNS caching</a></dt>
</dl>
-<dt><h3><a href="#l72">6: Benchmarking</a></h3></dt>
+<dt><h3><a href="#l76">6: Benchmarking</a></h3></dt>
<dl>
-<dt><a href="#l73">6.1: Benchmark 1: Accessing a proxy via crossroads or directly</a></dt>
+<dt><a href="#l77">6.1: Benchmark 1: Accessing a proxy via crossroads or directly</a></dt>
<dl>
-<dt><a href="#l74">6.1.1: Results</a></dt>
-<dt><a href="#l75">6.1.2: Discussion</a></dt>
+<dt><a href="#l78">6.1.1: Results</a></dt>
+<dt><a href="#l79">6.1.2: Discussion</a></dt>
</dl>
-<dt><a href="#l76">6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</a></dt>
+<dt><a href="#l80">6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</a></dt>
<dl>
-<dt><a href="#l77">6.2.1: Environment</a></dt>
-<dt><a href="#l78">6.2.2: Tests and results</a></dt>
+<dt><a href="#l81">6.2.1: Environment</a></dt>
+<dt><a href="#l82">6.2.2: Tests and results</a></dt>
</dl>
</dl>
-<dt><h3><a href="#l79">7: Compiling and Installing</a></h3></dt>
+<dt><h3><a href="#l83">7: Compiling and Installing</a></h3></dt>
<dl>
-<dt><a href="#l80">7.1: Prerequisites</a></dt>
-<dt><a href="#l81">7.2: Compiling and installing</a></dt>
-<dt><a href="#l82">7.3: Configuring crossroads</a></dt>
-<dt><a href="#l83">7.4: A boot script</a></dt>
+<dt><a href="#l84">7.1: Prerequisites</a></dt>
+<dt><a href="#l85">7.2: Compiling and installing</a></dt>
+<dt><a href="#l86">7.3: Configuring crossroads</a></dt>
+<dt><a href="#l87">7.4: A boot script</a></dt>
<dl>
-<dt><a href="#l84">7.4.1: SysV Style Startup</a></dt>
-<dt><a href="#l85">7.4.2: BSD Style Startup</a></dt>
+<dt><a href="#l88">7.4.1: SysV Style Startup</a></dt>
+<dt><a href="#l89">7.4.2: BSD Style Startup</a></dt>
</dl>
<p><hr><p>
@@ -192,8 +199,7 @@ As quick reference, here are some important URL's for Crossroads:
<p>
<li> <a href="svn://svn.e-tunity.com/crossroads">svn://svn.e-tunity.com/crossroads</a> is the SVN
repository; anonymous reading (fetching) is allowed. In order
- to commit changes, <a href="mailto:karel@e-tunity.com">mail me</a> for
- credentials.</ul>
+ to commit changes, mail the author or maintainer for credentials.</ul>
<p>
<a name="l3"></a>
<h3>1.2: Reporting bugs</h3>
@@ -212,7 +218,7 @@ or bug reports, always include the following:
observed behavior.
<p>
<li> The Crossroads configuration (normally
- <code>/etc/crossroads.conf</code>)
+ /etc/crossroads.conf)
<p>
<li> The version of Crossroads and all compile-time settings,
obtained via <code>crossroads -C</code>.</ul>
@@ -331,7 +337,37 @@ using the terms here in a very strict sense.)
</dl>
<p>
<a name="l6"></a>
-<h3>1.5: Porting issues for pre-1.21 installations</h3>
+<h3>1.5: Porting Issues</h3>
+<p>
+This section lists some caveats when converting Crossroads
+configurations to new versions. Given the changes of the syntax of the
+configuration file of Crossroads, existing configuration files may
+need to be made suitable for new versions.
+<p>
+<a name="l7"></a>
+<strong>1.5.1: Porting issues for pre-1.43 installations</strong>
+<p>
+As of version 1.43, the shared memory key calculations are based
+ on a different algorithm. This key is e.g. necessary when starting
+ and stopping Crossroads; in both actions, the key must be computed
+ in the same way.
+<p>
+Therefore, when upgrading Crossroads, make sure that you stop a
+ running Crossroads daemon using the same binary that started
+ it. After this, install a new binary, and start the daemon using
+ the new binary.
+<p>
+(Incidentally, this is always a good idea, but especially so when
+ the 'old' binary is pre-1.43 and the 'new' one is post-1.43.)
+<p>
+Furthermore, shell-style comment is no longer supported as of
+ 1.43. The reason is that 1.43 introduces the hash mark as a
+ preprocessor token (in <code>#include</code>, <code>#define</code>). Therefore, if
+ your configuration files use shell-style comment, please convert
+ this to <strong>C</strong> or <strong>C++</strong> style.
+<p>
+<a name="l8"></a>
+<strong>1.5.2: Porting issues for pre-1.21 installations</strong>
<p>
As of version 1.21, the event-hook directives <code>onsuccess</code> and
<code>onfailure</code> no longer exists.
@@ -345,8 +381,8 @@ The commands that are run via <code>onstart</code>, <code>onend</code> or <code>
are subject to format expansion; e.g., <code>%1w</code> is expanded to the
weight of the first back end, etc.. See section <a href="crossroads.html#config">4</a> for details.
<p>
-<a name="l7"></a>
-<h3>1.6: Porting issues for pre-0.26 installations</h3>
+<a name="l9"></a>
+<strong>1.5.3: Porting issues for pre-0.26 installations</strong>
<p>
As of version 0.26 the syntax of the configuration file has
changed. In particular:
@@ -364,8 +400,8 @@ Therefore when converting configuration files to the new syntax,
<em>session</em> is used strictly in that sense -- and no longer for a
TCP connection.)
<p>
-<a name="l8"></a>
-<h3>1.7: Porting issues for pre-1.08 installations</h3>
+<a name="l10"></a>
+<strong>1.5.4: Porting issues for pre-1.08 installations</strong>
<p>
As of version 1.08, the following directives no longer are
supported:
@@ -385,7 +421,7 @@ As of version 1.08, the following directives no longer are
This incidentally also makes it possible to change the header
name (here: <code>XR-Real-IP</code>).</ul>
<p>
-<a name="l9"></a>
+<a name="l11"></a>
<h2>2: Installation for the impatient</h2>
<a name="impatient"></a>
For the impatient, here's the very-quick-but-very-superficial recipy
@@ -425,7 +461,7 @@ for getting crossroads up and running:
binary into <code>/usr/local/bin/</code>. If the compilation doesn't
work on your system, check <code>etc/Makefile.def</code> for hints.
<p>
-<li> Create a file <code>/etc/crossroads.conf</code>. In it state
+<li> Create a file /etc/crossroads.conf. In it state
something like:
<p>
<pre>
@@ -455,10 +491,10 @@ That's off course assuming that you want to balance HTTP on
status</code>.
</ul>
<p>
-<a name="l10"></a>
+<a name="l12"></a>
<h2>3: Using Crossroads</h2>
<a name="using"></a>Crossroads is started from the commandline, and highly depends on
-<code>/etc/crossroads.conf</code> (the default configuration file). It
+/etc/crossroads.conf (the default configuration file). It
supports a number of flags (e.g., to overrule the location of the
configuration file). The actual usage information is always obtained
by typing <code>crossroads</code> without any arguments. Crossroads then
@@ -469,7 +505,7 @@ second program called <code>crossroads-daemon</code>. This program is not meant
to be started from the command line; it is administered through the
front end <code>crossroads</code>.
<p>
-<a name="l11"></a>
+<a name="l13"></a>
<h3>3.1: General Commandline Syntax</h3>
<p>
This section shows the most basic usage. As said above, start
@@ -502,10 +538,10 @@ This section shows the most basic usage. As said above, start
<li> <code>crossroads sampleconf</code> shows a sample configuration on
screen. A good way of quicky viewing the configuration
file syntax, or of getting a start for your own
- configuration <code>/etc/crossroads.conf</code>.
+ configuration /etc/crossroads.conf.
</ul>
<p>
-<a name="l12"></a>
+<a name="l14"></a>
<h3>3.2: Status Reporting</h3>
<p>
The command <code>crossroads status</code> shows a verbose human-readable
@@ -537,9 +573,10 @@ follows:
<p>
The flag <code>-x</code> causes the overview to be presented as an XML
document. This can be handy if you want to further automate the
-control over Crossroads, or if you want to show the status via the web.
+control over Crossroads, or if you want to show the status via the
+web. (See section <a href="crossroads.html#xmlstatus">5.13</a> for more information.)
<p>
-<a name="l13"></a>
+<a name="l15"></a>
<h3>3.3: Logging-related options</h3>
<p>
Two 'flags' of Crossroads are specifically logging-related. This
@@ -582,7 +619,7 @@ That instructs <code>syslogd</code> to send <code>LOG_LOCAL7</code> requests to
<li> Finally, monitor <code>/var/log/crossroads.log</code> for Crossroads'
messages.</ul>
<p>
-<a name="l14"></a>
+<a name="l16"></a>
<h3>3.4: Reloading Configurations</h3>
<p>
Crossroads doesn't support the reloading of a configuration while
@@ -593,22 +630,24 @@ However, external lists of allowed or denied IP addresses can be
reloaded by sending a signal -1 (<code>SIGHUP</code>) to Crossroads. See
section <a href="crossroads.html#servicedef">4.2</a> for the details.
<p>
-<a name="l15"></a>
+
+
+<a name="l17"></a>
<h2>4: The configuration</h2>
<a name="config"></a>The configuration that crossroads uses is normally stored in the file
-<code>/etc/crossroads.conf</code>. This location can be overruled using the
+/etc/crossroads.conf. This location can be overruled using the
command line flag <code>-c</code>.
<p>
This section explains the syntax of the configuration file, and what
all settings do.
<p>
-<a name="l16"></a>
+<a name="l18"></a>
<h3>4.1: General language elements</h3>
<p>
This section describes the general elements of the crossroads
configuration language.
<p>
-<a name="l17"></a>
+<a name="l19"></a>
<strong>4.1.1: Empty lines and comments</strong>
<p>
Empty lines are of course allowed in the
@@ -617,8 +656,6 @@ configuration. Crossroads recognizes three formats of comment:
<ul>
<li> C-style, between <code>/*</code> and <code>*/</code>,
<li> C++-style, starting with <code>//</code> and ending with the end
- of the text line;
- <li> Shell-style, starting with <code>#</code> and ending with the end
of the text line.</ul>
<p>
Simply choose your favorite editor and use the comment that 'looks
@@ -626,8 +663,37 @@ best'. (I favor C or C++ comment. My favorite editor <em>emacs</em>
can be put in <code>cmode</code> and nicely highlight what's comment and what's
not. And as a bonus it will auto-indent the configuration!)
<p>
-<a name="l18"></a>
-<strong>4.1.2: Keywords, numbers, identifiers, generic strings</strong>
+<a name="l20"></a>
+<strong>4.1.2: Preprocessor directives</strong>
+<p>
+Similar to <strong>C</strong> or <strong>C++</strong>, the Crossroads grammar knows <code>#include</code>
+and <code>#define</code>. Both directives must start at the first column of the
+line (ie., the <code>#</code> sign must occur at the leftmost line
+position).
+<p>
+<ul>
+ <li> <code>#include</code> <code>"</code><em>filename</em><code>"</code> includes the stated file
+ name at the place of the statement.
+ <li> <code>#define</code> <em>SYMBOL</em> <em>DEFINITION</em> defines <em>SYMBOL</em>
+ as placeholder for <em>DEFINITION</em>.</ul>
+<p>
+For example, one may use the configuration:
+<p>
+<pre>
+#define SERVICEPORT 80
+service web {
+ port SERVICEPORT;
+ .
+ . /* More statements follow here */
+ .
+}
+</pre>
+
+<p>
+The <code>port</code> statement is then read as <code>port 80</code>.
+<p>
+<a name="l21"></a>
+<strong>4.1.3: Keywords, numbers, identifiers, generic strings</strong>
<p>
In a configuration file, statements are identified by <em>keywords</em>,
such as <code>service</code>, <code>verbosity</code>. These are reserved words.
@@ -661,7 +727,7 @@ Finally, an argument can be a 'boolean' value. Crossroads knows
<code>true</code>, <code>yes</code> and <code>on</code> all mean the same and can be used
interchangeably; as can the keywords <code>false</code>, <code>no</code> and <code>off</code>.
<p>
-<a name="l19"></a>
+<a name="l22"></a>
<h3>4.2: Service definitions</h3> <a name="servicedef"></a>
<p>
Service definitions are blocks in the configuration file that
@@ -685,7 +751,7 @@ identifying names differ. The following list shows possible
statements. Each statement must end with a semicolon, except for the
<code>backend</code> statement, which has is own block (more on this later).
<p>
-<a name="conf/type"></a><a name="l20"></a>
+<a name="conf/type"></a><a name="l23"></a>
<strong>4.2.1: type - Defining the service type</strong> <a name="conftype - Defining the service type"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The <code>type</code> statement defines how crossroads handles the stated
@@ -705,7 +771,7 @@ Unless you really need such special features, use the type <code>any</code> (the
<p><dt><strong>Default:</strong><dd> <code>any</code>
</dl>
<p>
-<a name="conf/port"></a><a name="l21"></a>
+<a name="conf/port"></a><a name="l24"></a>
<strong>4.2.2: port - Specifying the listen port</strong> <a name="confport - Specifying the listen port"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The <code>port</code> statement defines to which TCP port a service
@@ -715,7 +781,7 @@ Unless you really need such special features, use the type <code>any</code> (the
<p><dt><strong>Default:</strong><dd> There is no default. This is a required setting.
</dl>
<p>
-<a name="conf/bindto"></a><a name="l22"></a>
+<a name="conf/bindto"></a><a name="l25"></a>
<strong>4.2.3: bindto - Binding to a specific IP address</strong> <a name="confbindto - Binding to a specific IP address"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The <code>bindto</code> statement is used in situations where crossroads
@@ -729,7 +795,7 @@ Unless you really need such special features, use the type <code>any</code> (the
<p><dt><strong>Default:</strong><dd> <code>any</code>
</dl>
<p>
-<a name="conf/verbose"></a><a name="l23"></a>
+<a name="conf/verbose"></a><a name="l26"></a>
<strong>4.2.4: verbosity - Controlling debug output</strong> <a name="confverbosity - Controlling debug output"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Verbosity statements come in two forms: <code>verbosity on</code> or
@@ -746,7 +812,7 @@ Unless you really need such special features, use the type <code>any</code> (the
<p><dt><strong>Default:</strong><dd> <code>off</code>
</dl>
<p>
-<a name="conf/dispatchmode"></a><a name="l24"></a>
+<a name="conf/dispatchmode"></a><a name="l27"></a>
<strong>4.2.5: dispatchmode - How are back ends selected</strong> <a name="confdispatchmode - How are back ends selected"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The dispatch mode controls how crossroads selects a back end from
@@ -795,10 +861,10 @@ The modifier <code>over</code> <em>connections</em> is optional. (The square
is taken, and so on.
<p>
<li> <code>dispatchmode byclientip</code>: The client's IP address is
- 'hashed' into a number, which is used to pick a back end. The
- same client IP address will therefore always be dispatched to
- the same back end. When the back end of choice is down,
- <code>dispatchmode byconnections</code> is used.
+ 'hashed' into a number, which is used to pick a back end. The
+ same client IP address will therefore always be dispatched to
+ the same back end. When the back end of choice is down,
+ <code>dispatchmode byconnections</code> is used.
<p>
<li> <code>dispatchmode externalhandler</code> <em>program arguments</em>:
This is a special mode, where an external program is delegated
@@ -833,7 +899,7 @@ Your 'right' dispatch mode will depend on the type of service. Given
<p><dt><strong>Default:</strong><dd> <code>roundrobin</code>
</dl>
<p>
-<a name="conf/revivinginterval"></a><a name="l25"></a>
+<a name="conf/revivinginterval"></a><a name="l28"></a>
<strong>4.2.6: revivinginterval - Back end wakeup calls</strong> <a name="confrevivinginterval - Back end wakeup calls"></a>
<dl>
<p><dt><strong>Description:</strong><dd> A reviving interval definition is needed when crossroads
@@ -855,7 +921,7 @@ An example of the definition is <code>revivinginterval 10</code>. When this
<p><dt><strong>Default:</strong><dd> 0 (no wakeup calls)
</dl>
<p>
-<a name="conf/maxconnections"></a><a name="l26"></a>
+<a name="conf/maxconnections"></a><a name="l29"></a>
<strong>4.2.7: maxconnections - Limiting concurrent clients at service level</strong> <a name="confmaxconnections - Limiting concurrent clients at service level"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The maximum number of connections is specified using
@@ -871,7 +937,7 @@ An example of the definition is <code>revivinginterval 10</code>. When this
<p><dt><strong>Default:</strong><dd> 0, meaning that all connections will be accepted.
</dl>
<p>
-<a name="conf/backlog"></a><a name="l27"></a>
+<a name="conf/backlog"></a><a name="l30"></a>
<strong>4.2.8: backlog - The TCP Back Log size</strong> <a name="confbacklog - The TCP Back Log size"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The TCP back log size is a number that controls how many
@@ -887,7 +953,7 @@ An example of the definition is <code>revivinginterval 10</code>. When this
value for socket back log size.
</dl>
<p>
-<a name="conf/shmkey"></a><a name="l28"></a>
+<a name="conf/shmkey"></a><a name="l31"></a>
<strong>4.2.9: shmkey - Shared Memory Access</strong> <a name="confshmkey - Shared Memory Access"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Different Crossroads
@@ -897,18 +963,17 @@ An example of the definition is <code>revivinginterval 10</code>. When this
memory, which is reserved using a key.
<p>
Normally crossroads will supply a shared memory key, based on the
- service port and bitwise or-ed with a magic number. In situations
- where this conflicts with existing keys (of other programs, having
- their own keys), you may supply a chosen value.
+ service name. In situations where this conflicts with existing
+ keys (of other programs, having their own keys), you may supply a
+ chosen value.
<p>
The actual key value doesn't matter much, as long as it's unique
and as long as each invocation of crossroads uses it.
<p><dt><strong>Syntax:</strong><dd> <code>shmkey</code> <em>number</em>
<p><dt><strong>Default:</strong><dd> 0, which means that crossroads will 'guess' its
- own key, based on TCP port and a magic number.
+ own key, based on the service name.
</dl>
-<p>
-<a name="conf/allow"></a><a name="l29"></a>
+<a name="conf/allow"></a><a name="l32"></a>
<strong>4.2.10: allow* and deny* - Allowing or denying connections</strong> <a name="confallow* and deny* - Allowing or denying connections"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Crossroads can allow or deny
@@ -916,7 +981,7 @@ The actual key value doesn't matter much, as long as it's unique
directives that are relevant: <code>allowfrom</code>, <code>allowfile</code>,
<code>denyfrom</code> and <code>denyfile</code>. When using <code>allowfrom</code> and
<code>denyfrom</code> then the IP addresses to allow or deny connections are
- stated in <code>/etc/crossroads.conf</code>.
+ stated in /etc/crossroads.conf.
<p>
When <code>allow*</code> directives are used, then all connections are denied
unless they match the stated allowed IP's. When <code>deny*</code> directives
@@ -930,7 +995,7 @@ The statements <code>allowfrom</code> and <code>denyfrom</code> are followed by
filter specifications from those external files. In both cases,
Crossroads obtains filter specifications and places them in its
lists of allowed or denied IP addresses. The difference between
- specifying filters in <code>/etc/crossroads.conf</code> or in external
+ specifying filters in /etc/crossroads.conf or in external
files, is that Crossroads will reload the external files when it
receives signal 1 (<code>SIGHUP</code>), as in <code>killall -1 crossroads</code>.
<p>
@@ -970,23 +1035,23 @@ This is probably best explained by a few examples:
<code>/tmp/myfile.txt</code>, with the contents <code>10.3.1.15 10.2/16</code>,
is the same as above.</ul>
<p><dt><strong>Syntax:</strong><dd> <ul>
- <li> <code>allowfrom</code> <em>filter-specificication(s)</em>
- <li> <code>denyfrom</code> <em>filter-specificication(s)</em>
- <li> <code>allowfile</code> <em>filename</em>
- <li> <code>denyfile</code> <em>filename</em></ul>
+ <li> <code>allowfrom</code> <em>filter-specificication(s)</em>
+ <li> <code>denyfrom</code> <em>filter-specificication(s)</em>
+ <li> <code>allowfile</code> <em>filename</em>
+ <li> <code>denyfile</code> <em>filename</em></ul>
<p><dt><strong>Default:</strong><dd> In absence of these statements, all client IP's are accepted.
</dl>
<p>
-<a name="conf/useraccount"></a><a name="l30"></a>
+<a name="conf/useraccount"></a><a name="l33"></a>
<strong>4.2.11: useraccount - Limiting the effective ID of external processes</strong> <a name="confuseraccount - Limiting the effective ID of external processes"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Using the directive <code>useraccount</code>, the effective user and group
ID can be restricted. This comes into effect when Crossroads runs
external commands, such as:
<ul>
- <li> Hooks for <code>onstart</code>, <code>onend</code> or <code>onfail</code>;
- <li> External dispatchers, when <code>dispatchmode
- externalhandler</code> is in effect.</ul>
+ <li> Hooks for <code>onstart</code>, <code>onend</code> or <code>onfail</code>;
+ <li> External dispatchers, when <code>dispatchmode
+ externalhandler</code> is in effect.</ul>
Once a user name for external commands is specified, Crossroads
assumes the associated user ID and group ID before running those
commands.
@@ -995,7 +1060,7 @@ This is probably best explained by a few examples:
ID that was in effect when Crossroads was started.
</dl>
<p>
-<a name="l31"></a>
+<a name="l34"></a>
<h3>4.3: Backend definitions</h3>
<p>
Inside the service definitions as are described in the previous
@@ -1031,21 +1096,26 @@ Crossroads treats the network traffic as a stream of HTTP messages;
i.e., when the service is declared with <code>type http</code>. Incase of
<code>type any</code>, the HTTP-specific directives have no effect.
<p>
-<a name="conf/server.yo"></a><a name="l32"></a>
+<a name="conf/server.yo"></a><a name="l35"></a>
<strong>4.3.1: server - Specifying the back end address</strong> <a name="confserver - Specifying the back end address"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Each back end must be identified by the network name
(server name) where it is located. For example: <code>server
10.1.1.23</code>, or <code>server web.mydomain.org</code>. A TCP port specifier
- can follow the server name, as in <code>server web.mydomain.org:80</code>.
+ can follow the server name, as in <code>server
+ web.mydomain.org:80</code>. <strong>Note that</strong> resolved host names are
+ cached by Crossroads; there is no performance advantage in
+ specifying decimal addresses. (The DNS cache timeout can be
+ controlled using the invocation flag <code>-d</code>.)
<p><dt><strong>Syntax:</strong><dd> <ul>
- <li> <code>server</code> <em>servername</em>, where <em>servername</em> is a
- network name or IP address;
- <li> <code>server</code> <em>servername:port</em></ul>
+ <li> <code>server</code> <em>servername</em>, where <em>servername</em> is a
+ network name or IP address. In this case a separate <code>port</code>
+ statement must be used to define the TCP port;
+ <li> <code>server</code> <em>servername:port</em></ul>
<p><dt><strong>Default:</strong><dd> There is no default. This is a required setting.
</dl>
<p>
-<a name="conf/verbose-backend.yo"></a><a name="l33"></a>
+<a name="conf/verbose-backend.yo"></a><a name="l36"></a>
<strong>4.3.2: verbosity - Controlling verbosity at the back end level</strong> <a name="confverbosity - Controlling verbosity at the back end level"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Similar to <code>service</code> specifications, a
@@ -1053,13 +1123,13 @@ i.e., when the service is declared with <code>type http</code>. Incase of
<code>on</code>, traffic to and fro this back end is reported.
<p><dt><strong>Syntax:</strong><dd> <ul>
<li> <code>verbosity</code> <em>setting</em>, or
- <li> <code>verbose</code> <em>setting</em>, where <em>setting</em> is <code>true</code>,
- <code>yes</code> or <code>on</code>, or <code>false</code>, <code>no</code>, <code>off</code> to turn it
- off.</ul>
+ <li> <code>verbose</code> <em>setting</em>, where <em>setting</em> is <code>true</code>,
+ <code>yes</code> or <code>on</code>, or <code>false</code>, <code>no</code>, <code>off</code> to turn it
+ off.</ul>
<p><dt><strong>Default:</strong><dd> <code>off</code>
</dl>
<p>
-<a name="conf/retries.yo"></a><a name="l34"></a>
+<a name="conf/retries.yo"></a><a name="l37"></a>
<strong>4.3.3: retries - Specifying allowed failures</strong> <a name="confretries - Specifying allowed failures"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Back ends that are 'flaky' or on a less reliable network can be
@@ -1074,7 +1144,7 @@ i.e., when the service is declared with <code>type http</code>. Incase of
connection.
</dl>
<p>
-<a name="conf/weight"></a><a name="l35"></a>
+<a name="conf/weight"></a><a name="l38"></a>
<strong>4.3.4: weight - When a back end is more equal than others</strong> <a name="confweight - When a back end is more equal than others"></a>
<dl>
<p><dt><strong>Description:</strong><dd> To influence how backends are selected, a backend can specify its
@@ -1093,7 +1163,7 @@ The weighing mechanism only applies to the dispatch modes
<p><dt><strong>Default:</strong><dd> 1; all back ends have equal weight.
</dl>
<p>
-<a name="conf/decay"></a><a name="l36"></a>
+<a name="conf/decay"></a><a name="l39"></a>
<strong>4.3.5: decay - Levelling out activity of a back end</strong> <a name="confdecay - Levelling out activity of a back end"></a>
<dl>
<p><dt><strong>Description:</strong><dd> To make sure that a 'spike' of activity doesn't
@@ -1115,20 +1185,20 @@ This means that when a given back end is hit, then its usage data
<p><dt><strong>Default:</strong><dd> 0, meaning that no decay is applied to usage statistics.
</dl>
<p>
-<a name="conf/onhooks"></a><a name="l37"></a>
+<a name="conf/onhooks"></a><a name="l40"></a>
<strong>4.3.6: onstart, onend, onfail - Action Hooks</strong> <a name="confonstart, onend, onfail - Action Hooks"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The three directives <code>onstart</code>, <code>onend</code> and <code>onfail</code> can be
specified to start system commands (external programs) when a
connection to a back end starts, fails or ends:
<ul>
- <li> <code>onstart</code> commands will be run when Crossroads
- successfully connects to a back end, and starts servicing;
- <li> <code>onend</code> commands will be run when a (previously
- established) connection stops;
- <li> <code>onfail</code> commands will be run when Crossroads tries to
- contact a back end to serve a client, but the back end can't
- be reached.</ul>
+ <li> <code>onstart</code> commands will be run when Crossroads
+ successfully connects to a back end, and starts servicing;
+ <li> <code>onend</code> commands will be run when a (previously
+ established) connection stops;
+ <li> <code>onfail</code> commands will be run when Crossroads tries to
+ contact a back end to serve a client, but the back end can't
+ be reached.</ul>
<p>
The format is always <code>on</code><em>type</em> <em>command</em>. The <em>command</em>
is an external program, optionally followed by arguments. The
@@ -1160,14 +1230,14 @@ The format is always <code>on</code><em>type</em> <em>command</em>. The <em>comm
<p>
<p><dt><strong>Syntax:</strong><dd> <ul>
<li> <code>onstart</code> <em>commandline</em>
- <li> <code>onend</code> <em>commandline</em>
- <li> <code>onfail</code> <em>commandline</em>
- <li> <code>onsuccess</code> <em>commandline</em></ul>
+ <li> <code>onend</code> <em>commandline</em>
+ <li> <code>onfail</code> <em>commandline</em>
+ <li> <code>onsuccess</code> <em>commandline</em></ul>
<p><dt><strong>Default:</strong><dd> There is no default. Normally no external programs are run upon
connection, success or failure of a back end.
</dl>
<p>
-<a name="conf/trafficlog"></a><a name="l38"></a>
+<a name="conf/trafficlog"></a><a name="l41"></a>
<strong>4.3.7: trafficlog and throughputlog - Debugging and Performance Aids</strong> <a name="conftrafficlog and throughputlog - Debugging and Performance Aids"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Two directives are available
@@ -1182,12 +1252,12 @@ The <code>trafficlog</code> statement causes all traffic to be logged in
The <code>throughputlog</code> statement writes shorthand transmissions to
its log, accompanied by timings.
<p><dt><strong>Syntax:</strong><dd> <ul>
- <li> <code>trafficlog</code> <em>filename</em>
+ <li> <code>trafficlog</code> <em>filename</em>
<li> <code>throughputlog</code> <em>filename</em></ul>
<p><dt><strong>Default:</strong><dd> none
</dl>
<p>
-<a name="conf/stickycookie"></a><a name="l39"></a>
+<a name="conf/stickycookie"></a><a name="l42"></a>
<strong>4.3.8: stickycookie - Back end selection with an HTTP cookie</strong> <a name="confstickycookie - Back end selection with an HTTP cookie"></a>
<dl>
<p><dt><strong>Description:</strong><dd> The directive <code>stickycookie</code> <em>value</em>
@@ -1227,7 +1297,7 @@ There are basically to provide such cookies to a browser. First, a
<p><dt><strong>Default:</strong><dd> There is no default.
</dl>
<p>
-<a name="conf/addclientheader"></a><a name="l40"></a>
+<a name="conf/addclientheader"></a><a name="l43"></a>
<strong>4.3.9: HTTP Header Modification Directives</strong> <a name="confHTTP Header Modification Directives"></a>
<dl>
<p><dt><strong>Description:</strong><dd> Crossroads understands the following
@@ -1380,36 +1450,36 @@ service ... {
</pre>
</dl>
<p><dt><strong>Syntax:</strong><dd> <ul>
- <li> <code>addclientheader</code> <em>Headername: headervalue</em> to add a
- header in the traffic towards the client, even when another
- header <em>Headername</em> exists;
- <li> <code>appendclientheader</code> <em>Headername: headervalue</em> to
- append <em>headervalue</em> to an existing header <em>Headername</em>
- in the traffic towards the client,
- or to add the whole header alltogether;
- <li> <code>setclientheader</code> <em>Headername: headervalue</em> to
- overwrite an existing header in the traffic towards the
- client, or to add such a header;
- <li> <code>addserverheader</code> <em>Headername: headervalue</em> to add a
- header in the traffic towards the server, even when another
- header <em>Headername</em> exists;
- <li> <code>appendserverheader</code> <em>Headername: headervalue</em> to
- append <em>headervalue</em> to an existing header <em>Headername</em>
- in the traffic towards the server,
- or to add the whole header alltogether;
- <li> <code>setserverheader</code> <em>Headername: headervalue</em> to
- overwrite an existing header in the traffic towards the
- server, or to add such a header.</ul>
+ <li> <code>addclientheader</code> <em>Headername: headervalue</em> to add a
+ header in the traffic towards the client, even when another
+ header <em>Headername</em> exists;
+ <li> <code>appendclientheader</code> <em>Headername: headervalue</em> to
+ append <em>headervalue</em> to an existing header <em>Headername</em>
+ in the traffic towards the client,
+ or to add the whole header alltogether;
+ <li> <code>setclientheader</code> <em>Headername: headervalue</em> to
+ overwrite an existing header in the traffic towards the
+ client, or to add such a header;
+ <li> <code>addserverheader</code> <em>Headername: headervalue</em> to add a
+ header in the traffic towards the server, even when another
+ header <em>Headername</em> exists;
+ <li> <code>appendserverheader</code> <em>Headername: headervalue</em> to
+ append <em>headervalue</em> to an existing header <em>Headername</em>
+ in the traffic towards the server,
+ or to add the whole header alltogether;
+ <li> <code>setserverheader</code> <em>Headername: headervalue</em> to
+ overwrite an existing header in the traffic towards the
+ server, or to add such a header.</ul>
<p><dt><strong>Default:</strong><dd> There is no default.
</dl>
<p>
-<a name="l41"></a>
+<a name="l44"></a>
<h2>5: Tips, Tricks and Random Remarks</h2>
<a name="tips"></a>The following sections elaborate on the directives as described in
section <a href="crossroads.html#config">4</a> to illustrate how crossroads works and to help you
achieve the "optimal" balancing configuration.
<p>
-<a name="l42"></a>
+<a name="l45"></a>
<h3>5.1: How back ends are selected in load balancing</h3> <a name="howselected"></a>
<a name="tips/howselected"></a>In order to tune your load balancing, you'll need to understand how
crossroads computes usage, how weighing works, and so on. In this
@@ -1417,7 +1487,7 @@ section we'll focus on the dispatching modes <code>bysize</code>, <code>bydurati
and <code>byconnections</code> only. The other dispatching types are
self-explanatory.
<p>
-<a name="l43"></a>
+<a name="l46"></a>
<strong>5.1.1: Bysize, byduration or byconnections?</strong>
<p>
As stated before, crossroads doesn't know 'what a service does' and
@@ -1467,7 +1537,7 @@ E.g., consider a database connection. What's
<p>
</ul>
<p>
-<a name="l44"></a>
+<a name="l47"></a>
<strong>5.1.2: Averaging size and duration</strong>
<p>
The configuration statement <code>dispatchmode bysize</code> or <code>byduration</code>
@@ -1488,7 +1558,7 @@ In contrast, when e.g. <code>over 3</code> is in effect, then a sudden load
does show up -- because it highly contributes to the average of three
connections.
<p>
-<a name="l45"></a>
+<a name="l48"></a>
<strong>5.1.3: Specifying decays</strong>
<p>
Decays are also only relevant when crossroads computes the 'next best
@@ -1542,7 +1612,7 @@ service soap {
</pre>
<p>
-<a name="l46"></a>
+<a name="l49"></a>
<strong>5.1.4: Adjusting the weights</strong>
<p>
The back end modifier <code>weight</code> is useful in situations where your
@@ -1596,7 +1666,7 @@ both A and B crash). Note also that A's usage data decay much faster
than B's and C's: we're assuming that this big server recovers quicker
than its smaller siblings.
<p>
-<a name="l47"></a>
+<a name="l50"></a>
<h3>5.2: Throttling the number of concurrent connections</h3>
<a name="tips/throttling"></a>If you suspect that your service may occasionally receive 'spikes' of
activity (which you should always assume), then it might be a
@@ -1625,14 +1695,14 @@ too much, a situation may occur where that back end is about to be
hit. A <code>maxconnections</code> statement on the level of that back may then
protect it.
<p>
-<a name="l48"></a>
+<a name="l51"></a>
<h3>5.3: Using an external program to dispatch</h3> <a name="externalhandler"></a>
<a name="tips/externalhandler"></a>As mentioned before, Crossroads supports several built-in dispatch
modes. However, you are always free to hook-in your own dispatch mode
that determines the next back end using your own specific
algorithm. This section explains how to do it.
<p>
-<a name="l49"></a>
+<a name="l52"></a>
<strong>5.3.1: Configuring the external handler</strong>
<p>
First, the <code>dispatchmode</code> statement needs to inform Crossroads that
@@ -1671,16 +1741,16 @@ Note that the format specifiers such as <code>%b</code> don't make sense in the
phase in which an external handler is called, since there is no
current back end yet (the job of the handler is to supply one).
<p>
-<a name="l50"></a>
+<a name="l53"></a>
<strong>5.3.2: Writing the external handler</strong>
<p>
The external handler is activated using the arguments that are
-specified in <code>/etc/crossroads.conf</code>. The external handler can do
+specified in /etc/crossroads.conf. The external handler can do
whatever it wants, but ultimately, it must write a back end name on
its <em>stdout</em>. Crossroads reads this, and if the back end is
available, uses that back end for the connection.
<p>
-<a name="l51"></a>
+<a name="l54"></a>
<strong>5.3.3: Examples of external handlers</strong>
<p>
This section shows some examples of Crossroads configurations
@@ -2109,7 +2179,7 @@ if ($action eq 'dispatch') {
</pre>
<p>
-<a name="l52"></a>
+<a name="l55"></a>
<h3>5.4: TCP Session Stickiness</h3>
<a name="tips/tcpstickiness"></a>If you need to make sure that a client that once gets dispatched to a
given back end keeps re-visiting the back end, then Crossroads offers
@@ -2134,7 +2204,7 @@ If the preferred back end is unavailable, then the action that
Crossroads takes is to dispatch as if <code>byconnections</code>: of the
available back ends, the one with the least connections is taken.
<p>
-<a name="l53"></a>
+<a name="l56"></a>
<h3>5.5: HTTP Session Stickiness</h3>
<a name="tips/httpstickiness"></a>This section focuses on HTTP session stickiness. This term refers to
the ability of a balancer to route a conversation between browser and
@@ -2142,7 +2212,7 @@ a backend farm with webservers always to the same back end. In other
words: once a back end is selected by the balancer, it will remain the
back end of choice, even for subsequent connections.
<p>
-<a name="l54"></a>
+<a name="l57"></a>
<strong>5.5.1: Don't use stickiness!</strong>
<p>
The rule of thumb as far as the balancer is concerned, is: <strong>Do not
@@ -2174,7 +2244,7 @@ that all PHP applications have access to these data. Application
servers such as Websphere can be configured to replicate session data
between nodes.
<p>
-<a name="l55"></a>
+<a name="l58"></a>
<strong>5.5.2: But if you must..</strong>
<p>
If you really need stickiness, think first whether you might use TCP
@@ -2252,7 +2322,7 @@ Note how the cookie names and values in the directives
<code>stickycookie</code> and <code>addclientheader</code> match. That is obviously a
prerequisite for stickiness.
<p>
-<a name="l56"></a>
+<a name="l59"></a>
<h3>5.6: Passing the client's IP address</h3>
<a name="tips/clientip"></a>Since Crossroads just shuttles bytes to and fro, meta-information of
network connections is lost. As far as the back ends are concerned,
@@ -2279,7 +2349,7 @@ header: <code>X-Real-IP</code>, holding the client's IP address.
performance will be hampered -- all passing messages will have to be
unpacked and analyzed.
<p>
-<a name="l57"></a>
+<a name="l60"></a>
<strong>5.6.1: Sample Crossroads configuration</strong>
<p>
The below sample configuration shows two HTTP back ends that receive
@@ -2306,7 +2376,7 @@ service www {
</pre>
<p>
-<a name="l58"></a>
+<a name="l61"></a>
<strong>5.6.2: Sample Apache configuration</strong>
<p>
The method by which each back end analyzes the header <code>X-Real-IP</code>
@@ -2338,7 +2408,7 @@ LogFormat "%{X-Real-IP}i %l %u %t %D \"%r\" %>s %b" common
</pre>
<p>
-<a name="l59"></a>
+<a name="l62"></a>
<h3>5.7: Debugging network traffic</h3>
<a name="tips/debugging"></a> Incase the traffic between
client and backend
@@ -2461,9 +2531,9 @@ Summarizing, the throughput times of a client-back end connection
analyze the output and to compute round trip times. Such scripts
are not (yet) included in Crossroads.
<p>
-<a name="l60"></a>
+<a name="l63"></a>
<h3>5.8: IP filtering: Limiting Access by Client IP Address</h3>
-<a name="tips/ipfiltering"></a><a name="l61"></a>
+<a name="tips/ipfiltering"></a><a name="l64"></a>
<strong>5.8.1: General Examples</strong>
<p>
The directives <code>allowfrom</code>, <code>denyfrom</code>, <code>allowfile</code> and
@@ -2500,7 +2570,7 @@ with 192.168.1. The specifier <code>192.168.1/24</code> states that there are
three network bytes (192, 168 and 1), and 24 bits (or 3 bytes) are
relevant; so that the fourth network byte doesn't matter.
<p>
-<a name="l62"></a>
+<a name="l65"></a>
<strong>5.8.2: Using External Files</strong>
<p>
The directives <code>allowfile</code> and <code>denyfile</code> allow you to specify IP
@@ -2532,7 +2602,7 @@ is running, you may edit <code>/tmp/allow.txt</code>, and then issue <code>killa
-1 crossroads</code>. The new contents of <code>/tmp/allow.txt</code> will be
reloaded.
<p>
-<a name="l63"></a>
+<a name="l66"></a>
<strong>5.8.3: Mixing Directives</strong>
<p>
Crossroads allows to mix all directives in one service
@@ -2575,7 +2645,7 @@ This will first of all deny access to all IP addresses that
<p>
<li> Blacklisting or whitelisting can be left out.
A list is considered empty when no appropriate directives
- occur in <code>/etc/crossroads.conf</code>, or when the directive
+ occur in /etc/crossroads.conf, or when the directive
points to an empty or non-existent external file.
<p>
<li> Using <code>*from</code> and <code>*file</code> statements is allowed, but
@@ -2599,10 +2669,10 @@ Crossroads only performs syntactic checking of the configuration. Some
of the above samples are syntactically correct, but make no semantic
sense: Crossroads doesn't warn for such situations.
<p>
-<a name="l64"></a>
+<a name="l67"></a>
<h3>5.9: Configuration examples</h3>
<a name="tips/examples"></a>
-<a name="l65"></a>
+<a name="l68"></a>
<strong>5.9.1: A load balancer for three webserver back ends</strong>
<p>
The following configuration example binds crossroads to port 80 of the
@@ -2731,10 +2801,10 @@ service www {
</pre>
<p>
-<a name="l66"></a>
+<a name="l69"></a>
<strong>5.9.2: An HTTP forwarder when travelling</strong>
<p>
-As another example, here's my <code>crossroads.conf</code> that I use on my
+As another example, here's my /etc/crossroads.conf that I use on my
Unix laptop. The problem that I face is that I need many HTTP proxy
configurations (at home, at customers' sites and so on) but I'm too
lazy to reconfigure browsers all the time.
@@ -2820,7 +2890,7 @@ and <code>LocalSquid</code> are both active, then <code>crossroads tell httpprox
sshtunnel down</code> will 'take down' the back end <code>SshTunnel</code> -- and
will automatically cause crossroads to switch to <code>LocalSquid</code>.
<p>
-<a name="l67"></a>
+<a name="l70"></a>
<strong>5.9.3: SSH login with enforced idle logout</strong>
<p>
The following example shows how crossroads 'throttles' SSH
@@ -2846,7 +2916,7 @@ service Ssh {
</pre>
<p>
-<a name="l68"></a>
+<a name="l71"></a>
<h3>5.10: Linux and ip_conntrack_max</h3>
<a name="tips/ipconntrackmax"></a>The kernel value of <code>ip_conntrack_max</code> is important for routers and
balancers under Linux. Basically it's the maximum number of tracked
@@ -2883,7 +2953,7 @@ out yourself. Note however that each count will cause the kernel to
reserve 350 bytes. So if you set <code>ip_conntrack_max</code> to 100.000, then
you're already taking 33.3Mb off the total available memory.
<p>
-<a name="l69"></a>
+<a name="l72"></a>
<h3>5.11: Marking back ends as bad after more than one try</h3>
<a name="tips/retries"></a>Crossroads allows you to specify on a per-back end basis how many
retries are needed before a back end is considered unavailable. The
@@ -2928,7 +2998,7 @@ retry connecting with a small one-second delay in between. A high
<code>retries</code> number means also lots of one-second delays, in which time
a client is kept waiting.
<p>
-<a name="l70"></a>
+<a name="l73"></a>
<h3>5.12: Scripting Crossroads' back end availability</h3>
<a name="tips/scripting"></a>The internal reviving model of Crossroads can periodically check
whether back ends that are unavailable have woken up yet. The checker
@@ -2965,16 +3035,16 @@ In such situations you may want to replace the internal wakeup service
with your own scripted 'health check'. Here's how:
<p>
<ul>
- <li> First of all, you take out the <code>revivinginterval</code>
- statement of <code>/etc/crossroads.conf</code>, so that Crossroads'
- internal check which only verifies TCP connectivity is
- disabled.
+ <li> First of all, you take out the <code>revivinginterval</code>
+ statement of /etc/crossroads.conf, so that Crossroads'
+ internal check which only verifies TCP connectivity is
+ disabled.
<p>
<li> You determine a suitable URL in the applications that can
- be queried for the health. In our example this will be
- <code>/areyouthere.jsp</code>, a hypothetical page that does some
- database access. It doesn't even need to return output; just
- succeed, or fail.
+ be queried for the health. In our example this will be
+ <code>/areyouthere.jsp</code>, a hypothetical page that does some
+ database access. It doesn't even need to return output; just
+ succeed, or fail.
<p>
<li> You devise a small script that asks Crossroads the status
of back ends of a given service (in our example, service
@@ -3091,8 +3161,8 @@ done
The further implementation of such a mini-daemon that fires up
<code>healthcheck</code> is left to the reader.
<p>
-<a name="l71"></a>
-<h3>5.13: Rendering Crossroads' status in a web page</h3>
+<a name="l74"></a>
+<h3>5.13: Rendering Crossroads' status in a web page</h3> <a name="xmlstatus"></a>
<a name="tips/rendering"></a>The Crossroads flag <code>-x</code> causes the status output to be generated as
an XML document. This format can be nicely used to render the output
as an HTML page.
@@ -3149,25 +3219,49 @@ The solution for this problem is to make the shared memory access
somewhat more liberal. There are basically two options:
<p>
<ul>
- <li> Start Crossroads with the flag <code>-m 0666</code>, which makes
- the shared memory segment available to all. The octal number
- 0666 works just like a file permission setting under
- Unix. Now, any user can run <code>crossroads status</code>.
+ <li> Start Crossroads with the flag <code>-m 0666</code>, which makes
+ the shared memory segment available to all. The octal number
+ 0666 works just like a file permission setting under
+ Unix. Now, any user can run <code>crossroads status</code>.
<p>
<li> If you want to make the access to Crossroads' shared
- memory somewhat stricter, then make the user who starts
- Crossroads and the user who runs the webserver member of a new
- Unix group. Start Crossroads with the flag <code>-m 0664</code>. Now,
- users belonging to the same group as the Crossroads starter
- can run <code>crossroads status</code>.</ul>
+ memory somewhat stricter, then make the user who starts
+ Crossroads and the user who runs the webserver member of a new
+ Unix group. Start Crossroads with the flag <code>-m 0664</code>. Now,
+ users belonging to the same group as the Crossroads starter
+ can run <code>crossroads status</code>.</ul>
<p>
-<a name="l72"></a>
+<a name="l75"></a>
+<h3>5.14: Crossroads and DNS caching</h3>
+<a name="tips/dnscaching"></a>
+The option <code>-d</code> allows you to control Crossroads' built in DNS
+caching mechanism. Most often you will not need to use this:
+DNS lookups in Crossroads occur only to find back ends; and back ends
+are usually 'near' to the balancer.
+<p>
+You might want or need to use DNS caching if:
+<p>
+<ul>
+ <li> Back end servers are specified as hostnames, and not as
+ IP addresses;
+ <li> DNS resolving of those host names is perceptibly slow.</ul>
+<p>
+You can test DNS resolving from the command line using e.g. the
+commands <code>nslookup</code> and <code>host</code>.
+<p>
+If DNS resolving is an issue, then you can specify the flag <code>-d</code>
+<em>nsec</em> on the command line while invoking Crossroads. This instructs
+Crossroads to use its DNS cache to store results. Each result is
+stored for up to <em>nsec</em> seconds - after that, a new request for the
+back end will lead to a new DNS lookup.
+<p>
+<a name="l76"></a>
<h2>6: Benchmarking</h2>
<a name="benchmarking"></a>This section shows how crossroads affects the
transmitting of HTML data when used as an intermediate 'station'
through which all data travels.
<p>
-<a name="l73"></a>
+<a name="l77"></a>
<h3>6.1: Benchmark 1: Accessing a proxy via crossroads or directly</h3>
<p>
The benchmark was run on a system where the following was varied:
@@ -3195,7 +3289,7 @@ service HttpProxy {
</pre>
<p>
-<a name="l74"></a>
+<a name="l78"></a>
<strong>6.1.1: Results</strong>
<p>
The results of this test are that crossroads causes a negligible
@@ -3218,7 +3312,7 @@ sys 0m0.230s
</pre>
<p>
-<a name="l75"></a>
+<a name="l79"></a>
<strong>6.1.2: Discussion</strong>
<p>
The above shown results are quite favorable to crossroads. However,
@@ -3250,7 +3344,7 @@ seldom in the real world:
back end). Again, this processing time will weigh much heavier
than the multiple read/writes.</ul>
<p>
-<a name="l76"></a>
+<a name="l80"></a>
<h3>6.2: Benchmark 2: Crossroads versus Linux Virtual Server (LVS)</h3>
<p>
LVS is a kernel-based balancer that acts like a masquerading
@@ -3264,7 +3358,7 @@ LVS isn't aware of downtime of back ends (unless one implements an
external heartbeat). Also, crossroads offers more complex balancing
than LVS.
<p>
-<a name="l77"></a>
+<a name="l81"></a>
<strong>6.2.1: Environment</strong>
<p>
On the balancer, LVS was run on port 80, its forwarding set up for two
@@ -3295,7 +3389,7 @@ service http {
</pre>
<p>
-<a name="l78"></a>
+<a name="l82"></a>
<strong>6.2.2: Tests and results</strong>
<p>
In the first test, ports 80 and 81 on the balancer were 'bombed' with
@@ -3374,9 +3468,9 @@ are shown in the below table:
Again, the results show that crossroads performs just as effectively
as LVS, even with large data chunks!
<p>
-<a name="l79"></a>
+<a name="l83"></a>
<h2>7: Compiling and Installing</h2> <a name="installation"></a>
-<a name="compiling"></a><a name="l80"></a>
+<a name="compiling"></a><a name="l84"></a>
<h3>7.1: Prerequisites</h3>
<p>
The creation of crossroads requires:
@@ -3393,7 +3487,7 @@ The creation of crossroads requires:
Basically a Linux or Apple MacOSX box will do nicely. To compile and install
crossroads, follow these steps.
<p>
-<a name="l81"></a>
+<a name="l85"></a>
<h3>7.2: Compiling and installing</h3>
<p>
<ul>
@@ -3425,7 +3519,17 @@ crossroads, follow these steps.
to be done by the user <code>root</code> if the <code>BINDIR</code> setting of
<code>etc/Makefile.def</code> points to a root-owned directory.
<p>
-<li> The documentation doesn't install in this process. If you
+<li> The manual pages on the basic usage of Crossroads and on
+ the layout of the configuration file are installed as
+ well, if a suitable <code>man/</code> directory is present under the
+ installation prefix directory. If these pages are not
+ installed, then you can always copy <code>doc/crossroads.1</code> to a
+ suitable <code>man/man1/</code> directory, and
+ <code>doc/crossroads.conf.7</code> to a suitable <code>man/man7/</code>
+ directory. After this, <code>man crossroads</code> and <code>man
+ crossroads.conf</code> would show the appropriate manual pages.
+<p>
+<li> The full documentation doesn't install in this process. If you
want to install the documentation, then proceed as follows:
<p>
<ul>
@@ -3435,27 +3539,15 @@ crossroads, follow these steps.
<p>
<li> Optionally, <code>cp doc/crossroads.pdf</code>
<em>pdfdirectory/</em>; where <em>pdfdirectory</em> is the
- destination directory for your PDF manuals;
-<p>
-<li> Optionally, <code>cp doc/crossroads.man</code>
- <em>manualdirectory</em><code>/crossroads.1</code>, where
- <em>manualdirectory</em> is e.g. <code>/usr/man/man1</code>,
- <code>/usr/share/man1</code>, <code>/usr/local/man/man1</code>,
- <code>/usr/local/share/man1</code>. Any possibility is valid, as
- long as <em>manualdirectory</em> is one of the directories
- where manual pages are stored;
-<p>
-<li> If your manual page system supports compressed
- manual pages, then you can save some space with
- <code>gzip</code> <em>manualdirectory</em><code>/crossroads.1</code>.</ul>
+ destination directory for your PDF manuals.</ul>
<p>
</ul>
<p>
-<a name="l82"></a>
+<a name="l86"></a>
<h3>7.3: Configuring crossroads</h3>
<p>
Now that the binary is available on your system, you need to create a
-suitable <code>/etc/crossroads.conf</code>. Use this manual or the output of
+suitable /etc/crossroads.conf. Use this manual or the output of
<code>crossroads samplconf</code> to get started.
<p>
Once you have the configuration ready, start crossroads with
@@ -3500,13 +3592,13 @@ which crossroads daemons are running. Finally, the tailing of
<code>/var/log/messages</code> shows what's going on -- especially if you have
<code>verbosity true</code> statements in the configuration.
<p>
-<a name="l83"></a>
+<a name="l87"></a>
<h3>7.4: A boot script</h3>
<p>
Finally, you may want to create a boot-time startup script. The exact
procedure depends on the used Unix flavor.
<p>
-<a name="l84"></a>
+<a name="l88"></a>
<strong>7.4.1: SysV Style Startup</strong>
<p>
On SysV style systems, there's a startup script directory
@@ -3548,7 +3640,7 @@ If your runlevel is 5, then the right <code>cd</code> command is to
<code>/etc/rc.d/rc5.d</code>. Alternatively, you can create the
symlinks in both runlevel directories.</ul>
<p>
-<a name="l85"></a>
+<a name="l89"></a>
<strong>7.4.2: BSD Style Startup</strong>
<p>
On BSD style systems, daemons are booted directly from <code>/etc/rc</code> and
diff --git a/doc/crossroads.man b/doc/crossroads.man
@@ -209,7 +209,24 @@ controlled manner, without any client noticing it\&.
.PP
-.SH "1\&.5: Porting issues for pre-1\&.21 installations"
+.SH "1\&.5: Porting issues for pre-1\&.43 installations"
+
+.PP
+As of version 1\&.43, the shared memory key calculations are based
+on a different algorithm\&. This key is e\&.g\&. necessary when starting
+and stopping Crossroads; in both actions, the key must be computed
+in the same way\&.
+.PP
+Therefore, when upgrading Crossroads, make sure that you stop a
+running Crossroads daemon using the same binary that started
+it\&. After this, install a new binary, and start the daemon using
+the new binary\&.
+.PP
+(Incidentally, this is always a good idea, but especially so when
+the \&'old\&' binary is pre-1\&.43 and the \&'new\&' one is post-1\&.43\&.)
+.PP
+
+.SH "1\&.6: Porting issues for pre-1\&.21 installations"
.PP
As of version 1\&.21, the event-hook directives \f(CWonsuccess\fP and
@@ -227,7 +244,7 @@ The commands that are run via \f(CWonstart\fP, \f(CWonend\fP or \f(CWonfail\fP
weight of the first back end, etc\&.\&. See section ?? for details\&.
.PP
-.SH "1\&.6: Porting issues for pre-0\&.26 installations"
+.SH "1\&.7: Porting issues for pre-0\&.26 installations"
.PP
As of version 0\&.26 the syntax of the configuration file has
@@ -248,7 +265,7 @@ multiple TCP connections, and the term
TCP connection\&.)
.PP
-.SH "1\&.7: Porting issues for pre-1\&.08 installations"
+.SH "1\&.8: Porting issues for pre-1\&.08 installations"
.PP
As of version 1\&.08, the following directives no longer are
@@ -847,19 +864,18 @@ running services\&. This is internally implemented through shared
memory, which is reserved using a key\&.
.IP
Normally crossroads will supply a shared memory key, based on the
-service port and bitwise or-ed with a magic number\&. In situations
-where this conflicts with existing keys (of other programs, having
-their own keys), you may supply a chosen value\&.
+service name\&. In situations where this conflicts with existing
+keys (of other programs, having their own keys), you may supply a
+chosen value\&.
.IP
The actual key value doesn\&'t matter much, as long as it\&'s unique
and as long as each invocation of crossroads uses it\&.
.IP "Syntax:"
\f(CWshmkey\fP \fInumber\fP
.IP "Default:"
-0, which means that crossroads will \&'guess\&' its
-own key, based on TCP port and a magic number\&.
-
-.PP
+ 0, which means that crossroads will \&'guess\&' its
+ own key, based on the service name\&.
+
.SH "4\&.2\&.10: allow* and deny* - Allowing or denying connections"
.IP "Description:"
diff --git a/doc/crossroads.pdf b/doc/crossroads.pdf
Binary files differ.
diff --git a/doc/crossroads.yo b/doc/crossroads.yo
@@ -1,38 +0,0 @@
-tocclearpage()
-titleclearpage()
-includefile(defs.yo)
-abstract(Crossroads is a load balance and fail over utility for TCP
- based services. It is a daemon program running in user
- space, and features extensive configurability, polling of
- back ends using 'wakeup calls', detailed status reporting,
- 'hooks' for special actions when backend calls fail, and much
- more. Crossroads is service-independent: it is usable for
- HTTP/HTTPS, SSH, SMTP, DNS, etc. In the case of HTTP
- balancing, Crossroads can modify HTTP headers, e.g. to
- provide 'session stickiness' for back-end processes that need
- sessions, but aren't session-aware of other back-ends.)
-article(Crossroads VER())
- (Karel Kubat)
- (2005, 2006, ff.)
-
-sect(Introduction)
-includefile(intro)
-
-sect(Installation for the impatient)
-includefile(impatient)
-
-sect(Using Crossroads)
-includefile(using)
-
-sect(The configuration)
-includefile(config)
-
-sect(Tips, Tricks and Random Remarks)
-includefile(tips)
-
-sect(Benchmarking)
-includefile(benchmarking)
-
-sect(Compiling and Installing) label(installation)
-includefile(compiling)
-
diff --git a/doc/impatient.yo b/doc/impatient.yo
@@ -1,65 +0,0 @@
-
-For the impatient, here's the very-quick-but-very-superficial recipy
-for getting crossroads up and running:
-
-itemization(
-
- it() If you don't have SVN or don't want to use it:
-
- itemization(
- it() Obtain the crossroads source archive at
- lurl(http://crossroads.e-tunity.com).
-
- it() Change-dir to a 'sources' directory on your system and
- unpack the archive.
-
- it() Change-dir into the create directory tt(crossroads/).)
-
- it() If you have SVN and want to go for the newest snapshot:
-
- itemization(
- it() Get the latest sources and snapshots using SVN from nl()
- tt(svn://svn.e-tunity.com/crossroads).
-
- it() You'll find the newest alpha version under
- tt(crossroads/trunk) and the stable versions under
- tt(crossroads/tags),
- e.g. tt(crossroads/tags/release-1.00).
-
- it() Choose which you want to use: the latest stable
- release, or the bleeding edge alpha? In the former case,
- change-dir to tt(crossroads/tags/release-)em(X.YY), where
- em(X.YY) is a release ID. In the latter case, change-dir to
- tt(crossroads/trunk).)
-
- it() Type tt(make install). This installs the crossroads
- binary into tt(/usr/local/bin/). If the compilation doesn't
- work on your system, check tt(etc/Makefile.def) for hints.
-
- it() Create a file tt(/etc/crossroads.conf). In it state
- something like:
-
- verb(\
-service www {
- port 80;
- revivinginterval 15;
- backend one {
- server 10.1.1.100:80;
- }
- backend two {
- server 10.1.1.101:80;
- }
-})
-
- That's off course assuming that you want to balance HTTP on
- port 80 to two back ends at 10.1.1.100 and 10.1.1.101.
-
- it() Type tt(crossroads start).
-
- it() Surf to the machine where crossroads is running. You will
- see the pages served by the back ends 10.1.1.100 or
- 10.1.1.101.
-
- it() To monitor the status of crossroads, type tt(crossroads
- status).
-)
diff --git a/doc/intro.yo b/doc/intro.yo
@@ -1,229 +0,0 @@
-Crossroads is a daemon that basically accepts TCP connections
-at preconfigured ports, and given a list of 'back ends'
-distributes each incoming connection to one of the back ends,
-so that a client request is
-served. Additionally, crossroads maintains an internal
-administration of the back end connectivity: if a back end isn't
-usable, then the client request is handled using another back
-end. Crossroads will then periodically check whether a previously not
-usable back end has come to life yet. Also, crossroads can select
-back ends by estimating the load, so that balancing is achieved.
-
-Using this approach, crossroads serves as load balancer and fail over
-utility. Crossroads will very likely not be as reliable as
-hardware based balancers, since it always will require a server to
-run on. This server, in turn, may become a new Single Point of
-Failure (SPOS). However, in situations where cost efficiency is an issue,
-crossroads may be a good choice. Furthermore, crossroads can be
-deployed in situations where a hardware based balancing already
-exists and augmenting service reliability is needed. Or, crossroads may be
-run off a diskless system, which again improves reliability of the
-underlying hardware.
-
-This document describes how to use crossroads, how to configure it
-in order to increase the reliability of your systems, and how to
-compile the program from its sources. whenhtml(This document is
-also available in url(PDF)(crossroads.pdf) format.)
-
-subsect(Obtaining Crossroads)
-
-As quick reference, here are some important URL's for Crossroads:
-
-itemization(
- it() lurl(http:/crossroads.e-tunity.com) is the site that serves
- Crossroads. You can browse this at leisure
- for documentation, sources, and so on.
-
- it() lurl(http://freshmeat.net/projects/crossr) is the
- Freshmeat announcement page.
-
- it() lurl(svn://svn.e-tunity.com/crossroads) is the SVN
- repository; anonymous reading (fetching) is allowed. In order
- to commit changes, url(mail me)(mailto:karel@e-tunity.com) for
- credentials.)
-
-subsect(Reporting bugs)
-
-Crossroads was thoroughly tested and proven to work. However, on
-particular Unices with particular needs and network particularities,
-bugs may occur.
-
-In such cases you can contact the maintainer to ask for
-assistance. Visit the site url(http://crossroads.e-tunity.com)
-(http://crossroads.e-tunity.com) for contact information. In questions
-or bug reports, always include the following:
-
-itemization(
- it() A description of the bug: when does it occur, what are
- the circumstances, what is the expected behavior, what is the
- observed behavior.
-
- it() The Crossroads configuration (normally
- tt(/etc/crossroads.conf))
-
- it() The version of Crossroads and all compile-time settings,
- obtained via tt(crossroads -C).)
-
-subsect(Copyright and Disclaimer)
-
-Crossroads is distributed as-is, without assumptions of fitness
-or usability. You are free to use crossroads to your
-liking. It's free, and as with everything that's free: there's
-also no warranty.
-
-You are allowed to make modifications to the source code of
-crossroads, and you are allowed to (re)distribute crossroads, as
-long as you include this text, all sources, and if applicable: all
-your modifications, with each distribution.
-
-While you are allowed to make any and all changes to the sources,
-I would appreciate hearing about them. If the changes concern new
-functionality or bugfixes, then I'll include them in a next
-release, stating full credits. If you want to seriously contribute (to
-which you are heartily encouraged), then mail me and I'll get you
-access to the Crossroads SVN repository, so that you can update and
-commit as you like.
-
-subsect(Terminology)
-
-Throughout this document, the following terms are used: footnote(Many
-more meanings of the terms will exist -- yes, I am aware of that. I'm
-using the terms here in a very strict sense.)
-
-description(
- dit(A client) is a process that initiates a network connection
- to get contact with some service.
- dit(A service) or bf(server process) or bf(listener)
- is a central application
- that accepts network connections from clients and sevices
- them.
- dit(Back ends) are locations where crossroads looks in
- order to service its clients. Crossroads sits 'in between'
- and does its tricks. Therefore, as far as the back ends
- are concerned, crossroads behaves like a client. As far as
- the true client is concerned, crossroads behaves like the
- service. The communication is however transparent: neither
- client nor back end are aware of the middle position of
- crossroads.
- dit(A connection) is a network conversation between client and service,
- where data are transferred to and fro. As
- far as crossroads is concerned, success means that a
- connection can be established without errors on
- the network level. Crossroads isn't aware of service
- pecularities. E.g., when a webserver answers tt(HTTP/1.0
- 500 Server Error) then crossroads will see this as a
- succesful connection, though the user behind a browser may
- think otherwise.
- dit(Back end selection algorithms) are methods by which
- crossroads determines which back end it will talk to
- next. Crossroads has a number of built-in algorithms,
- which may be configured per service.
- dit(Back end states) are the statusses of each back end that
- is known to crossroads. A back end may be available,
- (temporarily) unavailble or truly down. When a back end is
- temporarily unavailable, then crossroads will periodically
- check whether the back end has come to life yet (that is,
- if configured so).
- dit(A spike) is a sudden increase in activity, leading to
- extra load on a given service. When crossroads is in
- effect and when the spike occurs in one connection,
- then obviously the spike will also appear at one
- of the back ends. However, crossroads will see the spike
- and will make sure that a subsequent request goes to an
- other back end. In contrast, when several connections
- arrive simultaneously and cause a spike, then crossroads
- will be able to distribute the connections over several
- back ends, thereby 'flattening out' the increase.
- dit(Load balancing) means that incoming client requests are
- distributed over more than just one back end (which wouldn't be the
- case if you wouldn't be running crossroads). Enabling load
- balancing is nothing more than duplicating services over
- more than one back end, and having something (in this
- case: crossroads) distribute the requests, so that per
- back end the load doesn't get too high.
- dit(An HTTP session) is a series of separate network connections
- that originate from one browser. E.g., to fill the display
- with text and images, the browser hits a website several times.
- An HTTP session may even span several
- screens. E.g., a website registration dialog may involve 3
- screens that when called from the same browser,
- form a logical group of some sort.
- dit(Headers) or bf(header lines) are specific parts of an HTTP
- message. Crossroads has directives to add or modify
- headers that are part of the request that a browser sends
- to server, or those that are part of the server.
- dit(Session stickiness) means that when a browser starts an
- HTTP dialog, the balancer makes sure that it 'sticks' to
- the same back end (i.e., subsequent requests from the
- browser are forced to go to the same back end, instead of
- being balanced to other ones).
- dit(Back end usage) is measured by crossroads in order to be
- able to determine back end selection. Crossroads stores
- information about the number of active connections, the
- transferred bytes and
- about the connection duration. These numbers can be used to
- estimate which back end is the least used -- and
- therefore, presumably, the best candidate for a new
- request.
- dit(Fail over) is almost always used when load balancing is in
- effect. The distributor of client requests (crossroads of
- course) can also monitor back ends, so that incase a back
- end is 'down', it is no longer accessed.
- dit(Service downtime) normally occurs when a service is
- switched off. Downtime is obviously avoided when fail over
- is in effect: a back end can be taken out of service in a
- controlled manner, without any client noticing it.
-)
-
-subsect(Porting issues for pre-1.21 installations)
-
- As of version 1.21, the event-hook directives tt(onsuccess) and
- tt(onfailure) no longer exists.
-
- itemization(
- it() Please replace tt(onsuccess) by tt(onstart);
- it() Please replace tt(onfailure) bu tt(onfail);
- it() Note that there is a new hook tt(onend).)
-
- The commands that are run via tt(onstart), tt(onend) or tt(onfail)
- are subject to format expansion; e.g., tt(%1w) is expanded to the
- weight of the first back end, etc.. See section ref(config) for details.
-
-subsect(Porting issues for pre-0.26 installations)
-
- As of version 0.26 the syntax of the configuration file has
- changed. In particular:
-
- itemization(
- it() The keyword tt(maxconnections) is now used instead of
- tt(maxclients);
- it() The keyword tt(connectiontimeout) is now used instead of
- tt(sessiontimeout).)
-
- Therefore when converting configuration files to the new syntax,
- the above keywords must be changed. (The reason for these changes
- is that 0.26 introduces em(sticky HTTP sessions) that span
- multiple TCP connections, and the term
- em(session) is used strictly in that sense -- and no longer for a
- TCP connection.)
-
-subsect(Porting issues for pre-1.08 installations)
-
- As of version 1.08, the following directives no longer are
- supported:
-
- itemization(
- it() tt(insertstickycookie) was replaced by the more generic
- directive tt(addclientheader). E.g., instead of nl()
- tt(insertstickycookie "XRID=100; Path=/";) nl()
- the syntax is now nl()
- tt(addclientheader "Set-Cookie: XRID=100; Path=/";)
-
- it() tt(insertrealip) was replaced by the more generic
- directive tt(setserverheader). E.g., instead of nl()
- tt(insertrealip on;) nl()
- the syntax is now nl()
- tt(setserverheader "XR-Real-IP: %r";) nl()
- This incidentally also makes it possible to change the header
- name (here: tt(XR-Real-IP)).)
-
-\ No newline at end of file
diff --git a/doc/benchmarking.yo b/doc/main/benchmarking.yo
diff --git a/doc/main/compiling.yo b/doc/main/compiling.yo
@@ -0,0 +1,170 @@
+subsect(Prerequisites)
+
+The creation of crossroads requires:
+
+itemization(
+ it() Standard Unix tools, such as tt(sed), tt(awk), tt(Perl)
+ (5.00 or better);
+
+ it() A POSIX-compliant C compiler;
+
+ it() Support for SYSV IPC, networking and so on.
+)
+
+Basically a Linux or Apple MacOSX box will do nicely. To compile and install
+crossroads, follow these steps.
+
+
+subsect(Compiling and installing)
+
+itemization(
+ it() Obtain the source distribution. It can be found on
+ lurl(http://crossroads.e-tunity.com). The distribution comes as an
+ archive tt(crossroads-)em(type)tt(.tar.gz), where em(type) is
+ tt(stable) or tt(devel).
+
+ it() Unpack the archive in a sources directory using tt(tar
+ xzf crossroads-)em(X.YY)tt(.tar.gz). The contents spill into a
+ subdirectory tt(crossroads-)em(X.YY/).
+
+ it() Change-dir into the directory.
+
+ it() Next, edit tt(etc/Makefile.def) and verify that all
+ compilation settings are to your likings. The settings are
+ explained in the file. bf(Note that) the default distribution
+ of tt(Makefile.def) is suited for Linux or Apple MacOSX
+ systems. On other Unices, or on non-Unix systems, you must
+ particularly pay attention to tt(SET_PROC_TITLE_BY...). When
+ in doubt, set the tt(SET_PROC_TITLE...)
+ settings to 0. Crossroads will work nevertheless, but it won't show
+ nice titles in tt(ps) listings. Also there's a macro
+ tt(EXTRA_LIBS) to add linkage flags (an example for a Solaris
+ build is included).
+
+ it() Now crossroads is ready for compilation. Do a tt(make
+ local) followed by tt(make install). The latter step may have
+ to be done by the user tt(root) if the tt(BINDIR) setting of
+ tt(etc/Makefile.def) points to a root-owned directory.
+
+ it() The manual pages on the basic usage of Crossroads and on
+ the layout of the configuration file are installed as
+ well, if a suitable tt(man/) directory is present under the
+ installation prefix directory. If these pages are not
+ installed, then you can always copy tt(doc/crossroads.1) to a
+ suitable tt(man/man1/) directory, and
+ tt(doc/crossroads.conf.7) to a suitable tt(man/man7/)
+ directory. After this, tt(man crossroads) and tt(man
+ crossroads.conf) would show the appropriate manual pages.
+
+ it() The full documentation doesn't install in this process. If you
+ want to install the documentation, then proceed as follows:
+
+ itemization(
+ it() Optionally, tt(cp doc/crossroads.html)
+ em(htmldirectory/); where em(htmldirectory) is the destination
+ directory for your HTML manuals;
+
+ it() Optionally, tt(cp doc/crossroads.pdf)
+ em(pdfdirectory/); where em(pdfdirectory) is the
+ destination directory for your PDF manuals.)
+
+)
+
+
+subsect(Configuring crossroads)
+
+Now that the binary is available on your system, you need to create a
+suitable DEFAULTCONF(). Use this manual or the output of
+tt(crossroads samplconf) to get started.
+
+Once you have the configuration ready, start crossroads with
+tt(crossroads start). Test the availability of your services and back
+ends. Monitor how crossroads is doing with:
+
+itemization(
+ it() In one terminal, run the script:
+ verb(\
+while [ 1 ] ; do
+ tput clear
+ crossroads status
+ sleep 3
+done)
+
+ bf(Note) that depending on your system you might need
+ tt(sleep 3s), i.e., with an tt(s) appended.
+
+ it() In another terminal, run:
+ verb(\
+while [ 1 ] ; do
+ tput clear
+ ps ax | grep crossroads | grep -v grep
+ sleep 3
+done)
+
+ bf(Note) that depending on your system you might need
+ tt(ps -ef) instead of tt(ps ax).
+
+ it() In yet another terminal, run tt(tail -f
+ /var/log/messages) (supply the appropriate system log file if
+ tt(/var/log/messages) doesn't work for you).)
+
+Now thoroughly test the availability of your back ends through
+crossroads. The status display will show an updated view of which back
+ends are selected and how busy they are. The process list will show
+which crossroads daemons are running. Finally, the tailing of
+tt(/var/log/messages) shows what's going on -- especially if you have
+tt(verbosity true) statements in the configuration.
+
+
+subsect(A boot script)
+
+Finally, you may want to create a boot-time startup script. The exact
+procedure depends on the used Unix flavor.
+
+subsubsect(SysV Style Startup)
+
+On SysV style systems, there's a startup script directory
+tt(/etc/init.d) where bootscripts for all utilities are located.
+You may have the tt(chkconfig) utility to automate the task of
+inserting scripts into the boot sequence, but
+otherwise the steps will resemble the following.
+
+itemization(
+ it() Create a script tt(crossroads) in tt(/etc/init.d) similar to the
+ following:
+
+verb(\
+#!/bin/sh
+/usr/local/bin/crossroads -v $@)
+
+ The stated directory tt(/usr/local/bin) must correspond with
+ the installation path. The flag tt(-v) causes the startup to
+ be more 'verbose'. However, once daemonized, the verbosity is
+ controlled by the appropriate statements in the configuration.
+
+ it() Determine your 'runlevel': usually 3 when your system is
+ running in text-mode only, or 5 when you are using a graphical
+ interface. If your runlevel is 3, then:
+
+verb(\
+root> cd /etc/rc.d/rc3.d
+root> ln -s /etc/init.d/crossroads S99crossroads
+root> ln -s /etc/init.d/crossroads K99crossroads)
+
+ This creates startup (tt(S*)) and stop (tt(K*)) links that
+ will be run when the system enters or leaves a given runlevel.
+
+ If your runlevel is 5, then the right tt(cd) command is to
+ tt(/etc/rc.d/rc5.d). Alternatively, you can create the
+ symlinks in both runlevel directories.)
+
+subsubsect(BSD Style Startup)
+
+On BSD style systems, daemons are booted directly from tt(/etc/rc) and
+related scripts. Incase you have a file tt(/etc/rc.local), edit it,
+and add the statement:
+
+verb(/usr/local/bin/crossroads start)
+
+If your BSD system lacks tt(/etc/rc.local), then you may need to start
+Crossroads from tt(/etc/rc). Your mileage may vary.
diff --git a/doc/main/conf/addclientheader.yo b/doc/main/conf/addclientheader.yo
@@ -0,0 +1,142 @@
+conf(HTTP Header Modification Directives)
+ (Crossroads understands the following
+ header modification directives: tt(addclientheader),
+ tt(appendclientheader), tt(setclientheader), tt(addserverheader),
+ tt(appendserverheader), tt(setserverheader).
+
+ The directive names always consist of
+ em(Action)em(Destination)tt(header), where:
+
+ itemization(
+ it() The action is tt(add), tt(append) or tt(insert).
+
+ itemization(
+ it() Action tt(add) adds a header, even when headers with
+ the same name already are present in an HTTP
+ message. Adding headers is useful for e.g. tt(Set-Cookie)
+ headers; a message may contain several of such headers.
+
+ it() Action tt(append) adds a header if it isn't present
+ yet in an HTTP message. If such a header is already
+ present, then the value is appended to the pre-existing
+ header. This is useful for e.g. tt(Via) headers. Imagine
+ an HTTP message with a header tt(Via: someproxy). Then the
+ directive tt(appendclientheader "Via: crossroads") will
+ rewrite the header to tt(Via: someproxy; crossroads).
+
+ it() Action tt(set) overwrites headers with the same
+ name; or adds a new header if no pre-existing is found.
+ This is useful for e.g. tt(Host) headers.)
+
+ it() The destination is one of tt(client) or tt(server). When
+ the destination is tt(server), then Crossroads will apply such
+ directives to HTTP messages that originate from the browser
+ and are being forwarded to back ends. When the destination is
+ tt(client), then Crossroads will apply such directives to
+ backend responses that are shuttled to the browser.)
+
+ The format of the directives is e.g. tt(addclientheader
+ "X-Processed-By: Crossroads"). The directives expect one
+ argument; a string, consisting of a header name, a colon, and a
+ header value. As usual, the directive must end with a semicolon.
+
+ The header value may contain one of the following formatting
+ directives:
+
+ INCLUDEFILE(formattable.yo)
+
+ The following examples show common uses of header modifications.
+
+ description(
+ dit(Enforcing session stickiness:) By combining
+ tt(stickycookie) and tt(addclientheader), HTTP session
+ stickiness is enforced. Consider the following configuration:
+
+ verb(\
+service ... {
+ ...
+ backend one {
+ ...
+ addclientheader "Set-Cookie: BalancerID=first; path=/";
+ stickycookie "BalancerID=first";
+ }
+ backend two {
+ ...
+ addclientheader "Set-Cookie: BalancerID=second; path=/";
+ stickycookie "BalancerID=second";
+ }
+})
+
+ The first request of an HTTP session is balanced to either
+ backend tt(one) or tt(two). The server response is enriched
+ using tt(addclientheader) with an appropriate cookie. A
+ subsequent request from the same browser now has that cookie
+ in place; and is therefore sent to the same back end where the
+ its predecessors went.
+
+ dit(Hiding the server software version:) Many servers
+ (e.g. Apache) advertize their version, as in tt(Server: Apache
+ 1.27). This potentially provides information to attackers. The
+ following configuration hides such information:
+
+ verb(\
+service ... {
+ ...
+ backend one {
+ ...
+ setclientheader "Server: WWW-Server";
+ }
+})
+
+ dit(Informing the server of the clients' IP address:) Since
+ Crossroads sits 'in the middle' between a client and a back
+ end, the back end perceives Crossroads as its client. The
+ following sends the true clients' IP address to the server, in
+ a header tt(X-Real-IP):
+
+ verb(\
+service ... {
+ ...
+ backend one {
+ ...
+ setserverheader "X-Real-IP: %r";
+ }
+})
+
+ dit(Keep-Alive Downgrading:) The directives
+ tt(setclientheader) and tt(setserverheader) also play a key
+ role in downgrading Keep-Alive connections to
+ 'single-shot'. E.g., the following configuration makes sure
+ that no Keep-Alive connections occur.
+
+ verb(\
+service ... {
+ ...
+ backend one {
+ ...
+ setserverheader "Connection: close";
+ setclientheader "Connection: close";
+ }
+})))
+ (itemization(
+ it() tt(addclientheader) em(Headername: headervalue) to add a
+ header in the traffic towards the client, even when another
+ header em(Headername) exists;
+ it() tt(appendclientheader) em(Headername: headervalue) to
+ append em(headervalue) to an existing header em(Headername)
+ in the traffic towards the client,
+ or to add the whole header alltogether;
+ it() tt(setclientheader) em(Headername: headervalue) to
+ overwrite an existing header in the traffic towards the
+ client, or to add such a header;
+ it() tt(addserverheader) em(Headername: headervalue) to add a
+ header in the traffic towards the server, even when another
+ header em(Headername) exists;
+ it() tt(appendserverheader) em(Headername: headervalue) to
+ append em(headervalue) to an existing header em(Headername)
+ in the traffic towards the server,
+ or to add the whole header alltogether;
+ it() tt(setserverheader) em(Headername: headervalue) to
+ overwrite an existing header in the traffic towards the
+ server, or to add such a header.))
+ (There is no default.)
diff --git a/doc/main/conf/allow.yo b/doc/main/conf/allow.yo
@@ -0,0 +1,65 @@
+conf(allow* and deny* - Allowing or denying connections)
+ (Crossroads can allow or deny
+ connections based on the IP address of a client. There are four
+ directives that are relevant: tt(allowfrom), tt(allowfile),
+ tt(denyfrom) and tt(denyfile). When using tt(allowfrom) and
+ tt(denyfrom) then the IP addresses to allow or deny connections are
+ stated in DEFAULTCONF().
+
+ When tt(allow*) directives are used, then all connections are denied
+ unless they match the stated allowed IP's. When tt(deny*) directives
+ are used, then all connections are allowed unless they match the
+ stated disallowed IP's. When denying and allowing is both used,
+ then the Crossroads checks the deny list first.
+
+ The statements tt(allowfrom) and tt(denyfrom) are followed by a
+ list of filter specifications. The statements tt(allowfile) and
+ tt(denyfile) are followed by a filename; Crossroads will read
+ filter specifications from those external files. In both cases,
+ Crossroads obtains filter specifications and places them in its
+ lists of allowed or denied IP addresses. The difference between
+ specifying filters in DEFAULTCONF() or in external
+ files, is that Crossroads will reload the external files when it
+ receives signal 1 (tt(SIGHUP)), as in tt(killall -1 crossroads).
+
+ The filter specifications must obey the following syntax: it
+ consists of up to
+ four numbers ranging from 0 to 255 and separated by a decimal
+ sign. Optionally a slash follows, with a bitmask which is also a
+ decimal number.
+
+ This is probably best explained by a few examples:
+
+ itemization(
+ it() tt(allowfrom 10/8;) will allow connections from
+ tt(10.*.*.*) (a full Class A network). The mask tt(/8) means
+ that the first 8 bits of the number (ie., only the tt(10)) are
+ significant. On the last 3 positions of the IP address, all
+ numbers are allowed. Given this directive, client connections
+ from e.g. 10.1.1.1 and 10.2.3.4 will be allowed.
+
+ it() tt(allowfrom 10.3/16;) will allow all IP addresses that
+ start with tt(10.3).
+
+ it() tt(allowfrom 10.3.1/16;) is the same as above. The third
+ byte of the IP address is superfluous because the netmask
+ specifies that only the first 16 bits (2 numbers) are taken
+ into account.
+
+ it() tt(allowfrom 10.3.1.15;) allows traffic from only the
+ specified IP address. There is no bitmask; all four numbers
+ are relevant.
+
+ it() tt(allowfrom 10.3.1.15 10.2/16;) allows traffic from one
+ IP address tt(10.3.1.15) or from a complete Class B network
+ tt(10.2.*.*)
+
+ it() tt(allowfile /tmp/myfile.txt;) in combination with a file
+ tt(/tmp/myfile.txt), with the contents tt(10.3.1.15 10.2/16),
+ is the same as above.))
+ (itemization(
+ it() tt(allowfrom) em(filter-specificication(s))
+ it() tt(denyfrom) em(filter-specificication(s))
+ it() tt(allowfile) em(filename)
+ it() tt(denyfile) em(filename)))
+ (In absence of these statements, all client IP's are accepted.)
diff --git a/doc/conf/backlog.yo b/doc/main/conf/backlog.yo
diff --git a/doc/conf/bindto.yo b/doc/main/conf/bindto.yo
diff --git a/doc/conf/connectiontimeout.yo b/doc/main/conf/connectiontimeout.yo
diff --git a/doc/conf/decay.yo b/doc/main/conf/decay.yo
diff --git a/doc/main/conf/dispatchmode.yo b/doc/main/conf/dispatchmode.yo
@@ -0,0 +1,84 @@
+conf(dispatchmode - How are back ends selected)
+ (The dispatch mode controls how crossroads selects a back end from
+ a list of active back ends. The below text shows the bare
+ syntax. See section ref(howselected) for a textual explanation.
+
+ The settings can be:
+
+ itemization(
+ it() tt(dispatchmode roundrobin): Simply the 'next in line' is
+ chosen. E.g, when 3 back ends are active, then the usage
+ series is 1, 2, 3, 1, 2, 3, and so on.
+
+ Roundrobin dispatching is the default method, when no
+ tt(dispatchmode) statement occurs.
+
+ it() tt(dispatchmode random): Random selection. Probably only
+ for stress testing, though when used with weights (see below)
+ it is a good distributor of new connections too.
+
+ it() tt(dispatchmode bysize [ over) em(connections) tt(]):
+ The next back end is the one
+ that has transferred the least number of bytes. This
+ selection mechanism assumes that the more bytes, the heavier
+ the load.
+
+ The modifier tt(over) em(connections) is optional. (The square
+ brackets shown above are not part of the statement but
+ indicate optionality.) When given,
+ the load is computed as an average of the last stated number of
+ connections. When this modifier is absent, then the load is
+ computed over all connections since startup.
+
+ it() tt(dispatchmode byduration [ over) em(connections) tt(]):
+ The next back end is the one
+ that served connections for the shortest time. This mechanism
+ assumes that the longer the connection, the heavier the load.
+
+ it() tt(dispatchmode byconnections): The next back end is the one
+ with the least active connections. This mechanism assumes that
+ each connection to a back end represents load. It is usable
+ for e.g. database connections.
+
+ it() tt(dispatchmode byorder): The first back end is selected
+ every time, unless it's unavailable. In that case the second
+ is taken, and so on.
+
+ it() tt(dispatchmode byclientip): The client's IP address is
+ 'hashed' into a number, which is used to pick a back end. The
+ same client IP address will therefore always be dispatched to
+ the same back end. When the back end of choice is down,
+ tt(dispatchmode byconnections) is used.
+
+ it() tt(dispatchmode externalhandler) em(program arguments):
+ This is a special mode, where an external program is delegated
+ the responsibility to say which back end should be used
+ next. In this case, Crossroads will call the external program,
+ and this will of course be slower than one of the 'built-in'
+ dispatch modes. However, this is the ultimate escape when
+ custom-made dispatch modes are needed.
+
+ The dispatch mode that uses an tt(externalhandler) is
+ discussed separately in section ref(externalhandler).)
+
+ The selection algorithm is only used when clients are serviced that
+ aren't part of a sticky HTTP session. This is the case during:
+
+ itemization(
+ it() all client requests of a service type tt(any);
+ it() new sessions of a service type tt(http).)
+
+ When type tt(http) is in effect and a session is underway, then the
+ previously used back end is always selected -- regardless of
+ dispatching mode.
+
+ Your 'right' dispatch mode will depend on the type of service. Given
+ the fact that crossroads doesn't know (and doesn't care) how to
+ estimate load from a network traffic stream, you have to choose an
+ appropriate dispatch mode to optimize load balancing. In most cases,
+ tt(roundrobin) or tt(byconnections) will do the job just fine.)
+ (tt(dispatchmode) em(mode) (see above for the modes), optionally
+ followed by tt(over) em(number), or when the em(mode) is
+ tt(externalhandler), followed by em(program).)
+ (tt(roundrobin))
+
diff --git a/doc/conf/maxconnections.yo b/doc/main/conf/maxconnections.yo
diff --git a/doc/main/conf/onfailure.yo b/doc/main/conf/onfailure.yo
@@ -0,0 +1,10 @@
+conf(onfailure and onsuccess - Action Hooks)
+ (As special 'hooks' for actions, two triggers
+ are available: tt(onfailure) and tt(onsuccess). The argument to
+ the triggers is a system command that is executed when a connection
+ with the back end either fails or succeeds.)
+ (itemization(
+ it() tt(onfailure) em(commandline)
+ it() tt(onsuccess) em(commandline)))
+ (There is no default. Normally no external programs are run upon
+ success or failure of a back end.)
diff --git a/doc/main/conf/onhooks.yo b/doc/main/conf/onhooks.yo
@@ -0,0 +1,25 @@
+conf(onstart, onend, onfail - Action Hooks)
+ (The three directives tt(onstart), tt(onend) and tt(onfail) can be
+ specified to start system commands (external programs) when a
+ connection to a back end starts, fails or ends:
+ itemization(
+ it() tt(onstart) commands will be run when Crossroads
+ successfully connects to a back end, and starts servicing;
+ it() tt(onend) commands will be run when a (previously
+ established) connection stops;
+ it() tt(onfail) commands will be run when Crossroads tries to
+ contact a back end to serve a client, but the back end can't
+ be reached.)
+
+ The format is always tt(on)em(type) em(command). The em(command)
+ is an external program, optionally followed by arguments. The
+ command is expanded according to the following table:
+
+ INCLUDEFILE(formattable))
+ (itemization(
+ it() tt(onstart) em(commandline)
+ it() tt(onend) em(commandline)
+ it() tt(onfail) em(commandline)
+ it() tt(onsuccess) em(commandline)))
+ (There is no default. Normally no external programs are run upon
+ connection, success or failure of a back end.)
diff --git a/doc/conf/port.yo b/doc/main/conf/port.yo
diff --git a/doc/conf/retries.yo b/doc/main/conf/retries.yo
diff --git a/doc/conf/revivinginterval.yo b/doc/main/conf/revivinginterval.yo
diff --git a/doc/main/conf/server.yo b/doc/main/conf/server.yo
@@ -0,0 +1,15 @@
+conf(server - Specifying the back end address)
+ (Each back end must be identified by the network name
+ (server name) where it is located. For example: tt(server
+ 10.1.1.23), or tt(server web.mydomain.org). A TCP port specifier
+ can follow the server name, as in tt(server
+ web.mydomain.org:80). bf(Note that) resolved host names are
+ cached by Crossroads; there is no performance advantage in
+ specifying decimal addresses. (The DNS cache timeout can be
+ controlled using the invocation flag tt(-d).))
+ (itemization(
+ it() tt(server) em(servername), where em(servername) is a
+ network name or IP address. In this case a separate tt(port)
+ statement must be used to define the TCP port;
+ it() tt(server) em(servername:port)))
+ (There is no default. This is a required setting.)
diff --git a/doc/main/conf/shmkey.yo b/doc/main/conf/shmkey.yo
@@ -0,0 +1,17 @@
+conf(shmkey - Shared Memory Access)
+ (Different Crossroads
+ invocations must 'know' of each others activity. E.g, tt(crossroad
+ status) must be able to get to the actual state information of all
+ running services. This is internally implemented through shared
+ memory, which is reserved using a key.
+
+ Normally crossroads will supply a shared memory key, based on the
+ service name. In situations where this conflicts with existing
+ keys (of other programs, having their own keys), you may supply a
+ chosen value.
+
+ The actual key value doesn't matter much, as long as it's unique
+ and as long as each invocation of crossroads uses it.)
+ (tt(shmkey) em(number))
+ (0, which means that crossroads will 'guess' its
+ own key, based on the service name.)
+\ No newline at end of file
diff --git a/doc/conf/stickycookie.yo b/doc/main/conf/stickycookie.yo
diff --git a/doc/main/conf/trafficlog.yo b/doc/main/conf/trafficlog.yo
@@ -0,0 +1,17 @@
+conf(trafficlog and throughputlog - Debugging and Performance Aids)
+ (Two directives are available
+ to log network traffic to files. They are tt(trafficlog) and
+ tt(throughputlog).
+
+ The tt(trafficlog) statement causes all traffic to be logged in
+ hexadecimal format. Each line is prefixed by tt(B) or tt(C),
+ depending on whether the information was received from the back
+ end or from the client.
+
+ The tt(throughputlog) statement writes shorthand transmissions to
+ its log, accompanied by timings.)
+ (itemization(
+ it() tt(trafficlog) em(filename)
+ it() tt(throughputlog) em(filename)))
+ (none)
+
diff --git a/doc/conf/type.yo b/doc/main/conf/type.yo
diff --git a/doc/main/conf/useraccount.yo b/doc/main/conf/useraccount.yo
@@ -0,0 +1,14 @@
+conf(useraccount - Limiting the effective ID of external processes)
+ (Using the directive tt(useraccount), the effective user and group
+ ID can be restricted. This comes into effect when Crossroads runs
+ external commands, such as:
+ itemization(
+ it() Hooks for tt(onstart), tt(onend) or tt(onfail);
+ it() External dispatchers, when tt(dispatchmode
+ externalhandler) is in effect.)
+ Once a user name for external commands is specified, Crossroads
+ assumes the associated user ID and group ID before running those
+ commands.)
+ (tt(useraccount) em(username))
+ (None; when unspecified, external commands are run with the
+ ID that was in effect when Crossroads was started.)
+\ No newline at end of file
diff --git a/doc/main/conf/verbose-backend.yo b/doc/main/conf/verbose-backend.yo
@@ -0,0 +1,10 @@
+conf(verbosity - Controlling verbosity at the back end level)
+ (Similar to tt(service) specifications, a
+ tt(backend) can have its own verbosity (tt(on) or tt(off)). When
+ tt(on), traffic to and fro this back end is reported.)
+ (itemization(
+ it() tt(verbosity) em(setting), or
+ it() tt(verbose) em(setting), where em(setting) is tt(true),
+ tt(yes) or tt(on), or tt(false), tt(no), tt(off) to turn it
+ off.))
+ (tt(off))
diff --git a/doc/conf/verbose.yo b/doc/main/conf/verbose.yo
diff --git a/doc/conf/weight.yo b/doc/main/conf/weight.yo
diff --git a/doc/main/config.yo b/doc/main/config.yo
@@ -0,0 +1,175 @@
+The configuration that crossroads uses is normally stored in the file
+DEFAULTCONF(). This location can be overruled using the
+command line flag tt(-c).
+
+This section explains the syntax of the configuration file, and what
+all settings do.
+
+confsect(General language elements)
+
+This section describes the general elements of the crossroads
+configuration language.
+
+
+confsubsect(Empty lines and comments)
+
+Empty lines are of course allowed in the
+configuration. Crossroads recognizes three formats of comment:
+
+itemization(
+ it() C-style, between tt(/*) and tt(*/),
+ it() C++-style, starting with tt(//) and ending with the end
+ of the text line.)
+
+Simply choose your favorite editor and use the comment that 'looks
+best'.footnote(I favor C or C++ comment. My favorite editor em(emacs)
+can be put in tt(cmode) and nicely highlight what's comment and what's
+not. And as a bonus it will auto-indent the configuration!)
+
+confsubsect(Preprocessor directives)
+
+Similar to bf(C) or bf(C++), the Crossroads grammar knows tt(#include)
+and tt(#define). Both directives must start at the first column of the
+line (ie., the tt(#) sign must occur at the leftmost line
+position).
+
+itemization(
+ it() tt(#include) tt(")em(filename)tt(") includes the stated file
+ name at the place of the statement.
+ it() tt(#define) em(SYMBOL) em(DEFINITION) defines em(SYMBOL)
+ as placeholder for em(DEFINITION).)
+
+For example, one may use the configuration:
+
+verb(\
+#define SERVICEPORT 80
+service web {
+ port SERVICEPORT;
+ .
+ . /* More statements follow here */
+ .
+})
+
+The tt(port) statement is then read as tt(port 80).
+
+
+confsubsect(Keywords, numbers, identifiers, generic strings)
+
+In a configuration file, statements are identified by em(keywords),
+such as tt(service), tt(verbosity). These are reserved words.
+
+Many keywords require an em(identifier) as the argument. E.g, a
+service has a unique name, which must start with a letter or
+underscore, followed by zero or more letters, underscores, or
+digits. Therefore, in the statement tt(service myservice), the keyword is
+tt(service) and the identifier is tt(myservice).
+
+Other keywords require a numeric argument. Crossroads knows only
+non-negative integer numbers, as in tt(port 8000). Here, tt(port) is
+the keyword and tt(8000) is the number.
+
+Yet other keywords require 'generic strings', such as hostname
+specifications or system commands. Such generic strings contain any
+characters (including white space) up to the terminating statement
+character tt(;). If a string must contain a semicolon, then it must
+be enclosed in single or double quotes:
+
+itemization(
+ it() tt(This is a string;) is a string that starts at tt(T)
+ and ends with tt(g)
+ it() tt("This is a string";) is the same, the double quotes
+ are not necessary
+ it() tt("This is ; a string";) has double quotes to protect
+ the inner ;)
+
+Finally, an argument can be a 'boolean' value. Crossroads knows
+tt(true), tt(false), tt(yes), tt(no), tt(on), tt(off). The keywords
+tt(true), tt(yes) and tt(on) all mean the same and can be used
+interchangeably; as can the keywords tt(false), tt(no) and tt(off).
+
+
+confsect(Service definitions) label(servicedef)
+
+Service definitions are blocks in the configuration file that
+state what is for each service. A service definition starts with
+tt(service), followed by a unique identifier, and by statements in
+tt({) and tt(}). For example:
+
+verb(\
+// Definition of service 'www':
+service www {
+ ...
+ ... // statements that define the
+ ... // service named 'www'
+ ...
+})
+
+The configuration file can contain many service blocks, as long as the
+identifying names differ. The following list shows possible
+statements. Each statement must end with a semicolon, except for the
+tt(backend) statement, which has is own block (more on this later).
+
+redef(conf)(4)(\
+ confsubsect(ARG1) label(confARG1)
+ startdit()
+ dit(Description:) ARG2
+ dit(Syntax:) ARG3
+ dit(Default:) ARG4
+ enddit())
+
+
+includefile(conf/type)
+includefile(conf/port)
+includefile(conf/bindto)
+includefile(conf/verbose)
+includefile(conf/dispatchmode)
+includefile(conf/revivinginterval)
+includefile(conf/maxconnections)
+includefile(conf/backlog)
+includefile(conf/shmkey)
+includefile(conf/allow)
+includefile(conf/useraccount)
+
+
+confsect(Backend definitions)
+
+Inside the service definitions as are described in the previous
+section, em(backend definitions) must also occur. Backend definitions
+are started by the keyword tt(backend), followed by an identifier
+(the back end name) , and statements inside tt({) and tt(}):
+
+verb(\
+service myservice {
+ ...
+ ... // statements that define the
+ ... // service named 'myservice'
+ ...
+
+ backend mybackend {
+ ...
+ ... // statements that define the
+ ... // backend named 'mybackend'
+ ...
+ }
+})
+
+Each service definition must have at least one backend
+definition. There may be more (and probably will, if you want
+balancing and fail over) as long as the backend names differ.
+The statements in the backend definition blocks are described in the
+following sections.
+
+Some directives (tt(stickycookie) etc.) only have effect when
+Crossroads treats the network traffic as a stream of HTTP messages;
+i.e., when the service is declared with tt(type http). Incase of
+tt(type any), the HTTP-specific directives have no effect.
+
+includefile(conf/server.yo)
+includefile(conf/verbose-backend.yo)
+includefile(conf/retries.yo)
+includefile(conf/weight)
+includefile(conf/decay)
+includefile(conf/onhooks)
+includefile(conf/trafficlog)
+includefile(conf/stickycookie)
+includefile(conf/addclientheader)
diff --git a/doc/main/crossroads.yo b/doc/main/crossroads.yo
@@ -0,0 +1,42 @@
+includefile(../crossroads-defs)
+tocclearpage()
+titleclearpage()
+includefile(defs)
+abstract(Crossroads is a load balance and fail over utility for TCP
+ based services. It is a daemon program running in user
+ space, and features extensive configurability, polling of
+ back ends using 'wakeup calls', detailed status reporting,
+ 'hooks' for special actions when backend calls fail, and much
+ more. Crossroads is service-independent: it is usable for
+ HTTP/HTTPS, SSH, SMTP, DNS, etc. In the case of HTTP
+ balancing, Crossroads can modify HTTP headers, e.g. to
+ provide 'session stickiness' for back-end processes that need
+ sessions, but aren't session-aware of other back-ends.)
+article(Crossroads VER())
+ (AUTHORNAME() nl()
+ Maintained by MAINTAINERNAME() (MAINTAINEREMAIL()))
+ (YEARS(), ff.)
+
+sect(Introduction)
+includefile(intro)
+
+sect(Installation for the impatient)
+includefile(impatient)
+
+sect(Using Crossroads)
+includefile(using)
+
+redef(confsect)(1)(subsect(ARG1))
+redef(confsubsect)(1)(subsubsect(ARG1))
+sect(The configuration)
+includefile(config)
+
+sect(Tips, Tricks and Random Remarks)
+includefile(tips)
+
+sect(Benchmarking)
+includefile(benchmarking)
+
+sect(Compiling and Installing) label(installation)
+includefile(compiling)
+
diff --git a/doc/defs.yo b/doc/main/defs.yo
diff --git a/doc/formattable.yo b/doc/main/formattable.yo
diff --git a/doc/main/impatient.yo b/doc/main/impatient.yo
@@ -0,0 +1,65 @@
+
+For the impatient, here's the very-quick-but-very-superficial recipy
+for getting crossroads up and running:
+
+itemization(
+
+ it() If you don't have SVN or don't want to use it:
+
+ itemization(
+ it() Obtain the crossroads source archive at
+ lurl(http://crossroads.e-tunity.com).
+
+ it() Change-dir to a 'sources' directory on your system and
+ unpack the archive.
+
+ it() Change-dir into the create directory tt(crossroads/).)
+
+ it() If you have SVN and want to go for the newest snapshot:
+
+ itemization(
+ it() Get the latest sources and snapshots using SVN from nl()
+ tt(svn://svn.e-tunity.com/crossroads).
+
+ it() You'll find the newest alpha version under
+ tt(crossroads/trunk) and the stable versions under
+ tt(crossroads/tags),
+ e.g. tt(crossroads/tags/release-1.00).
+
+ it() Choose which you want to use: the latest stable
+ release, or the bleeding edge alpha? In the former case,
+ change-dir to tt(crossroads/tags/release-)em(X.YY), where
+ em(X.YY) is a release ID. In the latter case, change-dir to
+ tt(crossroads/trunk).)
+
+ it() Type tt(make install). This installs the crossroads
+ binary into tt(/usr/local/bin/). If the compilation doesn't
+ work on your system, check tt(etc/Makefile.def) for hints.
+
+ it() Create a file DEFAULTCONF(). In it state
+ something like:
+
+ verb(\
+service www {
+ port 80;
+ revivinginterval 15;
+ backend one {
+ server 10.1.1.100:80;
+ }
+ backend two {
+ server 10.1.1.101:80;
+ }
+})
+
+ That's off course assuming that you want to balance HTTP on
+ port 80 to two back ends at 10.1.1.100 and 10.1.1.101.
+
+ it() Type tt(crossroads start).
+
+ it() Surf to the machine where crossroads is running. You will
+ see the pages served by the back ends 10.1.1.100 or
+ 10.1.1.101.
+
+ it() To monitor the status of crossroads, type tt(crossroads
+ status).
+)
diff --git a/doc/main/intro.yo b/doc/main/intro.yo
@@ -0,0 +1,256 @@
+Crossroads is a daemon that basically accepts TCP connections
+at preconfigured ports, and given a list of 'back ends'
+distributes each incoming connection to one of the back ends,
+so that a client request is
+served. Additionally, crossroads maintains an internal
+administration of the back end connectivity: if a back end isn't
+usable, then the client request is handled using another back
+end. Crossroads will then periodically check whether a previously not
+usable back end has come to life yet. Also, crossroads can select
+back ends by estimating the load, so that balancing is achieved.
+
+Using this approach, crossroads serves as load balancer and fail over
+utility. Crossroads will very likely not be as reliable as
+hardware based balancers, since it always will require a server to
+run on. This server, in turn, may become a new Single Point of
+Failure (SPOS). However, in situations where cost efficiency is an issue,
+crossroads may be a good choice. Furthermore, crossroads can be
+deployed in situations where a hardware based balancing already
+exists and augmenting service reliability is needed. Or, crossroads may be
+run off a diskless system, which again improves reliability of the
+underlying hardware.
+
+This document describes how to use crossroads, how to configure it
+in order to increase the reliability of your systems, and how to
+compile the program from its sources. whenhtml(This document is
+also available in url(PDF)(crossroads.pdf) format.)
+
+subsect(Obtaining Crossroads)
+
+As quick reference, here are some important URL's for Crossroads:
+
+itemization(
+ it() lurl(http:/crossroads.e-tunity.com) is the site that serves
+ Crossroads. You can browse this at leisure
+ for documentation, sources, and so on.
+
+ it() lurl(http://freshmeat.net/projects/crossr) is the
+ Freshmeat announcement page.
+
+ it() lurl(svn://svn.e-tunity.com/crossroads) is the SVN
+ repository; anonymous reading (fetching) is allowed. In order
+ to commit changes, mail the author or maintainer for credentials.)
+
+subsect(Reporting bugs)
+
+Crossroads was thoroughly tested and proven to work. However, on
+particular Unices with particular needs and network particularities,
+bugs may occur.
+
+In such cases you can contact the maintainer to ask for
+assistance. Visit the site url(http://crossroads.e-tunity.com)
+(http://crossroads.e-tunity.com) for contact information. In questions
+or bug reports, always include the following:
+
+itemization(
+ it() A description of the bug: when does it occur, what are
+ the circumstances, what is the expected behavior, what is the
+ observed behavior.
+
+ it() The Crossroads configuration (normally
+ DEFAULTCONF())
+
+ it() The version of Crossroads and all compile-time settings,
+ obtained via tt(crossroads -C).)
+
+subsect(Copyright and Disclaimer)
+
+Crossroads is distributed as-is, without assumptions of fitness
+or usability. You are free to use crossroads to your
+liking. It's free, and as with everything that's free: there's
+also no warranty.
+
+You are allowed to make modifications to the source code of
+crossroads, and you are allowed to (re)distribute crossroads, as
+long as you include this text, all sources, and if applicable: all
+your modifications, with each distribution.
+
+While you are allowed to make any and all changes to the sources,
+I would appreciate hearing about them. If the changes concern new
+functionality or bugfixes, then I'll include them in a next
+release, stating full credits. If you want to seriously contribute (to
+which you are heartily encouraged), then mail me and I'll get you
+access to the Crossroads SVN repository, so that you can update and
+commit as you like.
+
+subsect(Terminology)
+
+Throughout this document, the following terms are used: footnote(Many
+more meanings of the terms will exist -- yes, I am aware of that. I'm
+using the terms here in a very strict sense.)
+
+description(
+ dit(A client) is a process that initiates a network connection
+ to get contact with some service.
+ dit(A service) or bf(server process) or bf(listener)
+ is a central application
+ that accepts network connections from clients and sevices
+ them.
+ dit(Back ends) are locations where crossroads looks in
+ order to service its clients. Crossroads sits 'in between'
+ and does its tricks. Therefore, as far as the back ends
+ are concerned, crossroads behaves like a client. As far as
+ the true client is concerned, crossroads behaves like the
+ service. The communication is however transparent: neither
+ client nor back end are aware of the middle position of
+ crossroads.
+ dit(A connection) is a network conversation between client and service,
+ where data are transferred to and fro. As
+ far as crossroads is concerned, success means that a
+ connection can be established without errors on
+ the network level. Crossroads isn't aware of service
+ pecularities. E.g., when a webserver answers tt(HTTP/1.0
+ 500 Server Error) then crossroads will see this as a
+ succesful connection, though the user behind a browser may
+ think otherwise.
+ dit(Back end selection algorithms) are methods by which
+ crossroads determines which back end it will talk to
+ next. Crossroads has a number of built-in algorithms,
+ which may be configured per service.
+ dit(Back end states) are the statusses of each back end that
+ is known to crossroads. A back end may be available,
+ (temporarily) unavailble or truly down. When a back end is
+ temporarily unavailable, then crossroads will periodically
+ check whether the back end has come to life yet (that is,
+ if configured so).
+ dit(A spike) is a sudden increase in activity, leading to
+ extra load on a given service. When crossroads is in
+ effect and when the spike occurs in one connection,
+ then obviously the spike will also appear at one
+ of the back ends. However, crossroads will see the spike
+ and will make sure that a subsequent request goes to an
+ other back end. In contrast, when several connections
+ arrive simultaneously and cause a spike, then crossroads
+ will be able to distribute the connections over several
+ back ends, thereby 'flattening out' the increase.
+ dit(Load balancing) means that incoming client requests are
+ distributed over more than just one back end (which wouldn't be the
+ case if you wouldn't be running crossroads). Enabling load
+ balancing is nothing more than duplicating services over
+ more than one back end, and having something (in this
+ case: crossroads) distribute the requests, so that per
+ back end the load doesn't get too high.
+ dit(An HTTP session) is a series of separate network connections
+ that originate from one browser. E.g., to fill the display
+ with text and images, the browser hits a website several times.
+ An HTTP session may even span several
+ screens. E.g., a website registration dialog may involve 3
+ screens that when called from the same browser,
+ form a logical group of some sort.
+ dit(Headers) or bf(header lines) are specific parts of an HTTP
+ message. Crossroads has directives to add or modify
+ headers that are part of the request that a browser sends
+ to server, or those that are part of the server.
+ dit(Session stickiness) means that when a browser starts an
+ HTTP dialog, the balancer makes sure that it 'sticks' to
+ the same back end (i.e., subsequent requests from the
+ browser are forced to go to the same back end, instead of
+ being balanced to other ones).
+ dit(Back end usage) is measured by crossroads in order to be
+ able to determine back end selection. Crossroads stores
+ information about the number of active connections, the
+ transferred bytes and
+ about the connection duration. These numbers can be used to
+ estimate which back end is the least used -- and
+ therefore, presumably, the best candidate for a new
+ request.
+ dit(Fail over) is almost always used when load balancing is in
+ effect. The distributor of client requests (crossroads of
+ course) can also monitor back ends, so that incase a back
+ end is 'down', it is no longer accessed.
+ dit(Service downtime) normally occurs when a service is
+ switched off. Downtime is obviously avoided when fail over
+ is in effect: a back end can be taken out of service in a
+ controlled manner, without any client noticing it.
+)
+
+subsect(Porting Issues)
+
+This section lists some caveats when converting Crossroads
+configurations to new versions. Given the changes of the syntax of the
+configuration file of Crossroads, existing configuration files may
+need to be made suitable for new versions.
+
+subsubsect(Porting issues for pre-1.43 installations)
+
+ As of version 1.43, the shared memory key calculations are based
+ on a different algorithm. This key is e.g. necessary when starting
+ and stopping Crossroads; in both actions, the key must be computed
+ in the same way.
+
+ Therefore, when upgrading Crossroads, make sure that you stop a
+ running Crossroads daemon using the same binary that started
+ it. After this, install a new binary, and start the daemon using
+ the new binary.
+
+ (Incidentally, this is always a good idea, but especially so when
+ the 'old' binary is pre-1.43 and the 'new' one is post-1.43.)
+
+ Furthermore, shell-style comment is no longer supported as of
+ 1.43. The reason is that 1.43 introduces the hash mark as a
+ preprocessor token (in tt(#include), tt(#define)). Therefore, if
+ your configuration files use shell-style comment, please convert
+ this to bf(C) or bf(C++) style.
+
+subsubsect(Porting issues for pre-1.21 installations)
+
+ As of version 1.21, the event-hook directives tt(onsuccess) and
+ tt(onfailure) no longer exists.
+
+ itemization(
+ it() Please replace tt(onsuccess) by tt(onstart);
+ it() Please replace tt(onfailure) bu tt(onfail);
+ it() Note that there is a new hook tt(onend).)
+
+ The commands that are run via tt(onstart), tt(onend) or tt(onfail)
+ are subject to format expansion; e.g., tt(%1w) is expanded to the
+ weight of the first back end, etc.. See section ref(config) for details.
+
+subsubsect(Porting issues for pre-0.26 installations)
+
+ As of version 0.26 the syntax of the configuration file has
+ changed. In particular:
+
+ itemization(
+ it() The keyword tt(maxconnections) is now used instead of
+ tt(maxclients);
+ it() The keyword tt(connectiontimeout) is now used instead of
+ tt(sessiontimeout).)
+
+ Therefore when converting configuration files to the new syntax,
+ the above keywords must be changed. (The reason for these changes
+ is that 0.26 introduces em(sticky HTTP sessions) that span
+ multiple TCP connections, and the term
+ em(session) is used strictly in that sense -- and no longer for a
+ TCP connection.)
+
+subsubsect(Porting issues for pre-1.08 installations)
+
+ As of version 1.08, the following directives no longer are
+ supported:
+
+ itemization(
+ it() tt(insertstickycookie) was replaced by the more generic
+ directive tt(addclientheader). E.g., instead of nl()
+ tt(insertstickycookie "XRID=100; Path=/";) nl()
+ the syntax is now nl()
+ tt(addclientheader "Set-Cookie: XRID=100; Path=/";)
+
+ it() tt(insertrealip) was replaced by the more generic
+ directive tt(setserverheader). E.g., instead of nl()
+ tt(insertrealip on;) nl()
+ the syntax is now nl()
+ tt(setserverheader "XR-Real-IP: %r";) nl()
+ This incidentally also makes it possible to change the header
+ name (here: tt(XR-Real-IP)).)
+
+\ No newline at end of file
diff --git a/doc/main/tips.yo b/doc/main/tips.yo
@@ -0,0 +1,45 @@
+The following sections elaborate on the directives as described in
+section ref(config) to illustrate how crossroads works and to help you
+achieve the "optimal" balancing configuration.
+
+subsect(How back ends are selected in load balancing) label(howselected)
+includefile(tips/howselected)
+
+subsect(Throttling the number of concurrent connections)
+includefile(tips/throttling)
+
+subsect(Using an external program to dispatch) label(externalhandler)
+includefile(tips/externalhandler)
+
+subsect(TCP Session Stickiness)
+includefile(tips/tcpstickiness)
+
+subsect(HTTP Session Stickiness)
+includefile(tips/httpstickiness)
+
+subsect(Passing the client's IP address)
+includefile(tips/clientip)
+
+subsect(Debugging network traffic)
+includefile(tips/debugging)
+
+subsect(IP filtering: Limiting Access by Client IP Address)
+includefile(tips/ipfiltering)
+
+subsect(Configuration examples)
+includefile(tips/examples)
+
+subsect(Linux and ip_conntrack_max)
+includefile(tips/ipconntrackmax)
+
+subsect(Marking back ends as bad after more than one try)
+includefile(tips/retries)
+
+subsect(Scripting Crossroads' back end availability)
+includefile(tips/scripting)
+
+subsect(Rendering Crossroads' status in a web page) label(xmlstatus)
+includefile(tips/rendering)
+
+subsect(Crossroads and DNS caching)
+includefile(tips/dnscaching)
diff --git a/doc/tips/clientip.yo b/doc/main/tips/clientip.yo
diff --git a/doc/tips/debugging.yo b/doc/main/tips/debugging.yo
diff --git a/doc/main/tips/dnscaching.yo b/doc/main/tips/dnscaching.yo
@@ -0,0 +1,21 @@
+
+The option tt(-d) allows you to control Crossroads' built in DNS
+caching mechanism. Most often you will not need to use this:
+DNS lookups in Crossroads occur only to find back ends; and back ends
+are usually 'near' to the balancer.
+
+You might want or need to use DNS caching if:
+
+itemization(
+ it() Back end servers are specified as hostnames, and not as
+ IP addresses;
+ it() DNS resolving of those host names is perceptibly slow.)
+
+You can test DNS resolving from the command line using e.g. the
+commands tt(nslookup) and tt(host).
+
+If DNS resolving is an issue, then you can specify the flag tt(-d)
+em(nsec) on the command line while invoking Crossroads. This instructs
+Crossroads to use its DNS cache to store results. Each result is
+stored for up to em(nsec) seconds - after that, a new request for the
+back end will lead to a new DNS lookup.
diff --git a/doc/main/tips/examples.yo b/doc/main/tips/examples.yo
@@ -0,0 +1,236 @@
+
+subsubsect(A load balancer for three webserver back ends)
+
+The following configuration example binds crossroads to port 80 of the
+current server, and distributes the load over three back ends. This
+configuration shows most of the possible settings.
+
+verb(\
+service www {
+ /* We don't need session stickyness. */
+ type any;
+
+ /* Port on which we'll listen in this service: required. */
+ port 8000;
+
+ /* What IP address should this service listen? Default is 'any'.
+ * Alternatively you can state an explicit IP address, such as
+ * 127.0.0.1; that would bind the service only to 'localhost'. */
+ bindto any;
+
+ /* Verbose reporting or not. Default is off. */
+ verbosity on;
+
+ /* Dispatching mode, or: How to select a back end for an incoming
+ * request. Possible values:
+ * roundrobin: just the next back end in line
+ * random: like roundrobin, but at random to make things more
+ * confusing. Probably only good for testing.
+ * bysize: The backend that transferred the least nr of bytes
+ * is the next in line. As a modifier you can say e.g.
+ * bysize over 10, meaning that the 10 last connections will
+ * be used to compute the transfer size, instead of all
+ * transfers.
+ * byduration: The backend that was active for the shortest time
+ * is the next in line. As a modifier you can say e.g.
+ * byduration of 10 to compute over the last 10 connections.
+ * byconnections: The back end with the least active connections
+ * is the next ine line.
+ * byorder: The first available back end is always taken.
+ */
+ dispatchmode byduration over 5;
+
+ /* Interval at which we'll check whether a temporarily unavailable
+ * backend has woken up.
+ */
+ revivinginterval 5;
+
+ /* TCP backlog of connections. Default is 0 (no backlog, one
+ * connection may be active).
+ */
+ backlog 5;
+
+ /* For status reporting: a shared memory key. Default is the same
+ * as the port number, OR-ed by a magic number.
+ */
+ shmkey 8000;
+
+ /* This controls when crossroads should consider a connection as
+ * finished even when the TCP sockets weren't closed. This is to
+ * avoid hanging connections that don't do anything. NOTE THAT when
+ * crossroads cuts off a connection due to timeout exceed, this is
+ * not marked as a failure, but as a success. Default is 0: no timeout.
+ */
+ connectiontimeout 300;
+
+ /* The max number of allowed client connections. When present, connections
+ * won't be accepted if the max is about to be exceeded. When
+ * absent, all connections will be accepted, which might be misused
+ * for a DOS attack.
+ */
+ maxconnections 300;
+
+ /* Now let's define a couple of back ends. Number 1: */
+ backend www_backend_1 {
+ /* The server and its port, the minimum configuration. */
+ server httpserver1;
+ port 9010;
+ /* The 'decay' of usage data of this back end. Only relevant
+ * when the whole service has 'dispatchmode bysize' or
+ * 'byduration'. The number is a percentage by which the usage
+ * parameter is decreased upon each connection of an other back
+ * end.
+ */
+ decay 10;
+
+ /* To see what's happening in /var/log/messages: */
+ verbosity on;
+ }
+
+ /* The second one: */
+ backend www_backend_2 {
+ /* Server and port */
+ server httpserver2;
+ port 9011;
+
+ /* Verbosity of reporting when this back end is active */
+ verbosity on;
+
+ /* Decay */
+ decay 10;
+
+ /* This back end is twice as weak as the first one */
+ weight 2;
+
+ /* Event triggers for system commands upon succesful activation
+ * and upon failure.
+ */
+ onsuccess echo 'success on backend 2' | mail root;
+ onfailure echo 'failure on backend 2' | mail root;
+ }
+
+ /* And yet another one.. this time we will dump the traffic
+ * to a trace file. Furthermore we don't want more than 10 concurrent
+ * connections here. Note that there's also a total maxconnections for the
+ * whole service.
+ */
+ backend www_backend_3 {
+ server httpserver3;
+ verbosity on;
+ port 9000;
+ verbosity on;
+ decay 10;
+ trafficlog /tmp/backend.3.log;
+ maxconnections 10;
+ }
+})
+
+subsubsect(An HTTP forwarder when travelling)
+
+As another example, here's my DEFAULTCONF() that I use on my
+Unix laptop. The problem that I face is that I need many HTTP proxy
+configurations (at home, at customers' sites and so on) but I'm too
+lazy to reconfigure browsers all the time.
+
+Here's how it used to be before crossroads:
+
+itemization(
+ it() At home, I would surf through a squid proxy on my local
+ machine. The browser proxy setting is then
+ tt(http://localhost:3128).
+
+ it() Sometimes I start up an SSH tunnel to our offices. The
+ tunnel has a local port 3129, and connects to a squid proxy on
+ our e-tunity server. Hence, the browser proxy is then
+ tt(http://localhost:3129).
+
+ it() At a customer's location I need the proxy
+ tt(http://10.120.34.113:8080), because they have configured it
+ so.
+
+ it() And in yet other instances, I use a HTTP diagnostic tool
+ url(Charles)(http://www.xk72.com/charles)
+ that sits between browser and website and shows me
+ what's happening. I run charles on my own machine and it
+ listens to port 8888, behaving like a proxy. The browser
+ configuration for the proxy is then
+ tt(http://localhost:8888).)
+
+Here's how it works with a crossroads configuration:
+
+itemization(
+ it() I have configured my browsers to use
+ tt(http://localhost:8080) as the proxy. For all situations.
+
+ it() I use the following crossroads configuration, and let
+ crossroads figure out which proxy backend works, and which
+ doesn't. Note two particularities:
+
+ itemization(
+ it() The statement tt(dispatchmode byorder). This
+ makes sure that once crossroads determines which
+ backend works, it will stick to it. This usage of
+ crossroads doesn't need to balance over more than one
+ back end.
+
+ it() The statement tt(bindto 127.0.0.1) makes sure
+ that requests from other interfaces than loopback
+ won't get serviced.)
+
+verb(\
+service HttpProxy {
+ port 8080;
+ bindto 127.0.0.1;
+ verbosity on;
+ dispatchmode byorder;
+ revivinginterval 15;
+
+ backend Charles {
+ server localhost:8888;
+ verbosity on;
+ }
+
+ backend CustomerProxy {
+ server 10.120.34.113:8080;
+ verbosity on;
+ }
+
+ backend SshTunnel {
+ server localhost:3129;
+ }
+
+ backend LocalSquid {
+ server localhost:3128;
+ }
+}))
+
+As a final note, the commandline argument tt(tell) can be used to
+influence crossroad's own detection mechanism of back end availability
+detection. E.g., if in the above example the back ends tt(SshTunnel)
+and tt(LocalSquid) are both active, then tt(crossroads tell httpproxy
+sshtunnel down) will 'take down' the back end tt(SshTunnel) -- and
+will automatically cause crossroads to switch to tt(LocalSquid).
+
+
+subsubsect(SSH login with enforced idle logout)
+
+The following example shows how crossroads 'throttles' SSH
+logins. Connections are accepted on port
+22 (the normal SSH port) and forwarded to the actual SSH daemon
+which is running on port 2222.
+
+Note the usage of the
+tt(connectiontimeout) directive. This makes sure that users are logged
+out after 10 minutes of inactivity. Note also the tt(maxconnections)
+setting, this makes sure that no more than 10 concurrent logins occur.
+
+verb(\
+service Ssh {
+ port 22;
+ backlog 5;
+ maxconnections 10;
+ connectiontimeout 600;
+ backend TrueSshDaemon {
+ server localhost:2222;
+ }
+})
diff --git a/doc/main/tips/externalhandler.yo b/doc/main/tips/externalhandler.yo
@@ -0,0 +1,449 @@
+As mentioned before, Crossroads supports several built-in dispatch
+modes. However, you are always free to hook-in your own dispatch mode
+that determines the next back end using your own specific
+algorithm. This section explains how to do it.
+
+subsubsect(Configuring the external handler)
+
+First, the tt(dispatchmode) statement needs to inform Crossroads that
+an external program will do the job. The syntax is: tt(dispatchmode
+externalhandler) em(program arguments). The em(program) must point to
+an executable program that will be started by Crossroads. The
+specifier em(arguments) can be anything you want; those will be the
+arguments to Crossroads. You can however use the following special
+format specifiers:
+
+INCLUDEFILE(formattable)
+
+Note that the format specifiers such as tt(%b) don't make sense in the
+phase in which an external handler is called, since there is no
+current back end yet (the job of the handler is to supply one).
+
+subsubsect(Writing the external handler)
+
+The external handler is activated using the arguments that are
+specified in DEFAULTCONF(). The external handler can do
+whatever it wants, but ultimately, it must write a back end name on
+its em(stdout). Crossroads reads this, and if the back end is
+available, uses that back end for the connection.
+
+subsubsect(Examples of external handlers)
+
+This section shows some examples of Crossroads configurations
+vs. external handlers. The sample handlers that are shown here, are
+also included in the Crossroads distribution, under the directory
+tt(etc/). Also note that the examples shown here are just
+quick-and-dirty Perl scripts, meant to illustrate only. Your
+applications may need other external handlers, but you can use the
+shown scripts as a starting point.
+
+subsubsubsect(Round-robin dispatching)
+
+This example is trivial in the sense that round-robin dispatching is
+already built into Crossroads, so
+that using an external handler for this purpose only slows down
+Crossroads. However, it's a good starting example.
+
+The Crossroads configuration is shown below:
+
+verb(\
+service test {
+ port 8001;
+ verbosity on;
+ revivinginterval 5;
+
+ dispatchmode externalhandler
+ /usr/local/src/crossroads/etc/dispatcher-roundrobin
+ %1b %1a %2b %2a;
+
+ backend testone {
+ server localhost:3128;
+ verbosity on;
+ }
+ backend testtwo {
+ server locallhost:3128;
+ verbosity on;
+ }
+})
+
+The relevant tt(dispatchmode) statement invokes the external program
+tt(dispatcher-roundrobin) with four arguments: the name of the first
+back end (tt(testone)), its availability (0 or 1), the name of the
+second back end (tt(testtwo)) and its availability (0 or 1).
+
+The external handler, which is also included in the Crossroads
+distribution, is shown below. It is a Perl script.
+
+verb(\
+#!/usr/bin/perl
+
+use strict;
+
+# Example of a round-robin external dispatcher. This is totally
+# superfluous, Crossroads has this on-board; if you use the external
+# program for determining round-robin dispatching, then you'll only
+# slow things down. This script is just meant as an example.
+
+# Globals / configuration
+# -----------------------
+my $log = '/tmp/exthandler.log'; # Debug log, set to /dev/null to suppress
+my $statefile = '/tmp/rr.last'; # Where we keep the last used
+
+# Logging
+# -------
+sub msg {
+ return if ($log eq '/dev/null' or $log eq '');
+ open (my $of, ">>$log") or return;
+ print $of (scalar(localtime()), ' ', @_);
+}
+
+# Read the last used back end
+# ---------------------------
+sub readlast() {
+ my $ret;
+
+ if (open (my $if, $statefile)) {
+ $ret = <$if>;
+ chomp ($ret);
+ close ($if);
+ msg ("Last used back end: $ret\n");
+ return ($ret);
+ }
+ msg ("No last-used back end (yet)\n");
+ return (undef);
+}
+
+# Write back the last used back end, reply to Crossroads and stop
+# ---------------------------------------------------------------
+sub reply ($) {
+ my $last = shift;
+
+ if (open (my $of, ">$statefile")) {
+ print $of ("$last\n");
+ }
+ print ("$last\n");
+ exit (0);
+}
+
+# Main starts here
+# ----------------
+
+# Collect the cmdline arguments. We expect pairs of backend-name /
+# backend-availablility, and we'll store only the available ones.
+msg ("Dispatch request received\n");
+my @backend;
+for (my $i = 0; $i <= $#ARGV; $i += 2) {
+ push (@backend, $ARGV[$i]) if ($ARGV[$i + 1]);
+}
+msg ("Available back ends: @backend\n");
+
+# Let's see what the last one is. If none found, then we return the
+# first available back end. Otherwise we need to go thru the list of
+# back ends, and return the next one in line.
+my $last = readlast();
+if ($last eq '') {
+ msg ("Returning first available back end $backend[0]\n");
+ reply ($backend[0]);
+}
+
+# There **was** a last back end. Try to match it in the list,
+# then return the next-in-line.
+for (my $i = 0; $i < $#backend; $i++) {
+ if ($last eq $backend[$i]) {
+ msg ("Returning next back end ", $backend[$i + 1], "\n");
+ reply ($backend[$i + 1]);
+ }
+}
+
+# No luck.. run back to the first one.
+msg ("Returning first back end $backend[0]\n");
+reply ($backend[0]);)
+
+The working of the script is basically as follows:
+
+itemization(
+ it() The argument list is scanned. Back ends that are
+ available are collected in an array tt(@backend).
+
+ it() The script queries a state file tt(/tmp/rr.last). If a
+ back end name occurs there, then the next back end is looked
+ up in tt(@backend) and returned to Crossroads. If no last back
+ is unknown or can't be matched, then the first available back
+ end (first element of tt(@backend)) is returned to Crossroads.
+
+ it() Informing Crossroads is done via the subroutine
+ tt(reply()). This code writes the selected back end to file
+ tt(/tmp/rr.last) (for future usage) and prints the back end
+ name to em(stdout).
+
+ it() The script logs its actions to a file
+ tt(/tmp/exthandler.log). This log file can be inspected for
+ the script's actions.)
+
+
+subsubsubsect(Dispatching by the client IP address)
+
+The following example shows a useful real-life situation that
+illustrates how dispatching by client IP address works. bf(Note that)
+as of Crossroads 1.31, tt(dispatchmode byclientip) is implemented --
+so that the below description is somewhat superfluous. The code
+snippets however can help you in modelling your own specific dispatch
+modes, aided by external helpers.
+
+The situation is as follows:
+
+itemization(
+ it() Crossroads is used as a single-address point to forward
+ Remote Desktop requests to a farm of Windows systems, where
+ users can work via remote access;
+
+ it() However, users may stop their session, and when they
+ re-connect, they expect to be sent to the Windows system that
+ they had worked on previously;
+
+ it() Client PC's have their distinct IP addresses, which
+ distinguishes them.
+
+ it() Of four windows systems, two are large servers, and two
+ are small ones. We'll want to assign large servers to clients
+ when we have a choice.)
+
+The requirements resemble session stickiness in HTTP, except that the remote
+desktop protocol doesn't support stickiness. This situation is a
+perfect example of how an external handler can help:
+
+itemization(
+ it() A suitable dispatch mode isn't yet available in
+ Crossroads, but can be easily coded in an external handler;
+
+ it() The potential delay due to the calling of an external
+ handler won't even be noticed. This is a network service where
+ the connection time isn't critical; we'd expect only a few
+ (albeit lengthy) TCP connections.)
+
+The approach to the solution of this problem uses several external
+program hooks:
+
+itemization(
+ it() An external dispatcher handler will be responsible for
+ suggesting a back end, given a client IP and given the current
+ timestamp. This handler will consult an internal
+ administration to see whether the stated IP address should
+ re-use a back end, or to determine which back end is free for usage.
+ it() An external hook tt(onstart) will be responsible for
+ updating the internal administration; i.e., to flag a back end
+ as 'occupied'.
+ it() The external hooks tt(onfailure) and tt(onend) will be
+ responsible for flagging a back end as 'free' again; i.e., for
+ erasing any previous information that states that the back end
+ was occupied.)
+
+The Crossroads configuration is shown below. Only four Windows back
+ends are shown. Each back end is configured on a
+given IP address, port 3389, and is limited to one concurrent connection
+(otherwise a new user might 'steal' a running desktop session).
+
+verb(\
+service rdp {
+ port 3389;
+ revivinginterval 5;
+
+ /* rdp-helper dispatch IP STAMP ... will suggest a back end to use,
+ * arguments are for all back ends: name, availability, weight */
+ dispatchmode externalhandler
+ /usr/local/src/crossroads/etc/rdp-helper dispatch %r %e
+ %1b %1a %1w
+ %2b %2a %2w
+ %3b %3a %3w
+ %4b %4a %4w;
+
+ backend win1 {
+ server 10.1.1.1:3389;
+ maxconnections 1;
+ /* rdp-helper start IP STAMP BACKEND will log the actual start
+ * of a connection;
+ * rdp-helper end IP will log the ending of a connection */
+ onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
+ onend /usr/local/src/crossroads/etc/rdp-helper end %r;
+ onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
+ }
+ backend win2 {
+ server 10.1.1.2:3389;
+ maxconnections 1;
+ onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
+ onend /usr/local/src/crossroads/etc/rdp-helper end %r;
+ onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
+ }
+ backend win3 {
+ server 10.1.1.3:3389;
+ maxconnections 1;
+ weight 2;
+ onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
+ onend /usr/local/src/crossroads/etc/rdp-helper end %r;
+ onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
+ }
+ backend win4 {
+ server 10.1.1.4:3389;
+ maxconnections 1;
+ weight 3;
+ onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
+ onend /usr/local/src/crossroads/etc/rdp-helper end %r;
+ onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
+ }
+})
+
+Depending on the dispatcher stage, the exernal handler tt(rdp-helper)
+is invoked in different ways:
+
+description(
+ dit(During dispatching) the helper is called to suggest a back
+ end. The arguments are an action indicator tt(dispatch), the
+ client's IP address, the timestamp, and four triplets that
+ represent back ends: per back end its name, its availability,
+ and its weight. The purpose of the helper is to tell
+ Crossroads which back end to use.
+
+ dit(During connection start) the helper will be invoked to
+ inform it of the start of a connection, given a client IP
+ address.
+
+ dit(When a connection terminates) the helper will be invoked
+ to inform it that the connection has ended.)
+
+Here's the external handler as Perl script. It uses the module
+tt(GDBM_File) which most likely will not be part of standard Perl
+distributions, but can be added using CPAN. (Alternatively, any other
+database module can be used.)
+
+verb(\
+#!/usr/bin/perl
+
+use strict;
+use GDBM_File;
+
+# Global variables and configuration
+# ----------------------------------
+my $log = '/tmp/exthandler.log'; # Debug log, set to /dev/null to suppress
+my $cdb = '/tmp/client.db'; # GDBM database of clients
+my %db; # .. and memory representation of it
+my $timeout = 24*60*60; # Timeout of a connection in secs
+
+# Logging
+# -------
+sub msg {
+ return if ($log eq '/dev/null' or $log eq '');
+ open (my $of, ">>$log") or return;
+ print $of (scalar(localtime()), ' ', @_);
+ close ($of);
+}
+
+# Reply a back end to the caller and stop processing.
+# ---------------------------------------------------
+sub reply ($) {
+ my $b = shift;
+ msg ("Suggesting $b to Crossroads.\n");
+ print ("$b\n");
+ exit (0);
+}
+
+# Is a value in an array
+# ----------------------
+sub inarray {
+ my $val = shift;
+ for my $other (@_) {
+ return (1) if ($other eq $val);
+ }
+ return (0);
+}
+
+# A connection is starting
+# ------------------------
+sub start {
+ my ($ip, $stamp, $backend) = @_;
+ msg ("Logging START of connection for IP $ip on stamp $stamp, ",
+ "back end $backend\n");
+ $db{$ip} = "$backend:$stamp";
+}
+
+# A connection has ended
+# ----------------------
+sub end {
+ my $ip = shift;
+ msg ("Logging END of connection for IP $ip\n");
+ $db{$ip} = undef;
+}
+
+# Request to determine a back end
+# -------------------------------
+sub dispatch {
+ my $ip = shift;
+ my $stamp = shift;
+
+ msg ("Request to dispatch IP $ip on stamp $stamp\n");
+
+ # Read the next arguments. They are triplets of
+ # backend-name / availability / weight. Store if the back end is
+ # available.
+ my (@backends, @weights);
+ for (my $i = 0; $i < $#_; $i += 3) {
+ if ($_[$i + 1] != 0) {
+ push (@backends, $_[$i]);
+ push (@weights, $_[$i + 2]);
+ msg ("Candidate back end: $_[$i] with weight ", $_[$i + 2], "\n");
+ }
+ }
+
+ # See if this is a reconnect by a previously seen client IP. We'll
+ # treat this as a reconnect if the timeout wasn't yet exceeded.
+ if ($db{$ip} ne '') {
+ my ($last_backend, $last_stamp) = split (/:/, $db{$ip});
+ msg ("IP $ip had last connected on $last_stamp to $last_backend\n");
+ if ($stamp < $last_stamp + $timeout) {
+ msg ("Timeout not yet exceeded, this may be a reconnect\n");
+ # We'll allow a reconnect only if the stated last_backend is
+ # free (sanity check).
+ if (inarray ($last_backend, @backends)) {
+ msg ("Last back end $last_backend is available, ",
+ "letting through\n");
+ reply ($last_backend);
+ } else {
+ msg ("Last used back end isn't free, suggesting a new one\n");
+ }
+ } else {
+ msg ("Timeout exceeded, suggesting a new back end\n");
+ }
+ } else {
+ msg ("Np preveious connection data, suggesting a new back end\n");
+ }
+
+ my $bestweight = -1;
+ my $bestbackend;
+ for (my $i = 0; $i <= $#weights; $i++) {
+ if ($bestweight == -1 or $bestweight > $weights[$i]) {
+ $bestweight = $weights[$i];
+ $bestbackend = $backends[$i];
+ }
+ }
+
+ msg ("Best back end: $bestbackend (given weight $bestweight)\n");
+ reply ($bestbackend);
+}
+
+# Main starts here
+# ----------------
+msg ("Start of run, attaching GDBM database '$cdb'\n");
+tie (%db, 'GDBM_File', $cdb, &GDBM_WRCREAT, 0600);
+
+# The first argument must be an action 'dispatch', 'start' or 'end'.
+# Depending on the action, we do stuff.
+my $action = shift (@ARGV);
+if ($action eq 'dispatch') {
+ dispatch (@ARGV);
+} elsif ($action eq 'start') {
+ start (@ARGV);
+} elsif ($action eq 'end') {
+ end (@ARGV);
+} else {
+ print STDERR ("Usage: rdp-helper {dispatch|start|end} args\n");
+ exit (1);
+})
diff --git a/doc/tips/howselected.yo b/doc/main/tips/howselected.yo
diff --git a/doc/tips/httpstickiness.yo b/doc/main/tips/httpstickiness.yo
diff --git a/doc/tips/ipconntrackmax.yo b/doc/main/tips/ipconntrackmax.yo
diff --git a/doc/main/tips/ipfiltering.yo b/doc/main/tips/ipfiltering.yo
@@ -0,0 +1,122 @@
+subsubsect(General Examples)
+
+The directives tt(allowfrom), tt(denyfrom), tt(allowfile) and
+tt(denyfile) can be used to instruct Crossroads to specifically allow
+access by using a "whitelist" of IP addresses, or to specifically deny
+access by using a "blacklist". E.g., the following configuration
+allows access to service tt(webproxy) only to em(localhost):
+
+verb(\
+service webproxy {
+ port 8000;
+ allowfrom 127.0.0.1;
+ backend one {
+ .
+ . Back end definitions occur here
+ .
+ }
+ .
+ . Other back ends or other service directives
+ . may occur here
+ .
+})
+
+In this example there is a "whitelist" having only one entry: IP
+address 127.0.0.1, or em(localhost). (Incidentally, the same behaviour
+could be accomplished by stating em(bindto 127.0.0.1), in which case
+Crossroads would only listen to the local network device.)
+
+In the same vein, the directive tt(allowfrom 127.0.0.1 192.168.1/24)
+would allow access to em(localhost) and to all IP addresses that start
+with 192.168.1. The specifier tt(192.168.1/24) states that there are
+three network bytes (192, 168 and 1), and 24 bits (or 3 bytes) are
+relevant; so that the fourth network byte doesn't matter.
+
+subsubsect(Using External Files)
+
+The directives tt(allowfile) and tt(denyfile) allow you to specify IP
+addresses in external files. The Crossroads configuration states
+e.g. tt(allowfile /tmp/allow.txt), and the IP addresses are then in
+tt(/tmp/allow.txt). The format of tt(/tmp/allow.txt) is as follows:
+
+itemization(
+ it() The specifications follow again em(p.q.r.s/mask), where
+ p, q, r and s are network bytes which can be left out on the
+ right hand side when the mask allows it;
+
+ it() The specifications must be separated by white space
+ (spaces, tabs or newlines).)
+
+E.g., the following is a valid example of an external specification
+file:
+
+verb(\
+127.0.0.1
+192.168.1/24
+10/8)
+
+When external files are in effect, then the signal tt(SIGHUP) (1)
+causes Crossroads to reload the external file. E.g., while Crossroads
+is running, you may edit tt(/tmp/allow.txt), and then issue tt(killall
+-1 crossroads). The new contents of tt(/tmp/allow.txt) will be
+reloaded.
+
+subsubsect(Mixing Directives)
+
+Crossroads allows to mix all directives in one service
+description. However, some mixes are less meaningful than others. It's
+up to you to take this into account.
+
+The following rules apply:
+
+itemization(
+ it() Blacklisting and whitelisting can be used together. When
+ combined, the blacklist will always be interpreted
+ first. E.g., consider the following directives:
+
+ verb(\
+allowfrom 192.168.1/24
+denyfrom 192.168.1.100)
+
+ Given the fact that the deny list is checked first, client
+ 192.168.1.100 won't be able to access Crossroads. Then the
+ allow list will be checked, stating that all clients whose IP
+ address starts with 192.168.1 may connect. The effect will be
+ that e.g., client 192.168.1.1 may connect, 192.168.1.2 may
+ connect too, 192.168.1.100 will be blocked, and 10.1.1.1 will
+ be blocked as well.
+
+ Now consider the following directives:
+
+ verb(\
+allowfrom 192.168.1.100 127.0.0.1
+denyfrom 192.168.1/24)
+
+ This will first of all deny access to all IP addresses that
+ start with 192.168.1. So the rule that allows 192.168.1.100
+ won't ever be effective. The net result will be that access
+ will be granted to 127.0.0.1.
+
+ it() Blacklisting or whitelisting can be left out.
+ A list is considered empty when no appropriate directives
+ occur in DEFAULTCONF(), or when the directive
+ points to an empty or non-existent external file.
+
+ it() Using tt(*from) and tt(*file) statements is allowed, but
+ doesn't make sense. E.g., the following configuration sample
+ is such a case:
+
+ verb(\
+allowfrom 127.0.0.1 192.168.1/24
+allowfile /tmp/allow.txt)
+
+ There is a technical reason for this. Once Crossroads
+ processes the tt(allowfile) directive, then the whole
+ whitelist is cleared (thereby removing the entries 127.0.0.1
+ and 192.168.1/24), and new entries are reloaded from the
+ file. The net result is that the tt(allowfrom) specification
+ is overruled.)
+
+Crossroads only performs syntactic checking of the configuration. Some
+of the above samples are syntactically correct, but make no semantic
+sense: Crossroads doesn't warn for such situations.
diff --git a/doc/main/tips/rendering.yo b/doc/main/tips/rendering.yo
@@ -0,0 +1,65 @@
+The Crossroads flag tt(-x) causes the status output to be generated as
+an XML document. This format can be nicely used to render the output
+as an HTML page.
+
+E.g., the following sample shows how Crossroads reports its status in
+XML format:
+
+verb(\
+<?xml version="1.0" encoding="UTF-8"?>
+<status>
+ <service id="1" name="smtp">
+ <connections>1</connections>
+ <lastbackend>0</lastbackend>
+ <backend id="0" name="first">
+ <availability id="0">available</availability>
+ <clients>0</clients>
+ <failures>0</failures>
+ <connections>2</connections>
+ <duration sec="0.559882">0.56s</duration>
+ <throughput bytes="3564">3.48Kb</throughput>
+ </backend>
+ <backend id="1" name="second">
+ <availability id="0">available</availability>
+ <clients>0</clients>
+ <failures>0</failures>
+ <connections>2</connections>
+ <duration sec="23.7636">23.76s</duration>
+ <throughput bytes="9055">8.84Kb</throughput>
+ </backend>
+ </service>
+</status>)
+
+A custom-made XSLT transformation stylesheet can be used to convert
+this to any output format - and also to HTML. Such a style sheet is
+included in the Crossroads distribution as
+tt(etc/xml-status-to-html.xslt). The sheet is lengthy, and is
+therefore not included in this document. (You're welcome to modify it
+to suit your specific needs. If you have cool tips, send them along to
+me and I'll include them in the next distribution!)
+
+If you want to show this output in a webpage which is generated on
+demand by a webserver, then you might run into the following
+problem. The status reporter (tt(crossroads -x status))
+ must be able to access the shared memory segment of the running
+Crossroads instance. By default, the shared memory is protected for
+the user that started Crossroads, which will often not be the user who
+runs the webserver. Under the auspices of the webserver user,
+tt(crossroads status) might abort with a message: "ERROR: Cannot get
+shared memory for service em(name), key em(number): Permission denied."
+
+The solution for this problem is to make the shared memory access
+somewhat more liberal. There are basically two options:
+
+itemization(
+ it() Start Crossroads with the flag tt(-m 0666), which makes
+ the shared memory segment available to all. The octal number
+ 0666 works just like a file permission setting under
+ Unix. Now, any user can run tt(crossroads status).
+
+ it() If you want to make the access to Crossroads' shared
+ memory somewhat stricter, then make the user who starts
+ Crossroads and the user who runs the webserver member of a new
+ Unix group. Start Crossroads with the flag tt(-m 0664). Now,
+ users belonging to the same group as the Crossroads starter
+ can run tt(crossroads status).)
diff --git a/doc/tips/retries.yo b/doc/main/tips/retries.yo
diff --git a/doc/main/tips/scripting.yo b/doc/main/tips/scripting.yo
@@ -0,0 +1,152 @@
+The internal reviving model of Crossroads can periodically check
+whether back ends that are unavailable have woken up yet. The checker
+is triggered by a tt(revivinginterval) statement of a service
+description, as in:
+
+verb(\
+service web {
+ port 80;
+ revivinginterval 5;
+
+ backend one {
+ server 10.1.1.1:80;
+ }
+
+ backend two {
+ server 10.1.1.2:80;
+ }
+})
+
+This instructs Crossroads to check back ends tt(one) or tt(two) each 5
+seconds. A back end is considered available when it accepts TCP
+connections on the given IP address and port.
+
+This approach may not be sufficient in all situations. E.g., a web
+server may 'hang': it might accept a connection, but never serve
+it. Or, an application server may serve simple connections, but if its
+database is offline, it will generate internal server errors on pages
+that try to access data.
+
+In such situations you may want to replace the internal wakeup service
+with your own scripted 'health check'. Here's how:
+
+itemization(
+ it() First of all, you take out the tt(revivinginterval)
+ statement of DEFAULTCONF(), so that Crossroads'
+ internal check which only verifies TCP connectivity is
+ disabled.
+
+ it() You determine a suitable URL in the applications that can
+ be queried for the health. In our example this will be
+ tt(/areyouthere.jsp), a hypothetical page that does some
+ database access. It doesn't even need to return output; just
+ succeed, or fail.
+
+ it() You devise a small script that asks Crossroads the status
+ of back ends of a given service (in our example, service
+ tt(web)).
+
+ it() The health check script starts by querying Crossroads to
+ determine whether a given back end is available or not. This
+ can be done via tt(crossroads -t status); the flag tt(-t)
+ causes Crossroads to emit easily parsable output.
+
+ it() When the service is available, the health check script
+ hits a given URL and expects an answer tt(HTTP/1.x 200
+ OK). When this answer is not present, the back end is marked
+ unavailable. (The reason for e.g. tt(HTTP/1.x 500) might be a
+ database failure, as described above.) Marking a back end as
+ unavailable can be done via tt(crossroads tell) em(service)
+ em(backend) tt(unavailable).
+
+ it() When the service is unavailable, then the health check
+ script hits the same given URL. When a tt(HTTP/1.x 200 OK)
+ answer is returned, then the back end has 'woken up' and can
+ be marked available (using tt(crossroads tell)).)
+
+A sample health check script that does this, is shown below. It is
+also in the Crossroads distribution as tt(etc/healthcheck). It expects
+three arguments: a testing URL, a service name, and a back end name.
+
+verb(\
+#!/usr/bin/perl
+
+use strict;
+use LWP::UserAgent;
+
+# Show usage and stop
+sub usage () {
+ die <<"ENDUSAGE";
+
+Usage: healthcheck URL SERVICE BACKEND
+
+Performs a health check of the stated url and if necessary flips the
+state of the stated back end between 'available' and 'unavailable'.
+Back ends that are 'down' are not affected.
+
+ENDUSAGE
+}
+
+# Test an URL. Return whether it's a success.
+sub testurl() {
+ my $ua = LWP::UserAgent->new();
+ my $req = HTTP::Request->new(GET => $ARGV[0]);
+ my $res = $ua->request($req);
+
+ if ($res->is_success()) {
+ print ("URL $ARGV[0] indicates success\n");
+ return (1);
+ } else {
+ print ("URL $ARGV[0] indicates failure\n");
+ return (0);
+ }
+}
+
+# Main starts here
+usage() unless ($#ARGV == 2);
+
+# Get the current state of the back end
+open (my $if, "crossroads -t status '$ARGV[1]' '$ARGV[2]' |")
+ or die ("Cannot run 'crossroads status'\n");
+my $status = <$if>;
+close ($if) or die ("'crossroads status' terminated with error\n");
+chomp ($status);
+$status =~ s{.*=}{};
+$status =~ s{\s+}{};
+
+print ("Back end $ARGV[2] has status $status\n");
+if ($status eq 'UNAVAILABLE') {
+ if (testurl()) {
+ print ("Back end $ARGV[2] is now available\n");
+ system ("crossroads tell $ARGV[1] $ARGV[2] available")
+ and die ("'crossroads tell' terminated with error\n");
+ }
+} elsif ($status eq 'available') {
+ if (!testurl()) {
+ print ("Back end $ARGV[2] is is now UNAVAILABLE\n");
+ system ("crossroads tell $ARGV[1] $ARGV[2] UNAVAILABLE")
+ and die ("'crossroads tell' terminated with error\n");
+ }
+} else {
+ print ("No action given status '$status'\n");
+})
+
+Once you have the health checker in place, it can be run e.g. each 10
+seconds in a mini-daemon for back end tt(one):
+
+verb(\
+while [ 1 ] ; do
+ healthcheck http://10.1.1.1/areyouthere.jsp web one
+ sleep 10
+done)
+
+The same is run for back end tt(two):
+
+verb(\
+while [ 1 ] ; do
+ healthcheck http://10.1.1.2/areyouthere.jsp web two
+ sleep 10
+done)
+
+The further implementation of such a mini-daemon that fires up
+tt(healthcheck) is left to the reader.
diff --git a/doc/tips/tcpstickiness.yo b/doc/main/tips/tcpstickiness.yo
diff --git a/doc/tips/throttling.yo b/doc/main/tips/throttling.yo
diff --git a/doc/main/using.yo b/doc/main/using.yo
@@ -0,0 +1,131 @@
+Crossroads is started from the commandline, and highly depends on
+DEFAULTCONF() (the default configuration file). It
+supports a number of flags (e.g., to overrule the location of the
+configuration file). The actual usage information is always obtained
+by typing tt(crossroads) without any arguments. Crossroads then
+displays the allowed arguments.
+
+The installation (see section ref(installation)) installs also a
+second program called tt(crossroads-daemon). This program is not meant
+to be started from the command line; it is administered through the
+front end tt(crossroads).
+
+subsect(General Commandline Syntax)
+
+This section shows the most basic usage. As said above, start
+tt(crossroads) without arguments to view the full listing of options.
+
+itemization(
+ it() tt(crossroads start) and tt(crossroads stop) are typical
+ actions that are run from system startup scripts. The
+ meaning is self-explanatory.
+ it() tt(crossroads restart) is a combination of the former
+ two. Beware that a restart may cause discontinuity in
+ service; it is just a shorthand for typing the 'stop' and
+ 'start' actions after one another.
+ it() tt(crossroad status) reports on each running
+ service. Per service, the state of each back end is
+ reported.
+ it() tt(crossroads tell) em(service backend state) is a
+ command line way of telling crossroads that a given back
+ end, of a given service, is in a given state. Normally
+ crossroads maintains state information itself, but by
+ using tt(crossroads tell), a back end can be e.g. taken
+ 'off line' for servicing.
+ it() tt(crossroads configtest) tells you whether the
+ configuration is syntactially correct.
+ it() tt(crossroads services) reports on the configured
+ services. In contrast to tt(crossroads status), this
+ option only shows what's configured -- not what's up and
+ running. Therefore, tt(crossroads services) doesn't
+ report on back end states.
+ it() tt(crossroads sampleconf) shows a sample configuration on
+ screen. A good way of quicky viewing the configuration
+ file syntax, or of getting a start for your own
+ configuration DEFAULTCONF().
+)
+
+subsect(Status Reporting)
+
+The command tt(crossroads status) shows a verbose human-readable
+report of how Crossroads is doing. When many services are configured,
+this can be a somewhat lengthy output. If you're interested in the
+overview of only one service, you can use tt(crossroads status)
+em(servicename), in which case the report will only be shown for the
+stated service.
+
+Similarly, if you're interested only in the status of a given back end
+of a given service, use tt(crossroads service) em(servicename)
+em(backendname).
+
+The flag tt(-t) causes the status overview to be abbreviated and
+displayed in a parseable format. This flag can be used in automated
+scripts that check how Crossroads is doing; e.g., in health checking
+scripts. When tt(-t) is used, the format of the status reporter is as
+follows:
+
+itemization(
+ it() Service health is reported on one line per service.
+ it() The first string on the line is the service name.
+ it() After this, a series follows of em(backendname=state),
+ where the back end name is the configured name of the back
+ end, and where state is e.g. tt(available), tt(DOWN),
+ tt(UNAVAILABLE), tt(WAKING). All statuses that cause
+ Crossroads not to use the back end are in caps. The series is
+ repeated for all back ends of the given service.)
+
+The flag tt(-x) causes the overview to be presented as an XML
+document. This can be handy if you want to further automate the
+control over Crossroads, or if you want to show the status via the
+web. (See section ref(xmlstatus) for more information.)
+
+
+subsect(Logging-related options)
+
+Two 'flags' of Crossroads are specifically logging-related. This
+section elaborates on these flags.
+
+First, there's flag tt(-a). When present, the start and end of
+activity is logged using statements like
+
+center(em(YYYY-MM-DD HH/MM/SS starting http from 61.45.32.189 to 10.1.1.1))
+
+Similarly, there are 'ending' statements. Using this flag and
+scanning your logs for these statements may be helpful in quickly
+determining your system load.
+
+Second, there's flag tt(-l). This flag selects the 'facility' of
+logging and defaults to tt(LOG_DAEMON). You can supply a number
+between 0 and 7 to flag tt(-l) to select tt(LOG_LOCAL0) to
+tt(LOG_LOCAL7). This would separate the Crossroads-related logging
+from other streams. Here's a very short guide; please read your Unix
+manpages of tt(syslogd) for more information.
+
+itemization(
+ it() First edit tt(/etc/syslog.conf) and add a line:
+
+ verb(local7.* /var/log/crossroads.log)
+
+ That instructs tt(syslogd) to send tt(LOG_LOCAL7) requests to the
+ logfile tt(/var/log/crossroads.log).
+
+ it() Next, restart tt(syslogd). On most Unices that's done by
+ issuing tt(killall -1 syslogd). (As a side-note, I tried this once
+ on an Bull/AIX system, and the box just shut down. The tt(killall)
+ command killed every process...)
+
+ it() Now start tt(crossroads) with the flag tt(-l7).
+
+ it() Finally, monitor tt(/var/log/crossroads.log) for Crossroads'
+ messages.)
+
+
+subsect(Reloading Configurations)
+
+Crossroads doesn't support the reloading of a configuration while
+running (such as other programs, e.g. Apache do). There are various
+technical reasons for this.
+
+However, external lists of allowed or denied IP addresses can be
+reloaded by sending a signal -1 (tt(SIGHUP)) to Crossroads. See
+section ref(servicedef) for the details.
diff --git a/doc/man/crossroads.conf.yo b/doc/man/crossroads.conf.yo
@@ -0,0 +1,24 @@
+includefile(../crossroads-defs)
+
+manpage(crossroads.conf)(7)(YEARS())(crossroads)()
+manpagename(crossroads.conf)(Crossroads configuration)
+
+manpagesynopsis()
+This manpage describes the configuration of Crossroads, normally the
+file bf(DEFAULTCONF()). Crossroads can however be started with a flag
+bf(-c) to overrule this name.
+
+manpagedescription()
+redef(confsect)(1)(manpagesection(ARG1))
+redef(confsubsect)(1)(bf(ARG1))
+includefile(../main/config)
+
+manpageseealso()
+ itemization(
+ it() crossroads (1)
+ it() The full Crossroads documentation, in pdf and html
+ format, distributed with the sources.)
+
+manpageauthor()
+ Crossroads is written by AUTHORNAME() and is maintained by
+ MAINTAINERNAME() (MAINTAINEREMAIL()).
+\ No newline at end of file
diff --git a/doc/man/crossroads.yo b/doc/man/crossroads.yo
@@ -0,0 +1,107 @@
+includefile(../crossroads-defs)
+manpage(crossroads)(1)(YEARS())(crossroads)()
+manpagename(crossroads)(Load balancer and fail over utility)
+
+manpagesynopsis()
+ itemization(
+ it() bf(crossroads) em([flags]) bf(start): starts Crossroads
+ it() bf(crossroads) em([flags]) bf(stop): stops Crossroads
+ it() bf(crossroads) em([flags]) bf(restart): restarts Crossroads
+ it() bf(crossroads) em([flags]) bf(configtest): verifies
+ configuration
+ it() bf(crossroads) em([flags]) bf(services): shows configured
+ services
+ it() bf(crossroads) em([flags]) bf(tell) em(service)
+ em(backend) em(state): sets a back end state)
+
+manpagedescription()
+
+ bf(crossroads) is the main control program of Crossroads, a
+ balancing and fail over utility. The Crossroads utility consists
+ of two binaries: bf(crossroads) and bf(crossroads-daemon). The
+ latter is controlled by the front end bf(crossroads).
+
+ Recognized states in bf(crossroads tell) are:
+
+ itemization(
+ it() bf(available) or bf(up) when a backend is working;
+ it() bf(unavailable) when a back end is temporarily down, but
+ can be woken up;
+ it() bf(down) when a back end is permanently down (e.g., for
+ maintenance). Crossroads itself will never activate a
+ backend in this state.
+ it() bf(waking) when the live status of a back end is being checked.)
+
+manpageoptions()
+
+ Crossroads recognizes the following flags:
+
+ itemization(
+ it() bf(-a): Logs start and end times of activity to
+ em(syslog).
+
+ it() bf(-b): Writes a binary representation of the
+ configuration to em(stdout). For debugging only.
+
+ it() bf(-C): Writes the compile time configuration to
+ em(stdout) and stops. Useful when submitting bug reports.
+
+ it() bf(-c) em(config): Uses em(config) as the configuration
+ file. The default is bf(DEFAULTCONF()).
+
+ it() bf(-d) em(sec): Sets the DNS cache time-to-live to
+ em(sec) seconds. Value 0 suppresses DNS entry
+ caching. The default is bf(DNSCACHETTL()).
+
+ it() bf(-l) em(facility): Specifies the openlog (3) facility,
+ default is bf(LOG_DAEMON). Values can be 0 to 7, meaning
+ bf(LOG_LOCAL0) to bf(LOG_LOCAL9).
+
+ it() bf(-m) em(permissions): Specifies shared memory
+ permissions, default is bf(0644).
+
+ it() bf(-s): Requests 'sloppy' binding to TCP ports. When a
+ port is busy, Crossroads will retry periodically to get
+ it. Default is to stop when a listening port cannot be
+ obtained.
+
+ it() bf(-t): Output of bf(crossroads status) is shown as a
+ tabular view, in one or more lines of:
+
+ em(service) em(backend=state) em([backend=state...])
+
+ it() bf(-x): Output of bf(crossroads status) is shown as an
+ XML document.
+
+ it() bf(-v): Initial actions of Crossroads are more
+ 'verbose'. (Once daemonized, the verbosity is controlled
+ using bf(verbosity) statements in the configuration.)
+
+ it() bf(-V): Shows the version ID and stops.
+
+ it() bf(-?, -h): Shows an overview of the usage.)
+
+manpagefiles()
+ bf(DEFAULTCONF()), the default configuration file
+
+manpageseealso()
+ itemization(
+ it() crossroads.conf (7)
+ it() The full Crossroads documentation in html or pdf format,
+ distributed with the sources.)
+
+manpagebugs()
+ Crossroads is of course bug free (haha). When submitting bugs to
+ the maintainer. please always include the following information:
+
+ itemization(
+ it() The configuration file that Crossroads uses;
+ it() The compile-time configuration, which is the output of
+ bf(crossroads -C);
+ it() A good description of the bug, and of the conditions
+ under which it occurs.)
+
+manpageauthor()
+ itemization(
+ it() Author: AUTHORNAME()
+ it() Maintainer: MAINTAINERNAME() MAINTAINEREMAIL())
+\ No newline at end of file
diff --git a/doc/tips.yo b/doc/tips.yo
@@ -1,42 +0,0 @@
-The following sections elaborate on the directives as described in
-section ref(config) to illustrate how crossroads works and to help you
-achieve the "optimal" balancing configuration.
-
-subsect(How back ends are selected in load balancing) label(howselected)
-includefile(tips/howselected)
-
-subsect(Throttling the number of concurrent connections)
-includefile(tips/throttling)
-
-subsect(Using an external program to dispatch) label(externalhandler)
-includefile(tips/externalhandler)
-
-subsect(TCP Session Stickiness)
-includefile(tips/tcpstickiness)
-
-subsect(HTTP Session Stickiness)
-includefile(tips/httpstickiness)
-
-subsect(Passing the client's IP address)
-includefile(tips/clientip)
-
-subsect(Debugging network traffic)
-includefile(tips/debugging)
-
-subsect(IP filtering: Limiting Access by Client IP Address)
-includefile(tips/ipfiltering)
-
-subsect(Configuration examples)
-includefile(tips/examples)
-
-subsect(Linux and ip_conntrack_max)
-includefile(tips/ipconntrackmax)
-
-subsect(Marking back ends as bad after more than one try)
-includefile(tips/retries)
-
-subsect(Scripting Crossroads' back end availability)
-includefile(tips/scripting)
-
-subsect(Rendering Crossroads' status in a web page)
-includefile(tips/rendering)
diff --git a/doc/tips/examples.yo b/doc/tips/examples.yo
@@ -1,236 +0,0 @@
-
-subsubsect(A load balancer for three webserver back ends)
-
-The following configuration example binds crossroads to port 80 of the
-current server, and distributes the load over three back ends. This
-configuration shows most of the possible settings.
-
-verb(\
-service www {
- /* We don't need session stickyness. */
- type any;
-
- /* Port on which we'll listen in this service: required. */
- port 8000;
-
- /* What IP address should this service listen? Default is 'any'.
- * Alternatively you can state an explicit IP address, such as
- * 127.0.0.1; that would bind the service only to 'localhost'. */
- bindto any;
-
- /* Verbose reporting or not. Default is off. */
- verbosity on;
-
- /* Dispatching mode, or: How to select a back end for an incoming
- * request. Possible values:
- * roundrobin: just the next back end in line
- * random: like roundrobin, but at random to make things more
- * confusing. Probably only good for testing.
- * bysize: The backend that transferred the least nr of bytes
- * is the next in line. As a modifier you can say e.g.
- * bysize over 10, meaning that the 10 last connections will
- * be used to compute the transfer size, instead of all
- * transfers.
- * byduration: The backend that was active for the shortest time
- * is the next in line. As a modifier you can say e.g.
- * byduration of 10 to compute over the last 10 connections.
- * byconnections: The back end with the least active connections
- * is the next ine line.
- * byorder: The first available back end is always taken.
- */
- dispatchmode byduration over 5;
-
- /* Interval at which we'll check whether a temporarily unavailable
- * backend has woken up.
- */
- revivinginterval 5;
-
- /* TCP backlog of connections. Default is 0 (no backlog, one
- * connection may be active).
- */
- backlog 5;
-
- /* For status reporting: a shared memory key. Default is the same
- * as the port number, OR-ed by a magic number.
- */
- shmkey 8000;
-
- /* This controls when crossroads should consider a connection as
- * finished even when the TCP sockets weren't closed. This is to
- * avoid hanging connections that don't do anything. NOTE THAT when
- * crossroads cuts off a connection due to timeout exceed, this is
- * not marked as a failure, but as a success. Default is 0: no timeout.
- */
- connectiontimeout 300;
-
- /* The max number of allowed client connections. When present, connections
- * won't be accepted if the max is about to be exceeded. When
- * absent, all connections will be accepted, which might be misused
- * for a DOS attack.
- */
- maxconnections 300;
-
- /* Now let's define a couple of back ends. Number 1: */
- backend www_backend_1 {
- /* The server and its port, the minimum configuration. */
- server httpserver1;
- port 9010;
- /* The 'decay' of usage data of this back end. Only relevant
- * when the whole service has 'dispatchmode bysize' or
- * 'byduration'. The number is a percentage by which the usage
- * parameter is decreased upon each connection of an other back
- * end.
- */
- decay 10;
-
- /* To see what's happening in /var/log/messages: */
- verbosity on;
- }
-
- /* The second one: */
- backend www_backend_2 {
- /* Server and port */
- server httpserver2;
- port 9011;
-
- /* Verbosity of reporting when this back end is active */
- verbosity on;
-
- /* Decay */
- decay 10;
-
- /* This back end is twice as weak as the first one */
- weight 2;
-
- /* Event triggers for system commands upon succesful activation
- * and upon failure.
- */
- onsuccess echo 'success on backend 2' | mail root;
- onfailure echo 'failure on backend 2' | mail root;
- }
-
- /* And yet another one.. this time we will dump the traffic
- * to a trace file. Furthermore we don't want more than 10 concurrent
- * connections here. Note that there's also a total maxconnections for the
- * whole service.
- */
- backend www_backend_3 {
- server httpserver3;
- verbosity on;
- port 9000;
- verbosity on;
- decay 10;
- trafficlog /tmp/backend.3.log;
- maxconnections 10;
- }
-})
-
-subsubsect(An HTTP forwarder when travelling)
-
-As another example, here's my tt(crossroads.conf) that I use on my
-Unix laptop. The problem that I face is that I need many HTTP proxy
-configurations (at home, at customers' sites and so on) but I'm too
-lazy to reconfigure browsers all the time.
-
-Here's how it used to be before crossroads:
-
-itemization(
- it() At home, I would surf through a squid proxy on my local
- machine. The browser proxy setting is then
- tt(http://localhost:3128).
-
- it() Sometimes I start up an SSH tunnel to our offices. The
- tunnel has a local port 3129, and connects to a squid proxy on
- our e-tunity server. Hence, the browser proxy is then
- tt(http://localhost:3129).
-
- it() At a customer's location I need the proxy
- tt(http://10.120.34.113:8080), because they have configured it
- so.
-
- it() And in yet other instances, I use a HTTP diagnostic tool
- url(Charles)(http://www.xk72.com/charles)
- that sits between browser and website and shows me
- what's happening. I run charles on my own machine and it
- listens to port 8888, behaving like a proxy. The browser
- configuration for the proxy is then
- tt(http://localhost:8888).)
-
-Here's how it works with a crossroads configuration:
-
-itemization(
- it() I have configured my browsers to use
- tt(http://localhost:8080) as the proxy. For all situations.
-
- it() I use the following crossroads configuration, and let
- crossroads figure out which proxy backend works, and which
- doesn't. Note two particularities:
-
- itemization(
- it() The statement tt(dispatchmode byorder). This
- makes sure that once crossroads determines which
- backend works, it will stick to it. This usage of
- crossroads doesn't need to balance over more than one
- back end.
-
- it() The statement tt(bindto 127.0.0.1) makes sure
- that requests from other interfaces than loopback
- won't get serviced.)
-
-verb(\
-service HttpProxy {
- port 8080;
- bindto 127.0.0.1;
- verbosity on;
- dispatchmode byorder;
- revivinginterval 15;
-
- backend Charles {
- server localhost:8888;
- verbosity on;
- }
-
- backend CustomerProxy {
- server 10.120.34.113:8080;
- verbosity on;
- }
-
- backend SshTunnel {
- server localhost:3129;
- }
-
- backend LocalSquid {
- server localhost:3128;
- }
-}))
-
-As a final note, the commandline argument tt(tell) can be used to
-influence crossroad's own detection mechanism of back end availability
-detection. E.g., if in the above example the back ends tt(SshTunnel)
-and tt(LocalSquid) are both active, then tt(crossroads tell httpproxy
-sshtunnel down) will 'take down' the back end tt(SshTunnel) -- and
-will automatically cause crossroads to switch to tt(LocalSquid).
-
-
-subsubsect(SSH login with enforced idle logout)
-
-The following example shows how crossroads 'throttles' SSH
-logins. Connections are accepted on port
-22 (the normal SSH port) and forwarded to the actual SSH daemon
-which is running on port 2222.
-
-Note the usage of the
-tt(connectiontimeout) directive. This makes sure that users are logged
-out after 10 minutes of inactivity. Note also the tt(maxconnections)
-setting, this makes sure that no more than 10 concurrent logins occur.
-
-verb(\
-service Ssh {
- port 22;
- backlog 5;
- maxconnections 10;
- connectiontimeout 600;
- backend TrueSshDaemon {
- server localhost:2222;
- }
-})
diff --git a/doc/tips/externalhandler.yo b/doc/tips/externalhandler.yo
@@ -1,449 +0,0 @@
-As mentioned before, Crossroads supports several built-in dispatch
-modes. However, you are always free to hook-in your own dispatch mode
-that determines the next back end using your own specific
-algorithm. This section explains how to do it.
-
-subsubsect(Configuring the external handler)
-
-First, the tt(dispatchmode) statement needs to inform Crossroads that
-an external program will do the job. The syntax is: tt(dispatchmode
-externalhandler) em(program arguments). The em(program) must point to
-an executable program that will be started by Crossroads. The
-specifier em(arguments) can be anything you want; those will be the
-arguments to Crossroads. You can however use the following special
-format specifiers:
-
-INCLUDEFILE(formattable)
-
-Note that the format specifiers such as tt(%b) don't make sense in the
-phase in which an external handler is called, since there is no
-current back end yet (the job of the handler is to supply one).
-
-subsubsect(Writing the external handler)
-
-The external handler is activated using the arguments that are
-specified in tt(/etc/crossroads.conf). The external handler can do
-whatever it wants, but ultimately, it must write a back end name on
-its em(stdout). Crossroads reads this, and if the back end is
-available, uses that back end for the connection.
-
-subsubsect(Examples of external handlers)
-
-This section shows some examples of Crossroads configurations
-vs. external handlers. The sample handlers that are shown here, are
-also included in the Crossroads distribution, under the directory
-tt(etc/). Also note that the examples shown here are just
-quick-and-dirty Perl scripts, meant to illustrate only. Your
-applications may need other external handlers, but you can use the
-shown scripts as a starting point.
-
-subsubsubsect(Round-robin dispatching)
-
-This example is trivial in the sense that round-robin dispatching is
-already built into Crossroads, so
-that using an external handler for this purpose only slows down
-Crossroads. However, it's a good starting example.
-
-The Crossroads configuration is shown below:
-
-verb(\
-service test {
- port 8001;
- verbosity on;
- revivinginterval 5;
-
- dispatchmode externalhandler
- /usr/local/src/crossroads/etc/dispatcher-roundrobin
- %1b %1a %2b %2a;
-
- backend testone {
- server localhost:3128;
- verbosity on;
- }
- backend testtwo {
- server locallhost:3128;
- verbosity on;
- }
-})
-
-The relevant tt(dispatchmode) statement invokes the external program
-tt(dispatcher-roundrobin) with four arguments: the name of the first
-back end (tt(testone)), its availability (0 or 1), the name of the
-second back end (tt(testtwo)) and its availability (0 or 1).
-
-The external handler, which is also included in the Crossroads
-distribution, is shown below. It is a Perl script.
-
-verb(\
-#!/usr/bin/perl
-
-use strict;
-
-# Example of a round-robin external dispatcher. This is totally
-# superfluous, Crossroads has this on-board; if you use the external
-# program for determining round-robin dispatching, then you'll only
-# slow things down. This script is just meant as an example.
-
-# Globals / configuration
-# -----------------------
-my $log = '/tmp/exthandler.log'; # Debug log, set to /dev/null to suppress
-my $statefile = '/tmp/rr.last'; # Where we keep the last used
-
-# Logging
-# -------
-sub msg {
- return if ($log eq '/dev/null' or $log eq '');
- open (my $of, ">>$log") or return;
- print $of (scalar(localtime()), ' ', @_);
-}
-
-# Read the last used back end
-# ---------------------------
-sub readlast() {
- my $ret;
-
- if (open (my $if, $statefile)) {
- $ret = <$if>;
- chomp ($ret);
- close ($if);
- msg ("Last used back end: $ret\n");
- return ($ret);
- }
- msg ("No last-used back end (yet)\n");
- return (undef);
-}
-
-# Write back the last used back end, reply to Crossroads and stop
-# ---------------------------------------------------------------
-sub reply ($) {
- my $last = shift;
-
- if (open (my $of, ">$statefile")) {
- print $of ("$last\n");
- }
- print ("$last\n");
- exit (0);
-}
-
-# Main starts here
-# ----------------
-
-# Collect the cmdline arguments. We expect pairs of backend-name /
-# backend-availablility, and we'll store only the available ones.
-msg ("Dispatch request received\n");
-my @backend;
-for (my $i = 0; $i <= $#ARGV; $i += 2) {
- push (@backend, $ARGV[$i]) if ($ARGV[$i + 1]);
-}
-msg ("Available back ends: @backend\n");
-
-# Let's see what the last one is. If none found, then we return the
-# first available back end. Otherwise we need to go thru the list of
-# back ends, and return the next one in line.
-my $last = readlast();
-if ($last eq '') {
- msg ("Returning first available back end $backend[0]\n");
- reply ($backend[0]);
-}
-
-# There **was** a last back end. Try to match it in the list,
-# then return the next-in-line.
-for (my $i = 0; $i < $#backend; $i++) {
- if ($last eq $backend[$i]) {
- msg ("Returning next back end ", $backend[$i + 1], "\n");
- reply ($backend[$i + 1]);
- }
-}
-
-# No luck.. run back to the first one.
-msg ("Returning first back end $backend[0]\n");
-reply ($backend[0]);)
-
-The working of the script is basically as follows:
-
-itemization(
- it() The argument list is scanned. Back ends that are
- available are collected in an array tt(@backend).
-
- it() The script queries a state file tt(/tmp/rr.last). If a
- back end name occurs there, then the next back end is looked
- up in tt(@backend) and returned to Crossroads. If no last back
- is unknown or can't be matched, then the first available back
- end (first element of tt(@backend)) is returned to Crossroads.
-
- it() Informing Crossroads is done via the subroutine
- tt(reply()). This code writes the selected back end to file
- tt(/tmp/rr.last) (for future usage) and prints the back end
- name to em(stdout).
-
- it() The script logs its actions to a file
- tt(/tmp/exthandler.log). This log file can be inspected for
- the script's actions.)
-
-
-subsubsubsect(Dispatching by the client IP address)
-
-The following example shows a useful real-life situation that
-illustrates how dispatching by client IP address works. bf(Note that)
-as of Crossroads 1.31, tt(dispatchmode byclientip) is implemented --
-so that the below description is somewhat superfluous. The code
-snippets however can help you in modelling your own specific dispatch
-modes, aided by external helpers.
-
-The situation is as follows:
-
-itemization(
- it() Crossroads is used as a single-address point to forward
- Remote Desktop requests to a farm of Windows systems, where
- users can work via remote access;
-
- it() However, users may stop their session, and when they
- re-connect, they expect to be sent to the Windows system that
- they had worked on previously;
-
- it() Client PC's have their distinct IP addresses, which
- distinguishes them.
-
- it() Of four windows systems, two are large servers, and two
- are small ones. We'll want to assign large servers to clients
- when we have a choice.)
-
-The requirements resemble session stickiness in HTTP, except that the remote
-desktop protocol doesn't support stickiness. This situation is a
-perfect example of how an external handler can help:
-
-itemization(
- it() A suitable dispatch mode isn't yet available in
- Crossroads, but can be easily coded in an external handler;
-
- it() The potential delay due to the calling of an external
- handler won't even be noticed. This is a network service where
- the connection time isn't critical; we'd expect only a few
- (albeit lengthy) TCP connections.)
-
-The approach to the solution of this problem uses several external
-program hooks:
-
-itemization(
- it() An external dispatcher handler will be responsible for
- suggesting a back end, given a client IP and given the current
- timestamp. This handler will consult an internal
- administration to see whether the stated IP address should
- re-use a back end, or to determine which back end is free for usage.
- it() An external hook tt(onstart) will be responsible for
- updating the internal administration; i.e., to flag a back end
- as 'occupied'.
- it() The external hooks tt(onfailure) and tt(onend) will be
- responsible for flagging a back end as 'free' again; i.e., for
- erasing any previous information that states that the back end
- was occupied.)
-
-The Crossroads configuration is shown below. Only four Windows back
-ends are shown. Each back end is configured on a
-given IP address, port 3389, and is limited to one concurrent connection
-(otherwise a new user might 'steal' a running desktop session).
-
-verb(\
-service rdp {
- port 3389;
- revivinginterval 5;
-
- /* rdp-helper dispatch IP STAMP ... will suggest a back end to use,
- * arguments are for all back ends: name, availability, weight */
- dispatchmode externalhandler
- /usr/local/src/crossroads/etc/rdp-helper dispatch %r %e
- %1b %1a %1w
- %2b %2a %2w
- %3b %3a %3w
- %4b %4a %4w;
-
- backend win1 {
- server 10.1.1.1:3389;
- maxconnections 1;
- /* rdp-helper start IP STAMP BACKEND will log the actual start
- * of a connection;
- * rdp-helper end IP will log the ending of a connection */
- onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
- onend /usr/local/src/crossroads/etc/rdp-helper end %r;
- onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
- }
- backend win2 {
- server 10.1.1.2:3389;
- maxconnections 1;
- onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
- onend /usr/local/src/crossroads/etc/rdp-helper end %r;
- onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
- }
- backend win3 {
- server 10.1.1.3:3389;
- maxconnections 1;
- weight 2;
- onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
- onend /usr/local/src/crossroads/etc/rdp-helper end %r;
- onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
- }
- backend win4 {
- server 10.1.1.4:3389;
- maxconnections 1;
- weight 3;
- onstart /usr/local/src/crossroads/etc/rdp-helper start %r %e %b;
- onend /usr/local/src/crossroads/etc/rdp-helper end %r;
- onfail /usr/local/src/crossroads/etc/rdp-helper end %r;
- }
-})
-
-Depending on the dispatcher stage, the exernal handler tt(rdp-helper)
-is invoked in different ways:
-
-description(
- dit(During dispatching) the helper is called to suggest a back
- end. The arguments are an action indicator tt(dispatch), the
- client's IP address, the timestamp, and four triplets that
- represent back ends: per back end its name, its availability,
- and its weight. The purpose of the helper is to tell
- Crossroads which back end to use.
-
- dit(During connection start) the helper will be invoked to
- inform it of the start of a connection, given a client IP
- address.
-
- dit(When a connection terminates) the helper will be invoked
- to inform it that the connection has ended.)
-
-Here's the external handler as Perl script. It uses the module
-tt(GDBM_File) which most likely will not be part of standard Perl
-distributions, but can be added using CPAN. (Alternatively, any other
-database module can be used.)
-
-verb(\
-#!/usr/bin/perl
-
-use strict;
-use GDBM_File;
-
-# Global variables and configuration
-# ----------------------------------
-my $log = '/tmp/exthandler.log'; # Debug log, set to /dev/null to suppress
-my $cdb = '/tmp/client.db'; # GDBM database of clients
-my %db; # .. and memory representation of it
-my $timeout = 24*60*60; # Timeout of a connection in secs
-
-# Logging
-# -------
-sub msg {
- return if ($log eq '/dev/null' or $log eq '');
- open (my $of, ">>$log") or return;
- print $of (scalar(localtime()), ' ', @_);
- close ($of);
-}
-
-# Reply a back end to the caller and stop processing.
-# ---------------------------------------------------
-sub reply ($) {
- my $b = shift;
- msg ("Suggesting $b to Crossroads.\n");
- print ("$b\n");
- exit (0);
-}
-
-# Is a value in an array
-# ----------------------
-sub inarray {
- my $val = shift;
- for my $other (@_) {
- return (1) if ($other eq $val);
- }
- return (0);
-}
-
-# A connection is starting
-# ------------------------
-sub start {
- my ($ip, $stamp, $backend) = @_;
- msg ("Logging START of connection for IP $ip on stamp $stamp, ",
- "back end $backend\n");
- $db{$ip} = "$backend:$stamp";
-}
-
-# A connection has ended
-# ----------------------
-sub end {
- my $ip = shift;
- msg ("Logging END of connection for IP $ip\n");
- $db{$ip} = undef;
-}
-
-# Request to determine a back end
-# -------------------------------
-sub dispatch {
- my $ip = shift;
- my $stamp = shift;
-
- msg ("Request to dispatch IP $ip on stamp $stamp\n");
-
- # Read the next arguments. They are triplets of
- # backend-name / availability / weight. Store if the back end is
- # available.
- my (@backends, @weights);
- for (my $i = 0; $i < $#_; $i += 3) {
- if ($_[$i + 1] != 0) {
- push (@backends, $_[$i]);
- push (@weights, $_[$i + 2]);
- msg ("Candidate back end: $_[$i] with weight ", $_[$i + 2], "\n");
- }
- }
-
- # See if this is a reconnect by a previously seen client IP. We'll
- # treat this as a reconnect if the timeout wasn't yet exceeded.
- if ($db{$ip} ne '') {
- my ($last_backend, $last_stamp) = split (/:/, $db{$ip});
- msg ("IP $ip had last connected on $last_stamp to $last_backend\n");
- if ($stamp < $last_stamp + $timeout) {
- msg ("Timeout not yet exceeded, this may be a reconnect\n");
- # We'll allow a reconnect only if the stated last_backend is
- # free (sanity check).
- if (inarray ($last_backend, @backends)) {
- msg ("Last back end $last_backend is available, ",
- "letting through\n");
- reply ($last_backend);
- } else {
- msg ("Last used back end isn't free, suggesting a new one\n");
- }
- } else {
- msg ("Timeout exceeded, suggesting a new back end\n");
- }
- } else {
- msg ("Np preveious connection data, suggesting a new back end\n");
- }
-
- my $bestweight = -1;
- my $bestbackend;
- for (my $i = 0; $i <= $#weights; $i++) {
- if ($bestweight == -1 or $bestweight > $weights[$i]) {
- $bestweight = $weights[$i];
- $bestbackend = $backends[$i];
- }
- }
-
- msg ("Best back end: $bestbackend (given weight $bestweight)\n");
- reply ($bestbackend);
-}
-
-# Main starts here
-# ----------------
-msg ("Start of run, attaching GDBM database '$cdb'\n");
-tie (%db, 'GDBM_File', $cdb, &GDBM_WRCREAT, 0600);
-
-# The first argument must be an action 'dispatch', 'start' or 'end'.
-# Depending on the action, we do stuff.
-my $action = shift (@ARGV);
-if ($action eq 'dispatch') {
- dispatch (@ARGV);
-} elsif ($action eq 'start') {
- start (@ARGV);
-} elsif ($action eq 'end') {
- end (@ARGV);
-} else {
- print STDERR ("Usage: rdp-helper {dispatch|start|end} args\n");
- exit (1);
-})
diff --git a/doc/tips/ipfiltering.yo b/doc/tips/ipfiltering.yo
@@ -1,122 +0,0 @@
-subsubsect(General Examples)
-
-The directives tt(allowfrom), tt(denyfrom), tt(allowfile) and
-tt(denyfile) can be used to instruct Crossroads to specifically allow
-access by using a "whitelist" of IP addresses, or to specifically deny
-access by using a "blacklist". E.g., the following configuration
-allows access to service tt(webproxy) only to em(localhost):
-
-verb(\
-service webproxy {
- port 8000;
- allowfrom 127.0.0.1;
- backend one {
- .
- . Back end definitions occur here
- .
- }
- .
- . Other back ends or other service directives
- . may occur here
- .
-})
-
-In this example there is a "whitelist" having only one entry: IP
-address 127.0.0.1, or em(localhost). (Incidentally, the same behaviour
-could be accomplished by stating em(bindto 127.0.0.1), in which case
-Crossroads would only listen to the local network device.)
-
-In the same vein, the directive tt(allowfrom 127.0.0.1 192.168.1/24)
-would allow access to em(localhost) and to all IP addresses that start
-with 192.168.1. The specifier tt(192.168.1/24) states that there are
-three network bytes (192, 168 and 1), and 24 bits (or 3 bytes) are
-relevant; so that the fourth network byte doesn't matter.
-
-subsubsect(Using External Files)
-
-The directives tt(allowfile) and tt(denyfile) allow you to specify IP
-addresses in external files. The Crossroads configuration states
-e.g. tt(allowfile /tmp/allow.txt), and the IP addresses are then in
-tt(/tmp/allow.txt). The format of tt(/tmp/allow.txt) is as follows:
-
-itemization(
- it() The specifications follow again em(p.q.r.s/mask), where
- p, q, r and s are network bytes which can be left out on the
- right hand side when the mask allows it;
-
- it() The specifications must be separated by white space
- (spaces, tabs or newlines).)
-
-E.g., the following is a valid example of an external specification
-file:
-
-verb(\
-127.0.0.1
-192.168.1/24
-10/8)
-
-When external files are in effect, then the signal tt(SIGHUP) (1)
-causes Crossroads to reload the external file. E.g., while Crossroads
-is running, you may edit tt(/tmp/allow.txt), and then issue tt(killall
--1 crossroads). The new contents of tt(/tmp/allow.txt) will be
-reloaded.
-
-subsubsect(Mixing Directives)
-
-Crossroads allows to mix all directives in one service
-description. However, some mixes are less meaningful than others. It's
-up to you to take this into account.
-
-The following rules apply:
-
-itemization(
- it() Blacklisting and whitelisting can be used together. When
- combined, the blacklist will always be interpreted
- first. E.g., consider the following directives:
-
- verb(\
-allowfrom 192.168.1/24
-denyfrom 192.168.1.100)
-
- Given the fact that the deny list is checked first, client
- 192.168.1.100 won't be able to access Crossroads. Then the
- allow list will be checked, stating that all clients whose IP
- address starts with 192.168.1 may connect. The effect will be
- that e.g., client 192.168.1.1 may connect, 192.168.1.2 may
- connect too, 192.168.1.100 will be blocked, and 10.1.1.1 will
- be blocked as well.
-
- Now consider the following directives:
-
- verb(\
-allowfrom 192.168.1.100 127.0.0.1
-denyfrom 192.168.1/24)
-
- This will first of all deny access to all IP addresses that
- start with 192.168.1. So the rule that allows 192.168.1.100
- won't ever be effective. The net result will be that access
- will be granted to 127.0.0.1.
-
- it() Blacklisting or whitelisting can be left out.
- A list is considered empty when no appropriate directives
- occur in tt(/etc/crossroads.conf), or when the directive
- points to an empty or non-existent external file.
-
- it() Using tt(*from) and tt(*file) statements is allowed, but
- doesn't make sense. E.g., the following configuration sample
- is such a case:
-
- verb(\
-allowfrom 127.0.0.1 192.168.1/24
-allowfile /tmp/allow.txt)
-
- There is a technical reason for this. Once Crossroads
- processes the tt(allowfile) directive, then the whole
- whitelist is cleared (thereby removing the entries 127.0.0.1
- and 192.168.1/24), and new entries are reloaded from the
- file. The net result is that the tt(allowfrom) specification
- is overruled.)
-
-Crossroads only performs syntactic checking of the configuration. Some
-of the above samples are syntactically correct, but make no semantic
-sense: Crossroads doesn't warn for such situations.
diff --git a/doc/tips/rendering.yo b/doc/tips/rendering.yo
@@ -1,65 +0,0 @@
-The Crossroads flag tt(-x) causes the status output to be generated as
-an XML document. This format can be nicely used to render the output
-as an HTML page.
-
-E.g., the following sample shows how Crossroads reports its status in
-XML format:
-
-verb(\
-<?xml version="1.0" encoding="UTF-8"?>
-<status>
- <service id="1" name="smtp">
- <connections>1</connections>
- <lastbackend>0</lastbackend>
- <backend id="0" name="first">
- <availability id="0">available</availability>
- <clients>0</clients>
- <failures>0</failures>
- <connections>2</connections>
- <duration sec="0.559882">0.56s</duration>
- <throughput bytes="3564">3.48Kb</throughput>
- </backend>
- <backend id="1" name="second">
- <availability id="0">available</availability>
- <clients>0</clients>
- <failures>0</failures>
- <connections>2</connections>
- <duration sec="23.7636">23.76s</duration>
- <throughput bytes="9055">8.84Kb</throughput>
- </backend>
- </service>
-</status>)
-
-A custom-made XSLT transformation stylesheet can be used to convert
-this to any output format - and also to HTML. Such a style sheet is
-included in the Crossroads distribution as
-tt(etc/xml-status-to-html.xslt). The sheet is lengthy, and is
-therefore not included in this document. (You're welcome to modify it
-to suit your specific needs. If you have cool tips, send them along to
-me and I'll include them in the next distribution!)
-
-If you want to show this output in a webpage which is generated on
-demand by a webserver, then you might run into the following
-problem. The status reporter (tt(crossroads -x status))
- must be able to access the shared memory segment of the running
-Crossroads instance. By default, the shared memory is protected for
-the user that started Crossroads, which will often not be the user who
-runs the webserver. Under the auspices of the webserver user,
-tt(crossroads status) might abort with a message: "ERROR: Cannot get
-shared memory for service em(name), key em(number): Permission denied."
-
-The solution for this problem is to make the shared memory access
-somewhat more liberal. There are basically two options:
-
-itemization(
- it() Start Crossroads with the flag tt(-m 0666), which makes
- the shared memory segment available to all. The octal number
- 0666 works just like a file permission setting under
- Unix. Now, any user can run tt(crossroads status).
-
- it() If you want to make the access to Crossroads' shared
- memory somewhat stricter, then make the user who starts
- Crossroads and the user who runs the webserver member of a new
- Unix group. Start Crossroads with the flag tt(-m 0664). Now,
- users belonging to the same group as the Crossroads starter
- can run tt(crossroads status).)
diff --git a/doc/tips/scripting.yo b/doc/tips/scripting.yo
@@ -1,152 +0,0 @@
-The internal reviving model of Crossroads can periodically check
-whether back ends that are unavailable have woken up yet. The checker
-is triggered by a tt(revivinginterval) statement of a service
-description, as in:
-
-verb(\
-service web {
- port 80;
- revivinginterval 5;
-
- backend one {
- server 10.1.1.1:80;
- }
-
- backend two {
- server 10.1.1.2:80;
- }
-})
-
-This instructs Crossroads to check back ends tt(one) or tt(two) each 5
-seconds. A back end is considered available when it accepts TCP
-connections on the given IP address and port.
-
-This approach may not be sufficient in all situations. E.g., a web
-server may 'hang': it might accept a connection, but never serve
-it. Or, an application server may serve simple connections, but if its
-database is offline, it will generate internal server errors on pages
-that try to access data.
-
-In such situations you may want to replace the internal wakeup service
-with your own scripted 'health check'. Here's how:
-
-itemization(
- it() First of all, you take out the tt(revivinginterval)
- statement of tt(/etc/crossroads.conf), so that Crossroads'
- internal check which only verifies TCP connectivity is
- disabled.
-
- it() You determine a suitable URL in the applications that can
- be queried for the health. In our example this will be
- tt(/areyouthere.jsp), a hypothetical page that does some
- database access. It doesn't even need to return output; just
- succeed, or fail.
-
- it() You devise a small script that asks Crossroads the status
- of back ends of a given service (in our example, service
- tt(web)).
-
- it() The health check script starts by querying Crossroads to
- determine whether a given back end is available or not. This
- can be done via tt(crossroads -t status); the flag tt(-t)
- causes Crossroads to emit easily parsable output.
-
- it() When the service is available, the health check script
- hits a given URL and expects an answer tt(HTTP/1.x 200
- OK). When this answer is not present, the back end is marked
- unavailable. (The reason for e.g. tt(HTTP/1.x 500) might be a
- database failure, as described above.) Marking a back end as
- unavailable can be done via tt(crossroads tell) em(service)
- em(backend) tt(unavailable).
-
- it() When the service is unavailable, then the health check
- script hits the same given URL. When a tt(HTTP/1.x 200 OK)
- answer is returned, then the back end has 'woken up' and can
- be marked available (using tt(crossroads tell)).)
-
-A sample health check script that does this, is shown below. It is
-also in the Crossroads distribution as tt(etc/healthcheck). It expects
-three arguments: a testing URL, a service name, and a back end name.
-
-verb(\
-#!/usr/bin/perl
-
-use strict;
-use LWP::UserAgent;
-
-# Show usage and stop
-sub usage () {
- die <<"ENDUSAGE";
-
-Usage: healthcheck URL SERVICE BACKEND
-
-Performs a health check of the stated url and if necessary flips the
-state of the stated back end between 'available' and 'unavailable'.
-Back ends that are 'down' are not affected.
-
-ENDUSAGE
-}
-
-# Test an URL. Return whether it's a success.
-sub testurl() {
- my $ua = LWP::UserAgent->new();
- my $req = HTTP::Request->new(GET => $ARGV[0]);
- my $res = $ua->request($req);
-
- if ($res->is_success()) {
- print ("URL $ARGV[0] indicates success\n");
- return (1);
- } else {
- print ("URL $ARGV[0] indicates failure\n");
- return (0);
- }
-}
-
-# Main starts here
-usage() unless ($#ARGV == 2);
-
-# Get the current state of the back end
-open (my $if, "crossroads -t status '$ARGV[1]' '$ARGV[2]' |")
- or die ("Cannot run 'crossroads status'\n");
-my $status = <$if>;
-close ($if) or die ("'crossroads status' terminated with error\n");
-chomp ($status);
-$status =~ s{.*=}{};
-$status =~ s{\s+}{};
-
-print ("Back end $ARGV[2] has status $status\n");
-if ($status eq 'UNAVAILABLE') {
- if (testurl()) {
- print ("Back end $ARGV[2] is now available\n");
- system ("crossroads tell $ARGV[1] $ARGV[2] available")
- and die ("'crossroads tell' terminated with error\n");
- }
-} elsif ($status eq 'available') {
- if (!testurl()) {
- print ("Back end $ARGV[2] is is now UNAVAILABLE\n");
- system ("crossroads tell $ARGV[1] $ARGV[2] UNAVAILABLE")
- and die ("'crossroads tell' terminated with error\n");
- }
-} else {
- print ("No action given status '$status'\n");
-})
-
-Once you have the health checker in place, it can be run e.g. each 10
-seconds in a mini-daemon for back end tt(one):
-
-verb(\
-while [ 1 ] ; do
- healthcheck http://10.1.1.1/areyouthere.jsp web one
- sleep 10
-done)
-
-The same is run for back end tt(two):
-
-verb(\
-while [ 1 ] ; do
- healthcheck http://10.1.1.2/areyouthere.jsp web two
- sleep 10
-done)
-
-The further implementation of such a mini-daemon that fires up
-tt(healthcheck) is left to the reader.
diff --git a/doc/using.yo b/doc/using.yo
@@ -1,130 +0,0 @@
-Crossroads is started from the commandline, and highly depends on
-tt(/etc/crossroads.conf) (the default configuration file). It
-supports a number of flags (e.g., to overrule the location of the
-configuration file). The actual usage information is always obtained
-by typing tt(crossroads) without any arguments. Crossroads then
-displays the allowed arguments.
-
-The installation (see section ref(installation)) installs also a
-second program called tt(crossroads-daemon). This program is not meant
-to be started from the command line; it is administered through the
-front end tt(crossroads).
-
-subsect(General Commandline Syntax)
-
-This section shows the most basic usage. As said above, start
-tt(crossroads) without arguments to view the full listing of options.
-
-itemization(
- it() tt(crossroads start) and tt(crossroads stop) are typical
- actions that are run from system startup scripts. The
- meaning is self-explanatory.
- it() tt(crossroads restart) is a combination of the former
- two. Beware that a restart may cause discontinuity in
- service; it is just a shorthand for typing the 'stop' and
- 'start' actions after one another.
- it() tt(crossroad status) reports on each running
- service. Per service, the state of each back end is
- reported.
- it() tt(crossroads tell) em(service backend state) is a
- command line way of telling crossroads that a given back
- end, of a given service, is in a given state. Normally
- crossroads maintains state information itself, but by
- using tt(crossroads tell), a back end can be e.g. taken
- 'off line' for servicing.
- it() tt(crossroads configtest) tells you whether the
- configuration is syntactially correct.
- it() tt(crossroads services) reports on the configured
- services. In contrast to tt(crossroads status), this
- option only shows what's configured -- not what's up and
- running. Therefore, tt(crossroads services) doesn't
- report on back end states.
- it() tt(crossroads sampleconf) shows a sample configuration on
- screen. A good way of quicky viewing the configuration
- file syntax, or of getting a start for your own
- configuration tt(/etc/crossroads.conf).
-)
-
-subsect(Status Reporting)
-
-The command tt(crossroads status) shows a verbose human-readable
-report of how Crossroads is doing. When many services are configured,
-this can be a somewhat lengthy output. If you're interested in the
-overview of only one service, you can use tt(crossroads status)
-em(servicename), in which case the report will only be shown for the
-stated service.
-
-Similarly, if you're interested only in the status of a given back end
-of a given service, use tt(crossroads service) em(servicename)
-em(backendname).
-
-The flag tt(-t) causes the status overview to be abbreviated and
-displayed in a parseable format. This flag can be used in automated
-scripts that check how Crossroads is doing; e.g., in health checking
-scripts. When tt(-t) is used, the format of the status reporter is as
-follows:
-
-itemization(
- it() Service health is reported on one line per service.
- it() The first string on the line is the service name.
- it() After this, a series follows of em(backendname=state),
- where the back end name is the configured name of the back
- end, and where state is e.g. tt(available), tt(DOWN),
- tt(UNAVAILABLE), tt(WAKING). All statuses that cause
- Crossroads not to use the back end are in caps. The series is
- repeated for all back ends of the given service.)
-
-The flag tt(-x) causes the overview to be presented as an XML
-document. This can be handy if you want to further automate the
-control over Crossroads, or if you want to show the status via the web.
-
-
-subsect(Logging-related options)
-
-Two 'flags' of Crossroads are specifically logging-related. This
-section elaborates on these flags.
-
-First, there's flag tt(-a). When present, the start and end of
-activity is logged using statements like
-
-center(em(YYYY-MM-DD HH/MM/SS starting http from 61.45.32.189 to 10.1.1.1))
-
-Similarly, there are 'ending' statements. Using this flag and
-scanning your logs for these statements may be helpful in quickly
-determining your system load.
-
-Second, there's flag tt(-l). This flag selects the 'facility' of
-logging and defaults to tt(LOG_DAEMON). You can supply a number
-between 0 and 7 to flag tt(-l) to select tt(LOG_LOCAL0) to
-tt(LOG_LOCAL7). This would separate the Crossroads-related logging
-from other streams. Here's a very short guide; please read your Unix
-manpages of tt(syslogd) for more information.
-
-itemization(
- it() First edit tt(/etc/syslog.conf) and add a line:
-
- verb(local7.* /var/log/crossroads.log)
-
- That instructs tt(syslogd) to send tt(LOG_LOCAL7) requests to the
- logfile tt(/var/log/crossroads.log).
-
- it() Next, restart tt(syslogd). On most Unices that's done by
- issuing tt(killall -1 syslogd). (As a side-note, I tried this once
- on an Bull/AIX system, and the box just shut down. The tt(killall)
- command killed every process...)
-
- it() Now start tt(crossroads) with the flag tt(-l7).
-
- it() Finally, monitor tt(/var/log/crossroads.log) for Crossroads'
- messages.)
-
-
-subsect(Reloading Configurations)
-
-Crossroads doesn't support the reloading of a configuration while
-running (such as other programs, e.g. Apache do). There are various
-technical reasons for this.
-
-However, external lists of allowed or denied IP addresses can be
-reloaded by sending a signal -1 (tt(SIGHUP)) to Crossroads. See
-section ref(servicedef) for the details.
diff --git a/etc/Makefile.conf b/etc/Makefile.conf
@@ -8,12 +8,16 @@ LIBS := $(shell $(BASE)/tools/c-conf -c $(BASE)/src/c-conf.cache lib \
# Compiletime defines. Remember to update show_config() when changing
# this list!
DEFS := -DDEFAULT_CONF='"$(DEFAULT_CONF)"' -DMAX_BACKEND=$(MAX_BACKEND) \
- -DSHM_MASK=$(SHM_MASK) -DSLEEP_TIME=$(SLEEP_TIME) \
+ -DSLEEP_TIME=$(SLEEP_TIME) -DDNS_CACHESIZE=$(DNS_CACHESIZE) \
+ -DDNS_CACHETTL=$(DNS_CACHETTL) -DDEF_MAX=$(DEF_MAX) \
-DCONNECT_TIMEOUT=$(CONNECT_TIMEOUT) -DVER='"$(VER)/$(REVVER)"' \
-DSET_PROC_TITLE_BY_ARGV=$(SET_PROC_TITLE_BY_ARGV) \
-DTCP_BUFSZ=$(TCP_BUFSZ) -DRETRY_WAIT=$(RETRY_WAIT) \
-DREVVER='"$(REVVER)"' -DBINDIR='"$(BINDIR)"' \
+ -DPREFIX='"$(PREFIX)"' -DYEARS='"$(YEARS)"' \
-DEXTRALIBS='"$(EXTRALIBS)"' -DLIBS='"$(LIBS)"' \
+ -DAUTHORNAME='"$(AUTHORNAME)"' -DMAINTAINERNAME='"$(MAINTAINERNAME)"' \
+ -DMAINTAINEREMAIL='"$(MAINTAINEREMAIL)"' \
$(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 \
diff --git a/etc/Makefile.def b/etc/Makefile.def
@@ -6,7 +6,15 @@
# Versioning. This defines the overall version ID and must match the topmost
# entry in the ChangeLog.
-VER = 1.42
+VER = 1.44
+
+# Years that Crossroads has been 'round.
+YEARS = 2005-2007
+
+# Author and maintainer
+AUTHORNAME = Karel Kubat
+MAINTAINERNAME = Karel Kubat
+MAINTAINEREMAIL = karel@kubat.nl
# Revision version, auto-detected.
REVVER = $(shell $(BASE)/etc/svnrev $(BASE)/ChangeLog $(BASE)/etc/svnrev.txt)
@@ -18,9 +26,6 @@ DEFAULT_CONF = /etc/crossroads.conf
# because it defines the size of the shared memory that crossroads claims.
MAX_BACKEND = 20
-# Magic mask for shared memory keys.
-SHM_MASK = 0x19081962
-
# Sleep time (sec). When we detect that there are too many clients, or
# no back ends, then we'll wait during this period.
SLEEP_TIME = 10
@@ -38,15 +43,26 @@ RETRY_WAIT = 1
# The size of buffers for the copying of data between sockets.
TCP_BUFSZ = 10240
-# The directory where the crossroads program will be installed. Note that
-# the docs aren't installed by default; you have to do that by hand.
-# For the bindir, we like to use EBINDIR, but supply a name if EBINDIR
-# isn't set.
-ifeq ($(strip $(EBINDIR)),)
-BINDIR ?= /usr/local/bin
-else
-BINDIR ?= $(EBINDIR)
-endif
+# The max size of the DNS cache (nr of entries). Crossroads will cache
+# gethostbyname() results until the max nr is exceeded; then the latest hits
+# will be killed off.
+DNS_CACHESIZE = 20
+
+# The max age of a DNS cache entry, before it is considered obsolete.
+# Value is in seconds; so e.g. 900 is 15 minutes, 3600 is 1 hour.
+# Value 0 suppresses DNS caching. This can always be overruled using the
+# flag -d.
+DNS_CACHETTL = 0
+
+# The number of #define expansions before Crossroads thinks it's a
+# circular definition. Also the max nr of #defines that's allowed in one file.
+DEF_MAX = 1000
+
+# Prefix directory for the install processs.
+PREFIX = /usr/local
+
+# Installation directory for the binaries.
+BINDIR = $(PREFIX)/bin
# If you're on Linux, then one can set the program title for 'ps' output
# by modifying argv directly. If you're on Linux or if your system supports
@@ -57,4 +73,3 @@ SET_PROC_TITLE_BY_ARGV = 1
# fiddle with LD_LIBRARY_PATH or crle (yuk!)
# EXTRALIBS = -R/usr/ucblib
EXTRALIBS =
-
diff --git a/etc/svnrev.txt b/etc/svnrev.txt
@@ -1 +1 @@
-154
+163
diff --git a/src/crossroads-daemon/Makefile b/src/crossroads-daemon/Makefile
@@ -9,17 +9,18 @@ install: all $(BINDIR)/$(BIN)
clean:
rm -f *.o $(BIN)
-$(BINDIR)/$(BIN): $(BIN) ../lib/libcrossroads.a
+$(BINDIR)/$(BIN): $(BIN)
cp $(BIN) $(BINDIR)/$(BIN)
strip $(BINDIR)/$(BIN)
main.o: main.c
$(CC) -c -g -W -Wall $(DEFS) main.c
-$(BIN): main.o
+$(BIN): main.o ../lib/libcrossroads.a
$(CC) -o $(BIN) main.o -L$(BASE)/src/lib -lcrossroads \
$(LIBS) $(EXTRALIBS)
# Extra deps:
-main.o: main.c $(BASE)/src/crossroads.h $(BASE)/etc/Makefile.def
+main.o: main.c $(BASE)/src/crossroads.h $(BASE)/etc/Makefile.def \
+ ../shared/parseopt.inc
diff --git a/src/crossroads-daemon/main.c b/src/crossroads-daemon/main.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -13,67 +13,9 @@ int main (int argc, char **argv) {
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");
- }
+ /* Parse the command line. */
+ #define TARGET_CROSSROADS_DAEMON
+ #include "../shared/parseopt.inc"
/* We're the daemon executable. We know what to do -- serve. */
create_commandline_space();
diff --git a/src/crossroads.h b/src/crossroads.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -15,7 +15,6 @@
#endif
#include <math.h>
#include <pwd.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -59,6 +58,19 @@
#endif
/* Types. */
+
+typedef struct { /* Symbol table for #define */
+ char *symbol;
+ char *redef;
+} Symtab;
+
+typedef struct { /* Bison/Flex state given files */
+ char *name;
+ FILE *file;
+ int lineno;
+ char *buf;
+} ParserState;
+
typedef enum { /* Config parsing related */
cf_portspec,
cf_verbosityspec,
@@ -255,6 +267,12 @@ typedef struct { /* Numeric state to string map */
char *nm;
} StateStringMap;
+typedef struct { /* DNS cache related */
+ char *hostname; /* resolved name */
+ struct in_addr hostaddr; /* resolved host info entry */
+ time_t stamp; /* date of cache entry */
+} DnsCache;
+
/* Globals. */
#ifndef EXTERN
#define EXTERN extern
@@ -267,6 +285,8 @@ EXTERN char *client_ip; /* connected client */
EXTERN char *config_file; /* config to parse */
EXTERN int current_backend; /* of a given service */
EXTERN int daemonized; /* are we forked off yet */
+EXTERN DnsCache dnscache[]; /* DNS cache */
+EXTERN int dns_cachettl; /* TTL of DNS cache entries */
EXTERN int flag_verbose; /* flag: verbosity */
EXTERN int gid_org, gid_set; /* original gid, flag: changed? */
EXTERN int iflag_present; /* flag: -i present */
@@ -279,6 +299,8 @@ EXTERN int logstarted; /* was syslog() called yet? */
EXTERN int nservice; /* # service descriptions */
EXTERN int org_argc; /* original argc */
EXTERN char **org_argv; /* and original argv */
+EXTERN ParserState *parserstate; /* parser state */
+EXTERN int nparserstate; /* size of array */
EXTERN Programstage program_stage; /* stage of the program */
EXTERN int relevant_sigs[]; /* relevant signals */
EXTERN int reload_allow_deny; /* flag to reload spec files */
@@ -291,6 +313,8 @@ EXTERN unsigned char *srbuf; /* server socket input buffer */
EXTERN int srbufpos, srbufmax; /* .. position & bytes */
EXTERN StateStringMap /* state/string map */
statestringmap[]; /* .. and vv */
+EXTERN Symtab *symtab; /* symbol table of #defines */
+EXTERN int nsymtab; /* table size */
EXTERN int tabular_status; /* -t: tabular status overview */
EXTERN int uid_org, uid_set; /* original uid, flag: changed? */
EXTERN int xml_status; /* -x: XML status overview */
@@ -316,6 +340,7 @@ extern int configtest (int ac, char **av);
extern void create_commandline_space (void);
extern void decr_client_count (void);
extern void dealloc_reporter (Service *s);
+extern struct in_addr *dns (char const *hostname);
extern void error (char const *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
extern int fork_tcp_servicer (int to_backend);
@@ -371,6 +396,13 @@ extern unsigned char *net_bufread (int sock, int maxbytes,
int *nreadp, int is_client);
extern int net_write (int sock, unsigned char const *buf, int len,
int is_client);
+extern int parser_close();
+extern char const *parser_filename(void);
+extern void parser_open (char const *name);
+extern int parser_input (char *buf, int max);
+extern void parser_run(void);
+extern void parser_skipchar(void);
+extern void parser_skipline(void);
extern int restart (int ac, char **av);
extern void runservice (void);
extern int serve (int ac, char **av);
@@ -387,6 +419,10 @@ extern char *str_expand_format (char const *h);
extern char *str_printf (char const *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
extern char *str_vprintf (char const *fmt, va_list args);
+extern void symtab_end (void);
+extern char const *symtab_lookup (char const *txt);
+extern void symtab_set (char const *symbol);
+extern void symtab_start (char const *symbol);
extern void sysrun (char const *cmd);
extern void tcpserve (int sock);
extern int tell_service (int ac, char **av);
diff --git a/src/crossroads/Makefile b/src/crossroads/Makefile
@@ -21,4 +21,6 @@ $(BIN): main.o ../lib/libcrossroads.a
$(LIBS) $(EXTRALIBS)
# Extra deps:
-main.o: main.c $(BASE)/src/crossroads.h $(BASE)/etc/Makefile.def
+main.o: main.c $(BASE)/src/crossroads.h $(BASE)/etc/Makefile.def \
+ ../shared/parseopt.inc
+
diff --git a/src/crossroads/main.c b/src/crossroads/main.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -32,85 +32,9 @@ int main (int argc, char **argv) {
org_argc = argc;
org_argv = argv;
- /* Parse options. */
- config_file = DEFAULT_CONF;
- while ( (opt = getopt (argc, argv, "b?c:fhvi:Val:stCm:x")) > 0 )
- switch (opt) {
- case 'a':
- log_activity++;
- break;
- case 'b':
- msg ("Parsing configuration %s", config_file);
- if (! (yyin = fopen (config_file, "r")) )
- error ("Cannot read configuration %s: %s",
- config_file, strerror(errno));
- yyparse ();
- fclose (yyin);
- config_write (1);
- exit (0);
- 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:
- usage();
- }
- break;
- case 'm':
- shmperm = strtol (optarg, 0, 8);
- break;
- case 's':
- sloppyportbind++;
- break;
- case 't':
- tabular_status++;
- break;
- case 'x':
- xml_status++;
- break;
- case 'C':
- show_config();
- exit (0);
- case 'V':
- puts (VER);
- exit (0);
- case '?':
- case 'h':
- default:
- usage ();
- }
+ /* Parse the command line. */
+ #define TARGET_CROSSROADS
+ #include "../shared/parseopt.inc"
/* We need at last one argument: the action */
if (optind >= argc)
@@ -126,12 +50,9 @@ int main (int argc, char **argv) {
(handler[i].narg == -1 ||
handler[i].narg == argc - optind - 1)) {
if (handler[i].needconf) {
- msg ("Parsing configuration %s", config_file);
- if (! (yyin = fopen (config_file, "r")) )
- error ("Cannot read configuration %s: %s",
- config_file, strerror(errno));
- yyparse();
- fclose (yyin);
+ parser_open (config_file);
+ parser_run();
+ parser_close();
}
if (!handler[i].handler (argc - optind, argv + optind + 1))
error ("'%s' failed", argv[optind]);
diff --git a/src/lib/Makefile b/src/lib/Makefile
@@ -2,17 +2,17 @@ include $(BASE)/etc/Makefile.def
include $(BASE)/etc/Makefile.conf
LIB = libcrossroads.a
+SRC := $(wildcard *.c)
+OBJ := $(patsubst %.c, %.o, $(SRC))
all:
BASE=$(BASE) make textconv
BASE=$(BASE) make grammar
- BASE=$(BASE) make lib
+ BASE=$(BASE) make $(LIB)
install: all
-lib: $(LIB)
-
-$(LIB): objects
+$(LIB): $(OBJ)
ar rs $(LIB) $(OBJ)
ranlib $(LIB)
@@ -26,12 +26,10 @@ proxyerror.h: proxyerror.txt
grammar: parser.c lexer.c
lexer.c: lexer.l
- flex -o$@ $<
+ flex -I -o$@ $<
parser.c: parser.y
bison -d -o $@ $<
-SRC := $(wildcard *.c)
-OBJ := $(patsubst %.c, %.o, $(SRC))
objects: $(OBJ)
@@ -51,3 +49,4 @@ clean:
# Extra deps:
strexpandformat.o: strexpandformat.c $(BASE)/etc/Makefile.def
showconfig.o: showconfig.c $(BASE)/etc/Makefile.def Makefile
+data.o: data.c $(BASE)/src/crossroads.h
diff --git a/src/lib/allocreporter.c b/src/lib/allocreporter.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ansistamp.c b/src/lib/ansistamp.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/backendavailable.c b/src/lib/backendavailable.c
@@ -1,8 +1,9 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, 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 backend_available (int target) {
diff --git a/src/lib/backendconnect.c b/src/lib/backendconnect.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/backendcount.c b/src/lib/backendcount.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/choosebackend.c b/src/lib/choosebackend.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/configread.c b/src/lib/configread.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/configtest.c b/src/lib/configtest.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/configwrite.c b/src/lib/configwrite.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/copysockets.c b/src/lib/copysockets.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/createcommandlinespace.c b/src/lib/createcommandlinespace.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/data.c b/src/lib/data.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -11,6 +11,8 @@
int log_facility = LOG_DAEMON;
int shmperm = 0644;
+int dns_cachettl = DNS_CACHETTL;
+char *config_file = DEFAULT_CONF;
StateStringMap statestringmap[] = {
{ st_available, "available" },
@@ -33,3 +35,5 @@ int relevant_sigs[] = { /* signals relevant to this app */
SIGTERM,
0,
};
+
+DnsCache dnscache[DNS_CACHESIZE]; /* The DNS cache */
diff --git a/src/lib/deallocreporter.c b/src/lib/deallocreporter.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/decrclientcount.c b/src/lib/decrclientcount.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/dns.c b/src/lib/dns.c
@@ -0,0 +1,99 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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"
+
+// #define DEBUG
+
+static int noncache_resolve (char const *hostname, struct in_addr *res) {
+ struct hostent *hent;
+
+ if (! (hent = gethostbyname(hostname)) )
+ return (0);
+ *res = *(struct in_addr *)hent->h_addr;
+ return (1);
+}
+
+struct in_addr *dns (char const *hostname) {
+ int i, target = -1;
+ time_t now, age, min;
+
+ /* No cache TTL? No caching. We use slot 0 for storage of the
+ * intermediate result. */
+ if (!dns_cachettl) {
+ if (noncache_resolve (hostname, &dnscache[0].hostaddr))
+ return (&dnscache[0].hostaddr);
+ return (0);
+ }
+
+ /* Current time */
+ now = time (0);
+
+ #ifdef DEBUG
+ if (program_stage != stage_retrying) {
+ msg ("dnscache: now %d", now);
+ for (i = 0; i < DNS_CACHESIZE; i++)
+ msg ("dnscache[%d].hostname: %s, dnscache[%d].stamp: %d",
+ i, dnscache[i].hostname, i, (int)dnscache[i].stamp);
+ }
+ #endif
+
+ /* See if we still have the hostname. If so, if the TTL isn't
+ * exceeded, return that. */
+ for (i = 0; i < DNS_CACHESIZE && dnscache[i].hostname; i++) {
+ if (!strcmp (dnscache[i].hostname, hostname)) {
+ age = now - dnscache[i].stamp;
+ if (age <= dns_cachettl) {
+ if (program_stage != stage_retrying)
+ msg ("Service %s: host %s resolved from cache slot %d "
+ "(age: %d sec)",
+ activeservice->name, hostname, i, (int)age);
+ return (&(dnscache[i].hostaddr));
+ } else {
+ if (program_stage != stage_retrying)
+ msg ("Service %s: host entry for %s is too old at slot %d "
+ "(age: %d sec, ttl %d sec)",
+ activeservice->name, hostname, i, (int)age,
+ dns_cachettl);
+ target = i;
+ break;
+ }
+ }
+ }
+
+ /* We failed to return from cache. If target isn't set yet, set it. */
+ if (target == -1) {
+ if (i < DNS_CACHESIZE) {
+ target = i;
+ if (program_stage != stage_retrying)
+ msg ("Service %s: host entry '%s' at slot %d will be added",
+ activeservice->name, hostname, target);
+ } else {
+ for (i = 0; i < DNS_CACHESIZE; i++)
+ if (i == 0 || dnscache[i].stamp < min) {
+ target = i;
+ min = dnscache[i].stamp;
+
+ }
+ if (program_stage != stage_retrying)
+ msg ("Service %s: host entry '%s' at slot %d "
+ "will be overwritten",
+ activeservice->name, hostname, target);
+ }
+ }
+
+ /* Get the name, and stick it in the cache if it's a resolved entry,
+ * return the result.*/
+ if (noncache_resolve (hostname, &dnscache[i].hostaddr)) {
+ free (dnscache[i].hostname);
+ dnscache[i].hostname = xstrdup (hostname);
+ dnscache[i].stamp = now;
+ return (&dnscache[i].hostaddr);
+ }
+
+ /* Failed, return a NULL ptr. */
+ return (0);
+}
diff --git a/src/lib/error.c b/src/lib/error.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/forktcpservicer.c b/src/lib/forktcpservicer.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/hashpjw.c b/src/lib/hashpjw.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpcopy.c b/src/lib/httpcopy.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httperror.c b/src/lib/httperror.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderaddheader.c b/src/lib/httpheaderaddheader.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderappendheader.c b/src/lib/httpheaderappendheader.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderconnectiontype.c b/src/lib/httpheaderconnectiontype.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderfree.c b/src/lib/httpheaderfree.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderhascookie.c b/src/lib/httpheaderhascookie.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderhttpver.c b/src/lib/httpheaderhttpver.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheadernew.c b/src/lib/httpheadernew.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderread.c b/src/lib/httpheaderread.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderremoveheader.c b/src/lib/httpheaderremoveheader.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheadersetheader.c b/src/lib/httpheadersetheader.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderval.c b/src/lib/httpheaderval.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpheaderwrite.c b/src/lib/httpheaderwrite.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpinsertheader.c b/src/lib/httpinsertheader.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpserve.c b/src/lib/httpserve.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpserversocket.c b/src/lib/httpserversocket.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/httpwrite.c b/src/lib/httpwrite.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/incrclientcount.c b/src/lib/incrclientcount.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/initsockaddr.c b/src/lib/initsockaddr.c
@@ -1,21 +1,22 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, 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 init_sockaddr (struct sockaddr_in *name,
const char *hostname, int port) {
- struct hostent *hostinfo;
+ struct in_addr *hostaddr;
if (program_stage != stage_retrying)
msg ("Service %s: trying to connect to backend %s:%d",
activeservice->name, hostname, port);
name->sin_family = AF_INET;
name->sin_port = htons (port);
- if (! (hostinfo = gethostbyname (hostname)) )
+ if (! (hostaddr = dns (hostname)) )
return (1);
- name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
+ name->sin_addr = *hostaddr;
return (0);
}
diff --git a/src/lib/interrupt.c b/src/lib/interrupt.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfaddallow.c b/src/lib/ipfaddallow.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfadddeny.c b/src/lib/ipfadddeny.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfallowed.c b/src/lib/ipfallowed.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfdenied.c b/src/lib/ipfdenied.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfloadfile.c b/src/lib/ipfloadfile.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfmatch.c b/src/lib/ipfmatch.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ipfparse.c b/src/lib/ipfparse.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/ishexdigit.c b/src/lib/ishexdigit.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/isspace.c b/src/lib/isspace.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/lexer.c b/src/lib/lexer.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -288,56 +288,60 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
*yy_cp = '\0'; \
yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 66
-#define YY_END_OF_BUFFER 67
-static yyconst short int yy_accept[416] =
+#define YY_NUM_RULES 78
+#define YY_END_OF_BUFFER 79
+static yyconst short int yy_accept[455] =
{ 0,
- 0, 0, 0, 0, 0, 0, 67, 55, 53, 54,
- 55, 55, 52, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 64, 65, 63, 64, 64, 62, 59, 58,
- 59, 53, 0, 1, 56, 0, 52, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 50, 51, 49, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 0, 60, 0, 61, 57, 0, 2, 51, 51,
- 29, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 49, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 31, 51, 51, 51,
- 51, 6, 5, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 28, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 15, 51, 51, 51, 51, 51, 37, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 4, 51, 51, 51, 51, 21, 51, 51, 51,
- 51, 51, 51, 51, 36, 51, 19, 51, 51, 51,
- 16, 51, 51, 51, 7, 51, 51, 51, 51, 51,
- 14, 51, 51, 51, 51, 51, 51, 8, 9, 51,
- 51, 51, 22, 51, 51, 51, 51, 51, 51, 51,
- 35, 10, 51, 51, 3, 51, 51, 51, 51, 51,
- 51, 51, 11, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 48, 46, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
-
- 51, 51, 47, 45, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 25, 51, 20,
- 51, 51, 51, 51, 51, 51, 18, 51, 51, 51,
- 30, 51, 33, 51, 51, 51, 51, 51, 51, 51,
- 51, 34, 51, 51, 51, 51, 51, 51, 51, 26,
- 51, 51, 51, 51, 51, 51, 17, 51, 51, 51,
- 51, 51, 38, 51, 51, 51, 51, 51, 23, 51,
- 51, 51, 51, 51, 51, 32, 51, 51, 51, 51,
- 51, 51, 13, 51, 51, 51, 39, 42, 51, 51,
-
- 51, 24, 51, 40, 43, 51, 51, 51, 27, 51,
- 51, 12, 41, 44, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 75, 75, 76, 76, 79, 56, 54, 55, 56, 53,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 56,
+ 65, 66, 64, 65, 65, 63, 60, 59, 60, 70,
+ 68, 68, 67, 74, 73, 71, 72, 71, 78, 75,
+ 76, 77, 54, 57, 0, 53, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 51, 52, 50, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+
+ 0, 0, 0, 0, 61, 0, 62, 58, 67, 71,
+ 72, 71, 75, 76, 0, 3, 52, 52, 30, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 50, 0, 0, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 32, 52, 52, 52,
+ 52, 7, 6, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 29, 52, 52, 52, 0, 0,
+
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 16, 52, 52, 52, 52, 52, 38,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 0, 0, 52,
+ 52, 52, 52, 52, 52, 5, 52, 52, 52, 52,
+ 22, 52, 52, 52, 52, 52, 52, 52, 37, 52,
+ 20, 52, 52, 52, 17, 52, 52, 52, 8, 52,
+ 52, 52, 52, 52, 15, 0, 0, 52, 52, 52,
+ 52, 52, 52, 9, 10, 52, 52, 52, 23, 52,
+ 52, 52, 52, 52, 52, 52, 36, 11, 52, 52,
+
+ 4, 52, 52, 52, 52, 52, 52, 52, 12, 52,
+ 2, 0, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 49, 47, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 1, 52,
+ 52, 48, 46, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 52, 52, 26, 52, 21, 52,
+ 52, 52, 52, 52, 52, 19, 52, 52, 52, 31,
+ 52, 34, 52, 52, 52, 52, 52, 52, 52, 52,
+ 35, 52, 52, 52, 52, 52, 52, 52, 27, 52,
+
+ 52, 52, 52, 52, 52, 18, 52, 52, 52, 52,
+ 52, 39, 52, 52, 52, 52, 52, 24, 52, 52,
+ 52, 52, 52, 52, 33, 52, 52, 52, 52, 52,
+ 52, 14, 52, 52, 52, 40, 43, 52, 52, 52,
+ 25, 52, 41, 44, 52, 52, 52, 28, 52, 52,
+ 13, 42, 45, 0
} ;
static yyconst int yy_ec[256] =
@@ -346,16 +350,16 @@ static yyconst int yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 4, 1, 5, 6, 1, 1, 1, 7, 1,
- 1, 8, 1, 1, 1, 1, 9, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 1, 11, 1,
- 1, 1, 1, 1, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 1, 1, 1, 1, 12, 1, 13, 14, 15, 16,
-
- 17, 18, 19, 20, 21, 12, 22, 23, 24, 25,
- 26, 27, 12, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 8, 1, 1, 9, 9, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 9, 12, 9,
+ 1, 9, 1, 1, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 1, 9, 1, 1, 13, 1, 14, 15, 16, 17,
+
+ 18, 19, 20, 21, 22, 13, 23, 24, 25, 26,
+ 27, 28, 13, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -372,228 +376,262 @@ static yyconst int yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst int yy_meta[37] =
+static yyconst int yy_meta[38] =
{ 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
- 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2
+ 1, 1, 2, 1, 3, 1, 1, 1, 3, 3,
+ 4, 1, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4
} ;
-static yyconst short int yy_base[423] =
+static yyconst short int yy_base[468] =
{ 0,
- 0, 0, 34, 39, 44, 45, 444, 445, 47, 445,
- 440, 46, 432, 0, 40, 45, 415, 40, 406, 426,
- 408, 424, 410, 44, 409, 47, 55, 54, 405, 416,
- 415, 414, 445, 445, 445, 425, 422, 445, 445, 445,
- 419, 66, 424, 445, 445, 423, 415, 0, 408, 400,
- 387, 394, 405, 394, 62, 393, 68, 388, 392, 385,
- 391, 383, 378, 0, 393, 69, 393, 381, 383, 49,
- 376, 62, 382, 384, 376, 71, 376, 385, 373, 379,
- 370, 393, 445, 390, 445, 445, 393, 445, 79, 369,
- 0, 377, 371, 376, 73, 360, 362, 368, 363, 374,
-
- 351, 358, 357, 366, 353, 354, 365, 354, 365, 347,
- 348, 345, 358, 345, 351, 346, 338, 80, 347, 353,
- 341, 348, 348, 347, 335, 348, 342, 0, 337, 342,
- 325, 332, 80, 326, 334, 329, 325, 336, 315, 333,
- 314, 330, 334, 316, 317, 327, 0, 317, 326, 320,
- 327, 0, 0, 313, 317, 305, 320, 83, 312, 317,
- 316, 310, 300, 312, 0, 316, 302, 307, 305, 297,
- 306, 307, 297, 295, 294, 302, 293, 304, 299, 298,
- 299, 0, 84, 283, 284, 286, 285, 0, 286, 280,
- 283, 289, 284, 276, 275, 287, 280, 272, 264, 263,
-
- 278, 275, 280, 265, 263, 275, 259, 85, 86, 274,
- 270, 0, 263, 270, 256, 257, 0, 254, 260, 256,
- 266, 267, 266, 253, 0, 247, 0, 247, 250, 248,
- 0, 256, 255, 239, 0, 96, 250, 254, 253, 93,
- 0, 242, 249, 242, 238, 240, 245, 0, 0, 231,
- 245, 238, 0, 237, 240, 232, 235, 236, 230, 235,
- 0, 0, 232, 236, 0, 224, 231, 221, 216, 218,
- 221, 217, 0, 212, 211, 212, 222, 214, 216, 208,
- 214, 204, 207, 206, 0, 0, 207, 212, 209, 213,
- 206, 205, 195, 196, 197, 192, 190, 194, 188, 183,
-
- 197, 196, 0, 0, 198, 182, 186, 191, 186, 185,
- 183, 187, 194, 176, 180, 179, 183, 182, 179, 173,
- 169, 179, 172, 179, 178, 169, 176, 0, 166, 0,
- 161, 174, 174, 163, 166, 156, 0, 168, 167, 162,
- 0, 159, 0, 151, 167, 166, 148, 149, 151, 154,
- 157, 0, 157, 146, 154, 157, 156, 151, 141, 0,
- 150, 149, 144, 143, 133, 137, 0, 137, 134, 130,
- 141, 140, 0, 136, 137, 136, 135, 134, 0, 133,
- 132, 119, 115, 129, 128, 0, 116, 115, 129, 128,
- 114, 111, 0, 125, 109, 108, 0, 0, 119, 118,
-
- 102, 0, 109, 0, 0, 114, 113, 99, 0, 79,
- 31, 0, 0, 0, 445, 116, 118, 120, 38, 122,
- 124, 126
+ 0, 549, 35, 41, 46, 47, 55, 67, 79, 109,
+ 62, 74, 551, 550, 552, 556, 39, 556, 84, 540,
+ 0, 76, 108, 523, 105, 514, 534, 516, 532, 518,
+ 105, 517, 81, 111, 104, 513, 524, 523, 522, 124,
+ 556, 556, 556, 534, 531, 556, 556, 556, 527, 556,
+ 556, 556, 0, 556, 556, 68, 0, 130, 556, 99,
+ 0, 556, 103, 556, 533, 524, 0, 517, 509, 496,
+ 503, 514, 503, 131, 502, 80, 497, 501, 494, 500,
+ 492, 487, 0, 502, 132, 502, 490, 492, 112, 485,
+ 123, 491, 493, 485, 121, 485, 494, 482, 488, 479,
+
+ 153, 490, 481, 501, 556, 498, 556, 556, 0, 152,
+ 0, 155, 161, 0, 501, 556, 148, 476, 0, 484,
+ 478, 483, 142, 467, 469, 475, 470, 481, 458, 465,
+ 464, 473, 460, 461, 472, 461, 472, 454, 455, 452,
+ 465, 452, 458, 453, 445, 151, 454, 460, 448, 455,
+ 455, 454, 442, 455, 449, 0, 449, 451, 442, 447,
+ 430, 437, 150, 431, 439, 434, 430, 441, 420, 438,
+ 419, 435, 439, 421, 422, 432, 0, 422, 431, 425,
+ 432, 0, 0, 418, 422, 410, 425, 154, 417, 422,
+ 421, 415, 405, 417, 0, 421, 407, 412, 410, 407,
+
+ 408, 400, 409, 410, 400, 398, 397, 405, 396, 407,
+ 402, 401, 402, 0, 151, 386, 387, 389, 388, 0,
+ 389, 383, 386, 392, 387, 379, 378, 390, 383, 375,
+ 367, 366, 381, 378, 383, 368, 366, 370, 363, 376,
+ 360, 155, 163, 375, 371, 0, 364, 371, 357, 358,
+ 0, 355, 361, 357, 367, 368, 367, 354, 0, 348,
+ 0, 348, 351, 349, 0, 357, 356, 340, 0, 167,
+ 351, 355, 354, 168, 0, 351, 351, 341, 348, 341,
+ 337, 339, 344, 0, 0, 330, 344, 337, 0, 336,
+ 339, 331, 334, 335, 329, 334, 0, 0, 331, 335,
+
+ 0, 323, 330, 320, 315, 317, 320, 316, 0, 311,
+ 556, 323, 309, 310, 320, 312, 314, 306, 312, 302,
+ 305, 304, 0, 0, 305, 310, 307, 311, 304, 303,
+ 293, 294, 295, 290, 288, 292, 286, 281, 556, 295,
+ 294, 0, 0, 296, 280, 284, 289, 284, 283, 281,
+ 285, 292, 274, 278, 277, 281, 280, 277, 271, 267,
+ 277, 270, 277, 276, 267, 274, 0, 264, 0, 259,
+ 272, 272, 261, 264, 254, 0, 266, 265, 260, 0,
+ 257, 0, 249, 265, 264, 246, 247, 249, 252, 255,
+ 0, 255, 244, 252, 255, 254, 249, 239, 0, 248,
+
+ 247, 242, 241, 231, 235, 0, 235, 232, 228, 239,
+ 238, 0, 234, 235, 234, 233, 232, 0, 231, 230,
+ 217, 213, 227, 226, 0, 214, 213, 227, 226, 212,
+ 209, 0, 223, 207, 200, 0, 0, 175, 174, 157,
+ 0, 163, 0, 0, 153, 131, 105, 0, 68, 31,
+ 0, 0, 0, 556, 193, 197, 201, 205, 209, 213,
+ 48, 217, 221, 223, 47, 227, 231
} ;
-static yyconst short int yy_def[423] =
+static yyconst short int yy_def[468] =
{ 0,
- 415, 1, 416, 416, 417, 417, 415, 415, 415, 415,
- 418, 415, 415, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 415, 415, 415, 420, 421, 415, 415, 415,
- 415, 415, 418, 415, 415, 422, 415, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 420, 415, 421, 415, 415, 422, 415, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
-
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
-
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
-
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
-
- 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 0, 415, 415, 415, 415, 415,
- 415, 415
+ 454, 1, 455, 455, 456, 456, 457, 457, 458, 458,
+ 459, 459, 460, 460, 454, 454, 454, 454, 454, 454,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 454,
+ 454, 454, 454, 462, 463, 454, 454, 454, 454, 454,
+ 454, 454, 464, 454, 454, 454, 465, 465, 454, 454,
+ 466, 454, 454, 454, 467, 454, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+
+ 454, 454, 454, 462, 454, 463, 454, 454, 464, 454,
+ 465, 465, 454, 466, 467, 454, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 454, 454, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 454, 454,
+
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 454, 454, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 454, 454, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 454, 454, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 454, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461,
+ 461, 461, 461, 0, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454
} ;
-static yyconst short int yy_nxt[482] =
+static yyconst short int yy_nxt[594] =
{ 0,
- 8, 9, 10, 9, 8, 11, 8, 8, 12, 13,
- 8, 14, 15, 16, 17, 18, 19, 20, 14, 21,
- 14, 14, 14, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 14, 32, 14, 34, 35, 36, 48,
- 37, 34, 35, 36, 38, 37, 40, 40, 42, 38,
- 42, 41, 41, 45, 46, 49, 57, 53, 414, 69,
- 58, 65, 50, 70, 51, 54, 52, 42, 66, 42,
- 59, 72, 71, 75, 73, 67, 95, 96, 114, 55,
- 115, 76, 100, 122, 74, 108, 109, 97, 77, 117,
- 98, 118, 101, 129, 159, 135, 173, 110, 136, 195,
-
- 246, 123, 174, 196, 219, 244, 413, 130, 160, 273,
- 268, 220, 245, 274, 247, 269, 33, 33, 39, 39,
- 43, 43, 82, 82, 84, 84, 87, 87, 412, 411,
- 410, 409, 408, 407, 406, 405, 404, 403, 402, 401,
- 400, 399, 398, 397, 396, 395, 394, 393, 392, 391,
- 390, 389, 388, 387, 386, 385, 384, 383, 382, 381,
- 380, 379, 378, 377, 376, 375, 374, 373, 372, 371,
- 370, 369, 368, 367, 366, 365, 364, 363, 362, 361,
- 360, 359, 358, 357, 356, 355, 354, 353, 352, 351,
- 350, 349, 348, 347, 346, 345, 344, 343, 342, 341,
-
- 340, 339, 338, 337, 336, 335, 334, 333, 332, 331,
- 330, 329, 328, 327, 326, 325, 324, 273, 323, 322,
- 321, 320, 319, 318, 317, 316, 315, 314, 313, 312,
- 311, 310, 309, 308, 307, 306, 305, 304, 303, 302,
- 301, 300, 299, 298, 297, 296, 295, 294, 293, 292,
- 291, 290, 289, 288, 287, 286, 285, 284, 283, 282,
- 281, 280, 279, 278, 277, 276, 275, 272, 271, 270,
- 267, 266, 265, 264, 263, 262, 261, 260, 259, 258,
- 257, 256, 255, 254, 253, 252, 251, 250, 249, 248,
- 243, 242, 241, 240, 239, 238, 237, 236, 235, 234,
+ 16, 17, 18, 17, 16, 16, 16, 16, 16, 19,
+ 20, 16, 21, 22, 23, 24, 25, 26, 27, 21,
+ 28, 21, 21, 21, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 21, 39, 21, 42, 43, 44,
+ 63, 45, 63, 42, 43, 44, 46, 45, 48, 48,
+ 111, 67, 46, 49, 49, 50, 51, 52, 51, 453,
+ 50, 50, 50, 60, 55, 60, 50, 50, 51, 52,
+ 51, 110, 50, 50, 50, 60, 55, 60, 50, 54,
+ 54, 55, 56, 54, 54, 54, 54, 54, 54, 54,
+ 54, 64, 68, 65, 88, 128, 452, 110, 89, 69,
+
+ 113, 70, 113, 71, 63, 129, 63, 90, 58, 54,
+ 54, 55, 56, 54, 54, 54, 54, 54, 54, 54,
+ 54, 72, 76, 84, 94, 101, 77, 101, 91, 73,
+ 85, 92, 95, 110, 150, 451, 78, 86, 58, 96,
+ 102, 93, 142, 74, 143, 103, 123, 124, 450, 136,
+ 137, 145, 151, 146, 101, 110, 101, 125, 110, 112,
+ 126, 138, 113, 159, 113, 165, 189, 205, 166, 102,
+ 449, 227, 253, 206, 103, 228, 280, 160, 282, 254,
+ 190, 110, 304, 281, 112, 309, 448, 305, 447, 310,
+ 446, 445, 283, 41, 41, 41, 41, 47, 47, 47,
+
+ 47, 53, 53, 53, 53, 57, 57, 57, 57, 59,
+ 59, 59, 59, 61, 61, 61, 61, 104, 104, 104,
+ 104, 106, 106, 106, 106, 109, 109, 114, 444, 114,
+ 114, 115, 115, 115, 115, 443, 442, 441, 440, 439,
+ 438, 437, 436, 435, 434, 433, 432, 431, 430, 429,
+ 428, 427, 426, 425, 424, 423, 422, 421, 420, 419,
+ 418, 417, 416, 415, 414, 413, 412, 411, 410, 409,
+ 408, 407, 406, 405, 404, 403, 402, 401, 400, 399,
+ 398, 397, 396, 395, 394, 393, 392, 391, 390, 389,
+ 388, 387, 386, 385, 384, 383, 382, 381, 380, 379,
+
+ 378, 377, 376, 375, 374, 373, 372, 371, 370, 369,
+ 368, 367, 366, 365, 364, 363, 309, 362, 361, 360,
+ 359, 358, 357, 356, 355, 354, 353, 352, 351, 350,
+ 349, 348, 347, 346, 345, 344, 343, 342, 341, 340,
+ 339, 338, 337, 336, 335, 334, 333, 332, 331, 330,
+ 329, 328, 327, 326, 325, 324, 323, 322, 321, 320,
+ 319, 318, 317, 316, 315, 314, 313, 312, 311, 308,
+ 307, 306, 303, 302, 301, 300, 299, 298, 297, 296,
+ 295, 294, 293, 292, 291, 290, 289, 288, 287, 286,
+ 285, 284, 279, 278, 277, 276, 275, 274, 273, 272,
+
+ 271, 270, 269, 268, 267, 266, 265, 264, 263, 262,
+ 261, 260, 259, 258, 257, 256, 255, 252, 251, 250,
+ 249, 248, 247, 246, 245, 244, 243, 242, 241, 240,
+ 239, 238, 237, 236, 235, 234, 233, 232, 231, 230,
+ 229, 226, 225, 224, 223, 222, 221, 220, 219, 83,
+ 218, 217, 216, 215, 214, 213, 212, 211, 210, 209,
+ 208, 207, 204, 203, 202, 201, 200, 199, 198, 197,
+ 196, 195, 156, 194, 193, 192, 191, 188, 187, 186,
+ 185, 184, 183, 182, 181, 180, 179, 178, 177, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168, 167, 164,
+
+ 163, 162, 161, 116, 107, 105, 158, 157, 156, 155,
+ 154, 153, 152, 149, 148, 147, 144, 141, 140, 139,
+ 83, 135, 134, 133, 132, 131, 130, 127, 122, 121,
+ 120, 119, 118, 117, 66, 116, 108, 107, 105, 100,
+ 99, 98, 97, 87, 83, 82, 81, 80, 79, 75,
+ 66, 454, 62, 62, 40, 15, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454
- 233, 232, 231, 230, 229, 228, 227, 226, 225, 224,
- 223, 222, 221, 218, 217, 216, 215, 214, 213, 212,
- 211, 210, 209, 208, 207, 206, 205, 204, 203, 202,
- 201, 200, 199, 198, 197, 194, 193, 192, 191, 190,
- 189, 188, 187, 64, 186, 185, 184, 183, 182, 181,
- 180, 179, 178, 177, 176, 175, 172, 171, 170, 169,
- 168, 167, 166, 165, 128, 164, 163, 162, 161, 158,
- 157, 156, 155, 154, 153, 152, 151, 150, 149, 148,
- 147, 146, 145, 144, 143, 142, 141, 140, 139, 138,
- 137, 134, 133, 132, 131, 88, 85, 83, 128, 127,
-
- 126, 125, 124, 121, 120, 119, 116, 113, 112, 111,
- 64, 107, 106, 105, 104, 103, 102, 99, 94, 93,
- 92, 91, 90, 89, 47, 88, 44, 86, 85, 83,
- 81, 80, 79, 78, 68, 64, 63, 62, 61, 60,
- 56, 47, 44, 415, 7, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415
} ;
-static yyconst short int yy_chk[482] =
+static yyconst short int yy_chk[594] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 3, 3, 419,
- 3, 4, 4, 4, 3, 4, 5, 6, 9, 4,
- 9, 5, 6, 12, 12, 15, 18, 16, 411, 26,
- 18, 24, 15, 26, 15, 16, 15, 42, 24, 42,
- 18, 27, 26, 28, 27, 24, 55, 55, 70, 16,
- 70, 28, 57, 76, 27, 66, 66, 55, 28, 72,
- 55, 72, 57, 89, 118, 95, 133, 66, 95, 158,
-
- 209, 76, 133, 158, 183, 208, 410, 89, 118, 240,
- 236, 183, 208, 240, 209, 236, 416, 416, 417, 417,
- 418, 418, 420, 420, 421, 421, 422, 422, 408, 407,
- 406, 403, 401, 400, 399, 396, 395, 394, 392, 391,
- 390, 389, 388, 387, 385, 384, 383, 382, 381, 380,
- 378, 377, 376, 375, 374, 372, 371, 370, 369, 368,
- 366, 365, 364, 363, 362, 361, 359, 358, 357, 356,
- 355, 354, 353, 351, 350, 349, 348, 347, 346, 345,
- 344, 342, 340, 339, 338, 336, 335, 334, 333, 332,
- 331, 329, 327, 326, 325, 324, 323, 322, 321, 320,
-
- 319, 318, 317, 316, 315, 314, 313, 312, 311, 310,
- 309, 308, 307, 306, 305, 302, 301, 300, 299, 298,
- 297, 296, 295, 294, 293, 292, 291, 290, 289, 288,
- 287, 284, 283, 282, 281, 280, 279, 278, 277, 276,
- 275, 274, 272, 271, 270, 269, 268, 267, 266, 264,
- 263, 260, 259, 258, 257, 256, 255, 254, 252, 251,
- 250, 247, 246, 245, 244, 243, 242, 239, 238, 237,
- 234, 233, 232, 230, 229, 228, 226, 224, 223, 222,
- 221, 220, 219, 218, 216, 215, 214, 213, 211, 210,
- 207, 206, 205, 204, 203, 202, 201, 200, 199, 198,
-
- 197, 196, 195, 194, 193, 192, 191, 190, 189, 187,
- 186, 185, 184, 181, 180, 179, 178, 177, 176, 175,
- 174, 173, 172, 171, 170, 169, 168, 167, 166, 164,
- 163, 162, 161, 160, 159, 157, 156, 155, 154, 151,
- 150, 149, 148, 146, 145, 144, 143, 142, 141, 140,
- 139, 138, 137, 136, 135, 134, 132, 131, 130, 129,
- 127, 126, 125, 124, 123, 122, 121, 120, 119, 117,
- 116, 115, 114, 113, 112, 111, 110, 109, 108, 107,
- 106, 105, 104, 103, 102, 101, 100, 99, 98, 97,
- 96, 94, 93, 92, 90, 87, 84, 82, 81, 80,
-
- 79, 78, 77, 75, 74, 73, 71, 69, 68, 67,
- 65, 63, 62, 61, 60, 59, 58, 56, 54, 53,
- 52, 51, 50, 49, 47, 46, 43, 41, 37, 36,
- 32, 31, 30, 29, 25, 23, 22, 21, 20, 19,
- 17, 13, 11, 7, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3,
+ 17, 3, 17, 4, 4, 4, 3, 4, 5, 6,
+ 465, 461, 4, 5, 6, 7, 7, 7, 7, 450,
+ 7, 7, 7, 11, 11, 11, 7, 8, 8, 8,
+ 8, 56, 8, 8, 8, 12, 12, 12, 8, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 19, 22, 19, 33, 76, 449, 56, 33, 22,
+
+ 60, 22, 60, 22, 63, 76, 63, 33, 9, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 23, 25, 31, 35, 40, 25, 40, 34, 23,
+ 31, 34, 35, 58, 95, 447, 25, 31, 10, 35,
+ 40, 34, 89, 23, 89, 40, 74, 74, 446, 85,
+ 85, 91, 95, 91, 101, 110, 101, 74, 112, 58,
+ 74, 85, 113, 117, 113, 123, 146, 163, 123, 101,
+ 445, 188, 215, 163, 101, 188, 242, 117, 243, 215,
+ 146, 110, 270, 242, 112, 274, 442, 270, 440, 274,
+ 439, 438, 243, 455, 455, 455, 455, 456, 456, 456,
+
+ 456, 457, 457, 457, 457, 458, 458, 458, 458, 459,
+ 459, 459, 459, 460, 460, 460, 460, 462, 462, 462,
+ 462, 463, 463, 463, 463, 464, 464, 466, 435, 466,
+ 466, 467, 467, 467, 467, 434, 433, 431, 430, 429,
+ 428, 427, 426, 424, 423, 422, 421, 420, 419, 417,
+ 416, 415, 414, 413, 411, 410, 409, 408, 407, 405,
+ 404, 403, 402, 401, 400, 398, 397, 396, 395, 394,
+ 393, 392, 390, 389, 388, 387, 386, 385, 384, 383,
+ 381, 379, 378, 377, 375, 374, 373, 372, 371, 370,
+ 368, 366, 365, 364, 363, 362, 361, 360, 359, 358,
+
+ 357, 356, 355, 354, 353, 352, 351, 350, 349, 348,
+ 347, 346, 345, 344, 341, 340, 338, 337, 336, 335,
+ 334, 333, 332, 331, 330, 329, 328, 327, 326, 325,
+ 322, 321, 320, 319, 318, 317, 316, 315, 314, 313,
+ 312, 310, 308, 307, 306, 305, 304, 303, 302, 300,
+ 299, 296, 295, 294, 293, 292, 291, 290, 288, 287,
+ 286, 283, 282, 281, 280, 279, 278, 277, 276, 273,
+ 272, 271, 268, 267, 266, 264, 263, 262, 260, 258,
+ 257, 256, 255, 254, 253, 252, 250, 249, 248, 247,
+ 245, 244, 241, 240, 239, 238, 237, 236, 235, 234,
+
+ 233, 232, 231, 230, 229, 228, 227, 226, 225, 224,
+ 223, 222, 221, 219, 218, 217, 216, 213, 212, 211,
+ 210, 209, 208, 207, 206, 205, 204, 203, 202, 201,
+ 200, 199, 198, 197, 196, 194, 193, 192, 191, 190,
+ 189, 187, 186, 185, 184, 181, 180, 179, 178, 176,
+ 175, 174, 173, 172, 171, 170, 169, 168, 167, 166,
+ 165, 164, 162, 161, 160, 159, 158, 157, 155, 154,
+ 153, 152, 151, 150, 149, 148, 147, 145, 144, 143,
+ 142, 141, 140, 139, 138, 137, 136, 135, 134, 133,
+ 132, 131, 130, 129, 128, 127, 126, 125, 124, 122,
+
+ 121, 120, 118, 115, 106, 104, 103, 102, 100, 99,
+ 98, 97, 96, 94, 93, 92, 90, 88, 87, 86,
+ 84, 82, 81, 80, 79, 78, 77, 75, 73, 72,
+ 71, 70, 69, 68, 66, 65, 49, 45, 44, 39,
+ 38, 37, 36, 32, 30, 29, 28, 27, 26, 24,
+ 20, 15, 14, 13, 2, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454, 454, 454, 454, 454, 454, 454, 454,
+ 454, 454, 454
+
} ;
static yy_state_type yy_last_accepting_state;
@@ -613,10 +651,9 @@ char *yytext;
#include "../crossroads.h"
#include "parser.h"
-/* Required by flex */
-static int yywrap () {
- return (1);
-}
+/* Redefinition of YY_INPUT to respect the parserstate. */
+#define YY_INPUT(buf,res,max) (res) = parser_input( (buf), (max) )
+#define yywrap parser_close
/* Lexer debugging related */
// #define LEXER_DEBUG
@@ -633,8 +670,12 @@ static int yywrap () {
#endif
#define stringstate 1
#define commentstate 2
+#define includestate 3
+#define definestate 4
+#define defineredef 5
+#define definesym 6
-#line 633 "lexer.c"
+#line 674 "lexer.c"
/* Macros after this point can all be overridden by user definitions in
* section 1.
@@ -777,6 +818,9 @@ YY_MALLOC_DECL
#endif
#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ yy_current_buffer->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
YY_USER_ACTION
YY_DECL
@@ -788,7 +832,7 @@ YY_DECL
#line 27 "lexer.l"
-#line 787 "lexer.c"
+#line 831 "lexer.c"
if ( yy_init )
{
@@ -827,6 +871,7 @@ YY_DECL
yy_bp = yy_cp;
yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
yy_match:
do
{
@@ -839,13 +884,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 416 )
+ if ( yy_current_state >= 455 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 445 );
+ while ( yy_base[yy_current_state] != 556 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -875,29 +920,37 @@ case 1:
YY_RULE_SETUP
#line 29 "lexer.l"
{
- lmsg ("comment");
- yylineno++;
+ lmsg ("include starts");
+ BEGIN (includestate);
}
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 34 "lexer.l"
+#line 35 "lexer.l"
+{
+ lmsg ("define starts");
+ BEGIN (definestate);
+}
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 40 "lexer.l"
{
lmsg ("comment");
yylineno++;
}
YY_BREAK
-case 3:
+case 4:
YY_RULE_SETUP
-#line 39 "lexer.l"
+#line 45 "lexer.l"
{
lmsg ("service");
return (SERVICE);
}
YY_BREAK
-case 4:
+case 5:
YY_RULE_SETUP
-#line 44 "lexer.l"
+#line 50 "lexer.l"
{
lmsg ("bindto");
BEGIN (stringstate);
@@ -906,97 +959,97 @@ YY_RULE_SETUP
return (BINDTO);
}
YY_BREAK
-case 5:
+case 6:
YY_RULE_SETUP
-#line 52 "lexer.l"
+#line 58 "lexer.l"
{
lmsg ("port");
return (PORT);
}
YY_BREAK
-case 6:
+case 7:
YY_RULE_SETUP
-#line 57 "lexer.l"
+#line 63 "lexer.l"
{
lmsg ("over");
return (OVER);
}
YY_BREAK
-case 7:
+case 8:
YY_RULE_SETUP
-#line 62 "lexer.l"
+#line 68 "lexer.l"
{
lmsg ("shmkey");
return (SHMKEY);
}
YY_BREAK
-case 8:
+case 9:
YY_RULE_SETUP
-#line 67 "lexer.l"
+#line 73 "lexer.l"
{
lmsg ("backend");
return (BACKEND);
}
YY_BREAK
-case 9:
+case 10:
YY_RULE_SETUP
-#line 72 "lexer.l"
+#line 78 "lexer.l"
{
lmsg ("backlog");
return (BACKLOG);
}
YY_BREAK
-case 10:
+case 11:
YY_RULE_SETUP
-#line 77 "lexer.l"
+#line 83 "lexer.l"
{
lmsg ("retries");
return (RETRIES);
}
YY_BREAK
-case 11:
+case 12:
YY_RULE_SETUP
-#line 82 "lexer.l"
+#line 88 "lexer.l"
{
lmsg ("verbosity");
return (VERBOSITY);
}
YY_BREAK
-case 12:
+case 13:
YY_RULE_SETUP
-#line 87 "lexer.l"
+#line 93 "lexer.l"
{
lmsg ("connectiontimeout");
return (CONNECTIONTIMEOUT);
}
YY_BREAK
-case 13:
+case 14:
YY_RULE_SETUP
-#line 92 "lexer.l"
+#line 98 "lexer.l"
{
lmsg ("maxconnections");
return (MAXCONNECTIONS);
}
YY_BREAK
-case 14:
+case 15:
YY_RULE_SETUP
-#line 97 "lexer.l"
+#line 103 "lexer.l"
{
lmsg ("weight");
return (WEIGHT);
}
YY_BREAK
-case 15:
+case 16:
YY_RULE_SETUP
-#line 102 "lexer.l"
+#line 108 "lexer.l"
{
lmsg ("decay");
return (DECAY);
}
YY_BREAK
-case 16:
+case 17:
YY_RULE_SETUP
-#line 107 "lexer.l"
+#line 113 "lexer.l"
{
lmsg ("server");
BEGIN (stringstate);
@@ -1005,65 +1058,65 @@ YY_RULE_SETUP
return (SERVER);
}
YY_BREAK
-case 17:
+case 18:
YY_RULE_SETUP
-#line 115 "lexer.l"
+#line 121 "lexer.l"
{
lmsg ("dispatchmode");
return (DISPATCHMODE);
}
YY_BREAK
-case 18:
+case 19:
YY_RULE_SETUP
-#line 120 "lexer.l"
+#line 126 "lexer.l"
{
lmsg ("roundrobin");
return (ROUNDROBIN);
}
YY_BREAK
-case 19:
+case 20:
YY_RULE_SETUP
-#line 125 "lexer.l"
+#line 131 "lexer.l"
{
lmsg ("random");
return (RANDOM);
}
YY_BREAK
-case 20:
+case 21:
YY_RULE_SETUP
-#line 130 "lexer.l"
+#line 136 "lexer.l"
{
lmsg ("byduration");
return (BYDURATION);
}
YY_BREAK
-case 21:
+case 22:
YY_RULE_SETUP
-#line 135 "lexer.l"
+#line 141 "lexer.l"
{
lmsg ("bysize");
return (BYSIZE);
}
YY_BREAK
-case 22:
+case 23:
YY_RULE_SETUP
-#line 140 "lexer.l"
+#line 146 "lexer.l"
{
lmsg ("byorder");
return (BYORDER);
}
YY_BREAK
-case 23:
+case 24:
YY_RULE_SETUP
-#line 145 "lexer.l"
+#line 151 "lexer.l"
{
lmsg ("byconnections");
return (BYCONNECTIONS);
}
YY_BREAK
-case 24:
+case 25:
YY_RULE_SETUP
-#line 150 "lexer.l"
+#line 156 "lexer.l"
{
lmsg ("externalhandler");
BEGIN (stringstate);
@@ -1072,17 +1125,17 @@ YY_RULE_SETUP
return (EXTERNALHANDLER);
}
YY_BREAK
-case 25:
+case 26:
YY_RULE_SETUP
-#line 158 "lexer.l"
+#line 164 "lexer.l"
{
lmsg ("byclientip");
return (BYCLIENTIP);
}
YY_BREAK
-case 26:
+case 27:
YY_RULE_SETUP
-#line 163 "lexer.l"
+#line 169 "lexer.l"
{
lmsg ("useraccount");
BEGIN (stringstate);
@@ -1091,33 +1144,33 @@ YY_RULE_SETUP
return (USERACCOUNT);
}
YY_BREAK
-case 27:
+case 28:
YY_RULE_SETUP
-#line 171 "lexer.l"
+#line 177 "lexer.l"
{
lmsg ("revivinginterval");
return (REVIVINGINTERVAL);
}
YY_BREAK
-case 28:
+case 29:
YY_RULE_SETUP
-#line 176 "lexer.l"
+#line 182 "lexer.l"
{
lmsg ("type");
return (TYPE);
}
YY_BREAK
-case 29:
+case 30:
YY_RULE_SETUP
-#line 181 "lexer.l"
+#line 187 "lexer.l"
{
lmsg ("any");
return (ANY);
}
YY_BREAK
-case 30:
+case 31:
YY_RULE_SETUP
-#line 186 "lexer.l"
+#line 192 "lexer.l"
{
lmsg ("stickyhttp");
warning ("The 'stickyhttp protocol is obsolte.\n"
@@ -1125,17 +1178,17 @@ YY_RULE_SETUP
return (HTTP);
}
YY_BREAK
-case 31:
+case 32:
YY_RULE_SETUP
-#line 193 "lexer.l"
+#line 199 "lexer.l"
{
lmsg ("http");
return (HTTP);
}
YY_BREAK
-case 32:
+case 33:
YY_RULE_SETUP
-#line 198 "lexer.l"
+#line 204 "lexer.l"
{
lmsg ("throughputlog");
BEGIN (stringstate);
@@ -1144,9 +1197,9 @@ YY_RULE_SETUP
return (THROUGHPUTLOG);
}
YY_BREAK
-case 33:
+case 34:
YY_RULE_SETUP
-#line 206 "lexer.l"
+#line 212 "lexer.l"
{
lmsg ("trafficlog");
BEGIN (stringstate);
@@ -1155,9 +1208,9 @@ YY_RULE_SETUP
return (TRAFFICLOG);
}
YY_BREAK
-case 34:
+case 35:
YY_RULE_SETUP
-#line 214 "lexer.l"
+#line 220 "lexer.l"
{
lmsg ("dumptraffic");
warning ("The 'dumptraffic' statement is obsolete.\n"
@@ -1168,9 +1221,9 @@ YY_RULE_SETUP
return (TRAFFICLOG);
}
YY_BREAK
-case 35:
+case 36:
YY_RULE_SETUP
-#line 224 "lexer.l"
+#line 230 "lexer.l"
{
lmsg ("onstart");
BEGIN (stringstate);
@@ -1179,9 +1232,9 @@ YY_RULE_SETUP
return (ONSTART);
}
YY_BREAK
-case 36:
+case 37:
YY_RULE_SETUP
-#line 232 "lexer.l"
+#line 238 "lexer.l"
{
lmsg ("onfail");
BEGIN (stringstate);
@@ -1190,9 +1243,9 @@ YY_RULE_SETUP
return (ONFAIL);
}
YY_BREAK
-case 37:
+case 38:
YY_RULE_SETUP
-#line 240 "lexer.l"
+#line 246 "lexer.l"
{
lmsg ("onend");
BEGIN (stringstate);
@@ -1201,9 +1254,9 @@ YY_RULE_SETUP
return (ONEND);
}
YY_BREAK
-case 38:
+case 39:
YY_RULE_SETUP
-#line 248 "lexer.l"
+#line 254 "lexer.l"
{
lmsg ("stickycookie");
BEGIN (stringstate);
@@ -1212,9 +1265,9 @@ YY_RULE_SETUP
return (STICKYCOOKIE);
}
YY_BREAK
-case 39:
+case 40:
YY_RULE_SETUP
-#line 256 "lexer.l"
+#line 262 "lexer.l"
{
lmsg ("addclientheader");
BEGIN (stringstate);
@@ -1223,9 +1276,9 @@ YY_RULE_SETUP
return (ADDCLIENTHEADER);
}
YY_BREAK
-case 40:
+case 41:
YY_RULE_SETUP
-#line 264 "lexer.l"
+#line 270 "lexer.l"
{
lmsg ("setclientheader");
BEGIN (stringstate);
@@ -1234,9 +1287,9 @@ YY_RULE_SETUP
return (SETCLIENTHEADER);
}
YY_BREAK
-case 41:
+case 42:
YY_RULE_SETUP
-#line 272 "lexer.l"
+#line 278 "lexer.l"
{
lmsg ("appendclientheader");
BEGIN (stringstate);
@@ -1245,9 +1298,9 @@ YY_RULE_SETUP
return (APPENDCLIENTHEADER);
}
YY_BREAK
-case 42:
+case 43:
YY_RULE_SETUP
-#line 280 "lexer.l"
+#line 286 "lexer.l"
{
lmsg ("addserverheader");
BEGIN (stringstate);
@@ -1256,9 +1309,9 @@ YY_RULE_SETUP
return (ADDSERVERHEADER);
}
YY_BREAK
-case 43:
+case 44:
YY_RULE_SETUP
-#line 288 "lexer.l"
+#line 294 "lexer.l"
{
lmsg ("setserverheader");
BEGIN (stringstate);
@@ -1267,9 +1320,9 @@ YY_RULE_SETUP
return (SETSERVERHEADER);
}
YY_BREAK
-case 44:
+case 45:
YY_RULE_SETUP
-#line 296 "lexer.l"
+#line 302 "lexer.l"
{
lmsg ("appendserverheader");
BEGIN (stringstate);
@@ -1278,9 +1331,9 @@ YY_RULE_SETUP
return (APPENDSERVERHEADER);
}
YY_BREAK
-case 45:
+case 46:
YY_RULE_SETUP
-#line 304 "lexer.l"
+#line 310 "lexer.l"
{
lmsg ("allowfrom");
BEGIN (stringstate);
@@ -1289,9 +1342,9 @@ YY_RULE_SETUP
return (ALLOWFROM);
}
YY_BREAK
-case 46:
+case 47:
YY_RULE_SETUP
-#line 312 "lexer.l"
+#line 318 "lexer.l"
{
lmsg ("denyfrom");
BEGIN (stringstate);
@@ -1300,9 +1353,9 @@ YY_RULE_SETUP
return (DENYFROM);
}
YY_BREAK
-case 47:
+case 48:
YY_RULE_SETUP
-#line 320 "lexer.l"
+#line 326 "lexer.l"
{
lmsg ("allowfile");
BEGIN (stringstate);
@@ -1311,9 +1364,9 @@ YY_RULE_SETUP
return (ALLOWFILE);
}
YY_BREAK
-case 48:
+case 49:
YY_RULE_SETUP
-#line 328 "lexer.l"
+#line 334 "lexer.l"
{
lmsg ("denyfile");
BEGIN (stringstate);
@@ -1322,110 +1375,110 @@ YY_RULE_SETUP
return (DENYFILE);
}
YY_BREAK
-case 49:
+case 50:
YY_RULE_SETUP
-#line 336 "lexer.l"
+#line 342 "lexer.l"
{
lmsg ("on");
return (ON);
}
YY_BREAK
-case 50:
+case 51:
YY_RULE_SETUP
-#line 341 "lexer.l"
+#line 347 "lexer.l"
{
lmsg ("off");
return (OFF);
}
YY_BREAK
-case 51:
+case 52:
YY_RULE_SETUP
-#line 346 "lexer.l"
+#line 352 "lexer.l"
{
llmsg ("identifier", yytext);
return (IDENTIFIER);
}
YY_BREAK
-case 52:
+case 53:
YY_RULE_SETUP
-#line 351 "lexer.l"
+#line 357 "lexer.l"
{
llmsg ("number", yytext);
return (NUMBER);
}
YY_BREAK
-case 53:
+case 54:
YY_RULE_SETUP
-#line 356 "lexer.l"
+#line 362 "lexer.l"
{
lmsg ("space(s)");
}
YY_BREAK
-case 54:
+case 55:
YY_RULE_SETUP
-#line 360 "lexer.l"
+#line 366 "lexer.l"
{
lmsg ("newline");
yylineno++;
}
YY_BREAK
-case 55:
+case 56:
YY_RULE_SETUP
-#line 365 "lexer.l"
+#line 371 "lexer.l"
{
llmsg ("lone char", yytext);
return (*yytext);
}
YY_BREAK
-case 56:
+case 57:
YY_RULE_SETUP
-#line 370 "lexer.l"
+#line 376 "lexer.l"
{
lmsg ("C-comment starts");
BEGIN(commentstate);
}
YY_BREAK
-case 57:
+case 58:
YY_RULE_SETUP
-#line 374 "lexer.l"
+#line 380 "lexer.l"
{
lmsg ("C-comment ends");
BEGIN(0);
}
YY_BREAK
-case 58:
+case 59:
YY_RULE_SETUP
-#line 378 "lexer.l"
+#line 384 "lexer.l"
{
yylineno++;
}
YY_BREAK
-case 59:
+case 60:
YY_RULE_SETUP
-#line 381 "lexer.l"
+#line 387 "lexer.l"
;
YY_BREAK
-case 60:
+case 61:
YY_RULE_SETUP
-#line 383 "lexer.l"
+#line 389 "lexer.l"
{
llmsg ("string part", yytext);
laststring = xstrcat (laststring, yytext + 1);
laststring[strlen(laststring) - 1] = 0;
}
YY_BREAK
-case 61:
+case 62:
YY_RULE_SETUP
-#line 388 "lexer.l"
+#line 394 "lexer.l"
{
llmsg ("string part", yytext);
laststring = xstrcat (laststring, yytext + 1);
laststring[strlen(laststring) - 1] = 0;
}
YY_BREAK
-case 62:
+case 63:
YY_RULE_SETUP
-#line 393 "lexer.l"
+#line 399 "lexer.l"
{
BEGIN (0);
unput (';');
@@ -1433,9 +1486,9 @@ YY_RULE_SETUP
return (STRING);
}
YY_BREAK
-case 63:
+case 64:
YY_RULE_SETUP
-#line 399 "lexer.l"
+#line 405 "lexer.l"
{
if (laststring) {
laststring = xstrcat (laststring, yytext);
@@ -1443,17 +1496,17 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 64:
+case 65:
YY_RULE_SETUP
-#line 405 "lexer.l"
+#line 411 "lexer.l"
{
llmsg ("string part", yytext);
laststring = xstrcat (laststring, yytext);
}
YY_BREAK
-case 65:
+case 66:
YY_RULE_SETUP
-#line 409 "lexer.l"
+#line 415 "lexer.l"
{
if (laststring) {
laststring = xstrcat (laststring, " ");
@@ -1462,12 +1515,105 @@ YY_RULE_SETUP
yylineno++;
}
YY_BREAK
-case 66:
+case 67:
+YY_RULE_SETUP
+#line 423 "lexer.l"
+{
+ lmsg ("includefile");
+ /* parser_skipline(); */
+ parser_open (yytext);
+ BEGIN (0);
+}
+ YY_BREAK
+case YY_STATE_EOF(includestate):
+#line 429 "lexer.l"
+{
+ error ("Unterminated #include");
+}
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 432 "lexer.l"
+;
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 433 "lexer.l"
+{
+ yylineno++;
+}
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 436 "lexer.l"
+{
+ error ("Illegal character 0x%2.2x in #include line", *yytext);
+}
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 440 "lexer.l"
+;
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 441 "lexer.l"
+{
+ symtab_start (yytext);
+ BEGIN (defineredef);
+}
+ YY_BREAK
+case YY_STATE_EOF(definestate):
+case YY_STATE_EOF(defineredef):
+case YY_STATE_EOF(definesym):
+#line 445 "lexer.l"
+{
+ error ("Unterminated #define");
+}
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 448 "lexer.l"
+{
+ error ("Unterminated #define");
+}
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 451 "lexer.l"
+{
+ error ("Unrecognized character '%c' in #define", *yytext);
+}
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 455 "lexer.l"
+{
+ BEGIN (definesym);
+}
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 458 "lexer.l"
+{
+ symtab_set (yytext);
+}
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 461 "lexer.l"
+{
+ yylineno++;
+ symtab_end();
+ BEGIN (0);
+}
+ YY_BREAK
+case 78:
YY_RULE_SETUP
-#line 416 "lexer.l"
+#line 466 "lexer.l"
ECHO;
YY_BREAK
-#line 1466 "lexer.c"
+#line 1612 "lexer.c"
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(stringstate):
case YY_STATE_EOF(commentstate):
@@ -1749,6 +1895,7 @@ static yy_state_type yy_get_previous_state()
register char *yy_cp;
yy_current_state = yy_start;
+ yy_current_state += YY_AT_BOL();
for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
{
@@ -1761,7 +1908,7 @@ static yy_state_type yy_get_previous_state()
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 416 )
+ if ( yy_current_state >= 455 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1796,11 +1943,11 @@ yy_state_type yy_current_state;
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 416 )
+ if ( yy_current_state >= 455 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 415);
+ yy_is_jam = (yy_current_state == 454);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1919,6 +2066,7 @@ static int input()
*yy_c_buf_p = '\0'; /* preserve yytext */
yy_hold_char = *++yy_c_buf_p;
+ yy_current_buffer->yy_at_bol = (c == '\n');
return c;
}
@@ -2355,4 +2503,4 @@ int main()
return 0;
}
#endif
-#line 416 "lexer.l"
+#line 466 "lexer.l"
diff --git a/src/lib/lexer.l b/src/lib/lexer.l
@@ -2,10 +2,9 @@
#include "../crossroads.h"
#include "parser.h"
-/* Required by flex */
-static int yywrap () {
- return (1);
-}
+/* Redefinition of YY_INPUT to respect the parserstate. */
+#define YY_INPUT(buf,res,max) (res) = parser_input( (buf), (max) )
+#define yywrap parser_close
/* Lexer debugging related */
// #define LEXER_DEBUG
@@ -22,13 +21,20 @@ static int yywrap () {
#endif
%}
-%x stringstate commentstate
+%pointer
+%x stringstate commentstate includestate definestate defineredef definesym
%%
-#.*\n {
- lmsg ("comment");
- yylineno++;
+^#[ \t]*include {
+ lmsg ("include starts");
+ BEGIN (includestate);
+}
+
+
+^#[ \t]*define {
+ lmsg ("define starts");
+ BEGIN (definestate);
}
\/\/.*\n {
@@ -413,3 +419,47 @@ off|false|no {
}
yylineno++;
}
+
+<includestate>[<>\"a-zA-Z0-9_\-\./:\\]+ {
+ lmsg ("includefile");
+ /* parser_skipline(); */
+ parser_open (yytext);
+ BEGIN (0);
+}
+<includestate><<EOF>> {
+ error ("Unterminated #include");
+}
+<includestate>[ \t\n] ;
+<includestate>\n {
+ yylineno++;
+}
+<includestate>. {
+ error ("Illegal character 0x%2.2x in #include line", *yytext);
+}
+
+<definestate>[ \s]+ ;
+<definestate>[A-Za-z_][A-Za-z0-9_]* {
+ symtab_start (yytext);
+ BEGIN (defineredef);
+}
+<definestate,defineredef,definesym><<EOF>> {
+ error ("Unterminated #define");
+}
+<definestate,defineredef>\n {
+ error ("Unterminated #define");
+}
+<definestate>. {
+ error ("Unrecognized character '%c' in #define", *yytext);
+}
+
+<defineredef>[ \t]* {
+ BEGIN (definesym);
+}
+<definesym>.* {
+ symtab_set (yytext);
+}
+<definesym>\n {
+ yylineno++;
+ symtab_end();
+ BEGIN (0);
+}
diff --git a/src/lib/lockreporter.c b/src/lib/lockreporter.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/logactivityany.c b/src/lib/logactivityany.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/logactivitycontinuation.c b/src/lib/logactivitycontinuation.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/logactivityend.c b/src/lib/logactivityend.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/logactivitystart.c b/src/lib/logactivitystart.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/makesocket.c b/src/lib/makesocket.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/markactivity.c b/src/lib/markactivity.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/msg.c b/src/lib/msg.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/msgdumpbuf.c b/src/lib/msgdumpbuf.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/netbuffer.c b/src/lib/netbuffer.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/netbufread.c b/src/lib/netbufread.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/netcopy.c b/src/lib/netcopy.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/netread.c b/src/lib/netread.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/netwrite.c b/src/lib/netwrite.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/parser.c b/src/lib/parser.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -88,10 +88,25 @@ static Service cur_service; /* Storage for a handled service */
# define pimsg(x,y)
#endif
+/* Conversion of yytext for symbol table */
+#define SYMBOL (symtab_lookup((yytext)))
+
/* Error handler for yyparse() */
static int yyerror (char *msg) {
- error ("Parse error at line %d, '%s': %s",
- yylineno + 1, yytext, yyerrmsg);
+ char *sym;
+
+ if (! yytext || ! *yytext)
+ sym = "<end of file>";
+ else if (isspace (*yytext))
+ sym = "<white space>";
+ else if (isprint (*yytext))
+ sym = yytext;
+ else
+ sym = "<nonprintable>";
+
+ error ("Parse error at %s, line %d, '%s': %s",
+ parser_filename(), yylineno + 1,
+ sym, yyerrmsg);
}
/* Store an encountered string */
@@ -283,19 +298,19 @@ static const short yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const short yyrline[] =
{
- 0, 130, 133, 137, 166, 171, 179, 182, 186, 191,
- 197, 203, 209, 219, 225, 231, 237, 243, 249, 255,
- 261, 267, 273, 279, 286, 457, 469, 481, 490, 497,
- 502, 515, 519, 525, 534, 536, 538, 542, 559, 566,
- 576, 585, 589, 593, 597, 601, 605, 609, 613, 619,
- 631, 640, 652, 664, 676, 688, 700, 712, 717, 721,
- 727, 739, 751, 763, 775, 784, 794, 802, 810, 816,
- 823, 828, 833, 838, 843, 848, 853, 858, 863, 868,
- 873, 878, 883, 888, 893, 898, 903, 908, 913, 920,
- 933, 945, 957, 963, 975, 987, 999, 1011, 1023, 1035,
- 1044, 1053, 1065, 1074, 1086, 1098, 1110, 1122, 1134, 1146,
- 1155, 1160, 1165, 1170, 1175, 1180, 1185, 1190, 1195, 1200,
- 1205, 1210, 1215, 1220, 1225, 1230, 1235, 1240
+ 0, 145, 148, 152, 183, 188, 199, 202, 206, 211,
+ 220, 226, 232, 242, 248, 254, 260, 266, 272, 278,
+ 284, 290, 296, 302, 309, 480, 492, 504, 513, 520,
+ 525, 538, 542, 548, 557, 559, 561, 565, 582, 589,
+ 599, 608, 612, 616, 620, 624, 628, 632, 636, 642,
+ 654, 663, 675, 687, 699, 711, 723, 735, 740, 744,
+ 750, 762, 774, 786, 798, 807, 817, 829, 837, 843,
+ 850, 855, 860, 865, 870, 875, 880, 885, 890, 895,
+ 900, 905, 910, 915, 920, 925, 930, 935, 940, 947,
+ 960, 972, 984, 990, 1002, 1014, 1026, 1038, 1050, 1062,
+ 1071, 1080, 1092, 1101, 1113, 1125, 1137, 1149, 1161, 1173,
+ 1182, 1187, 1192, 1197, 1202, 1207, 1212, 1217, 1222, 1227,
+ 1232, 1237, 1242, 1247, 1252, 1257, 1262, 1267
};
#endif
@@ -1209,7 +1224,7 @@ yyreduce:
switch (yyn) {
case 3:
-#line 142 "parser.y"
+#line 157 "parser.y"
{
/* Verify the service description, supply defaults
* and so on.
@@ -1222,7 +1237,9 @@ case 3:
cur_service.name);
if (!cur_service.shmkey)
- cur_service.shmkey = cur_service.port | SHM_MASK;
+ cur_service.shmkey = (unsigned) hashpjw (cur_service.name);
+ msg ("Service %s: shared memory key set to 0x%8.8x",
+ cur_service.name, cur_service.shmkey);
if (!cur_service.bind)
cur_service.bind = "any";
@@ -1234,22 +1251,28 @@ case 3:
;
break;}
case 5:
-#line 173 "parser.y"
+#line 190 "parser.y"
{
- psmsg ("service:", yytext);
- cur_service.name = xstrdup(yytext);
+ psmsg ("service:", SYMBOL);
+ for (i = 0; i < nservice; i++)
+ if (!strcmp (service[i].name, SYMBOL))
+ error ("Duplicate definition of service '%s'", SYMBOL);
+ cur_service.name = xstrdup(SYMBOL);
;
break;}
case 9:
-#line 192 "parser.y"
+#line 212 "parser.y"
{
pimsg ("sevice port:", yyvsp[0].set[0].v.ival);
+ for (i = 0; i < nservice; i++)
+ if (service[i].port == yyvsp[0].set[0].v.ival)
+ error ("Duplicate usage of port %d", yyvsp[0].set[0].v.ival);
cur_service.port = yyvsp[0].set[0].v.ival;
free (yyvsp[0].set);
;
break;}
case 10:
-#line 198 "parser.y"
+#line 221 "parser.y"
{
psmsg ("service binding:", yyvsp[0].set[0].v.sval);
cur_service.bind = yyvsp[0].set[0].v.sval;
@@ -1257,7 +1280,7 @@ case 10:
;
break;}
case 11:
-#line 204 "parser.y"
+#line 227 "parser.y"
{
pimsg ("service verbosity:", yyvsp[0].set[0].v.ival);
cur_service.verbosity = yyvsp[0].set[0].v.ival;
@@ -1265,7 +1288,7 @@ case 11:
;
break;}
case 12:
-#line 210 "parser.y"
+#line 233 "parser.y"
{
pimsg ("service dispatch mode:", yyvsp[0].set[0].v.ival);
pimsg ("service dispatch over:", lastovernr);
@@ -1277,7 +1300,7 @@ case 12:
;
break;}
case 13:
-#line 220 "parser.y"
+#line 243 "parser.y"
{
pimsg ("service revival interval:", yyvsp[0].set[0].v.ival);
cur_service.rev_interval = yyvsp[0].set[0].v.ival;
@@ -1285,7 +1308,7 @@ case 13:
;
break;}
case 14:
-#line 226 "parser.y"
+#line 249 "parser.y"
{
pimsg ("service backlog:", yyvsp[0].set[0].v.ival);
cur_service.backlog = yyvsp[0].set[0].v.ival;
@@ -1293,7 +1316,7 @@ case 14:
;
break;}
case 15:
-#line 232 "parser.y"
+#line 255 "parser.y"
{
pimsg ("service shmkey:", yyvsp[0].set[0].v.ival);
cur_service.shmkey = yyvsp[0].set[0].v.ival;
@@ -1301,7 +1324,7 @@ case 15:
;
break;}
case 16:
-#line 238 "parser.y"
+#line 261 "parser.y"
{
pimsg ("connection timout:", yyvsp[0].set[0].v.ival);
cur_service.connectiontimeout = yyvsp[0].set[0].v.ival;
@@ -1309,7 +1332,7 @@ case 16:
;
break;}
case 17:
-#line 244 "parser.y"
+#line 267 "parser.y"
{
pimsg ("max clients in service:", yyvsp[0].set[0].v.ival);
cur_service.maxconnections = yyvsp[0].set[0].v.ival;
@@ -1317,7 +1340,7 @@ case 17:
;
break;}
case 18:
-#line 250 "parser.y"
+#line 273 "parser.y"
{
pimsg ("service type: ", yyvsp[0].set[0].v.ival);
cur_service.type = yyvsp[0].set[0].v.ival;
@@ -1325,7 +1348,7 @@ case 18:
;
break;}
case 19:
-#line 256 "parser.y"
+#line 279 "parser.y"
{
psmsg ("allow from: ", yyvsp[0].set[0].v.sval);
add_allowfrom (yyvsp[0].set[0].v.sval);
@@ -1333,7 +1356,7 @@ case 19:
;
break;}
case 20:
-#line 262 "parser.y"
+#line 285 "parser.y"
{
psmsg ("allow file: ", yyvsp[0].set[0].v.sval);
cur_service.allowfile = yyvsp[0].set[0].v.sval;
@@ -1341,7 +1364,7 @@ case 20:
;
break;}
case 21:
-#line 268 "parser.y"
+#line 291 "parser.y"
{
psmsg ("deny from: ", yyvsp[0].set[0].v.sval);
add_denyfrom (yyvsp[0].set[0].v.sval);
@@ -1349,7 +1372,7 @@ case 21:
;
break;}
case 22:
-#line 274 "parser.y"
+#line 297 "parser.y"
{
psmsg ("deny file: ", yyvsp[0].set[0].v.sval);
cur_service.denyfile = yyvsp[0].set[0].v.sval;
@@ -1357,7 +1380,7 @@ case 22:
;
break;}
case 23:
-#line 280 "parser.y"
+#line 303 "parser.y"
{
psmsg ("user account: ", yyvsp[0].set[0].v.sval);
setuseraccount (yyvsp[0].set[0].v.sval);
@@ -1366,7 +1389,7 @@ case 23:
;
break;}
case 24:
-#line 287 "parser.y"
+#line 310 "parser.y"
{
pimsg ("converting backend statements, count is", yyvsp[0].n);
for (i = 0; i < yyvsp[0].n; i++)
@@ -1506,9 +1529,9 @@ case 24:
/* Verify the backend block, supply defaults,
* And so on.
*/
- if (!cur_service.port)
- error ("Back end %s lacks port",
- cur_service.port);
+ if (!cur_backend.port)
+ error ("Service %s: back end %s lacks port",
+ cur_service.name, cur_backend.name);
if (cur_backend.weight < 1)
cur_backend.weight = 1;
if (cur_backend.retries < 1)
@@ -1537,7 +1560,7 @@ case 24:
;
break;}
case 25:
-#line 460 "parser.y"
+#line 483 "parser.y"
{
pimsg ("port statement:", lastnr);
yyval.n = 1;
@@ -1547,7 +1570,7 @@ case 25:
;
break;}
case 26:
-#line 472 "parser.y"
+#line 495 "parser.y"
{
psmsg ("bindto statement:", laststr);
yyval.n = 1;
@@ -1557,7 +1580,7 @@ case 26:
;
break;}
case 27:
-#line 483 "parser.y"
+#line 506 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -1565,13 +1588,13 @@ case 27:
;
break;}
case 28:
-#line 492 "parser.y"
+#line 515 "parser.y"
{
- setlastnr (yytext);
+ setlastnr (SYMBOL);
;
break;}
case 30:
-#line 506 "parser.y"
+#line 529 "parser.y"
{
pimsg ("verbosity statement:", lastnr);
yyval.n = 1;
@@ -1581,25 +1604,25 @@ case 30:
;
break;}
case 31:
-#line 516 "parser.y"
+#line 539 "parser.y"
{
lastnr = 1;
;
break;}
case 32:
-#line 520 "parser.y"
+#line 543 "parser.y"
{
lastnr = 0;
;
break;}
case 33:
-#line 529 "parser.y"
+#line 552 "parser.y"
{
yyval = yyvsp[-2];
;
break;}
case 37:
-#line 544 "parser.y"
+#line 567 "parser.y"
{
pimsg ("dispatch mode statement:", lastnr);
yyval.n = 1;
@@ -1615,13 +1638,13 @@ case 37:
;
break;}
case 38:
-#line 561 "parser.y"
+#line 584 "parser.y"
{
- setlastovernr (yytext);
+ setlastovernr (SYMBOL);
;
break;}
case 39:
-#line 567 "parser.y"
+#line 590 "parser.y"
{
psmsg ("external handler:", laststr);
if (lastnr != ds_externalhandler)
@@ -1631,7 +1654,7 @@ case 39:
;
break;}
case 40:
-#line 578 "parser.y"
+#line 601 "parser.y"
{
yyval.n = 1;
yyval.set = xmalloc (sizeof(Confset));
@@ -1639,55 +1662,55 @@ case 40:
;
break;}
case 41:
-#line 586 "parser.y"
+#line 609 "parser.y"
{
lastnr = ds_roundrobin;
;
break;}
case 42:
-#line 590 "parser.y"
+#line 613 "parser.y"
{
lastnr = ds_random;
;
break;}
case 43:
-#line 594 "parser.y"
+#line 617 "parser.y"
{
lastnr = ds_byduration;
;
break;}
case 44:
-#line 598 "parser.y"
+#line 621 "parser.y"
{
lastnr = ds_bysize;
;
break;}
case 45:
-#line 602 "parser.y"
+#line 625 "parser.y"
{
lastnr = ds_byorder;
;
break;}
case 46:
-#line 606 "parser.y"
+#line 629 "parser.y"
{
lastnr = ds_byconnections;
;
break;}
case 47:
-#line 610 "parser.y"
+#line 633 "parser.y"
{
lastnr = ds_externalhandler;
;
break;}
case 48:
-#line 614 "parser.y"
+#line 637 "parser.y"
{
lastnr = ds_byclientip;
;
break;}
case 49:
-#line 622 "parser.y"
+#line 645 "parser.y"
{
pimsg ("user account statement:", laststr);
yyval.n = 1;
@@ -1697,7 +1720,7 @@ case 49:
;
break;}
case 50:
-#line 633 "parser.y"
+#line 656 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -1705,7 +1728,7 @@ case 50:
;
break;}
case 51:
-#line 643 "parser.y"
+#line 666 "parser.y"
{
pimsg ("reviving interval statement:", lastnr);
yyval.n = 1;
@@ -1715,7 +1738,7 @@ case 51:
;
break;}
case 52:
-#line 655 "parser.y"
+#line 678 "parser.y"
{
pimsg ("backlog statement:", lastnr);
yyval.n = 1;
@@ -1725,7 +1748,7 @@ case 52:
;
break;}
case 53:
-#line 667 "parser.y"
+#line 690 "parser.y"
{
pimsg ("shmkey statement:", lastnr);
yyval.n = 1;
@@ -1735,7 +1758,7 @@ case 53:
;
break;}
case 54:
-#line 679 "parser.y"
+#line 702 "parser.y"
{
pimsg ("connection timeout statement:", lastnr);
yyval.n = 1;
@@ -1745,7 +1768,7 @@ case 54:
;
break;}
case 55:
-#line 691 "parser.y"
+#line 714 "parser.y"
{
pimsg ("max clients statement (service):", lastnr);
yyval.n = 1;
@@ -1755,7 +1778,7 @@ case 55:
;
break;}
case 56:
-#line 703 "parser.y"
+#line 726 "parser.y"
{
pimsg ("service type:", lastnr);
yyval.n = 1;
@@ -1765,19 +1788,19 @@ case 56:
;
break;}
case 58:
-#line 718 "parser.y"
+#line 741 "parser.y"
{
lastnr = type_any;
;
break;}
case 59:
-#line 722 "parser.y"
+#line 745 "parser.y"
{
lastnr = type_http;
;
break;}
case 60:
-#line 730 "parser.y"
+#line 753 "parser.y"
{
psmsg ("allow from: ", laststr);
yyval.n = 1;
@@ -1787,7 +1810,7 @@ case 60:
;
break;}
case 61:
-#line 742 "parser.y"
+#line 765 "parser.y"
{
psmsg ("allow from: ", laststr);
yyval.n = 1;
@@ -1797,7 +1820,7 @@ case 61:
;
break;}
case 62:
-#line 754 "parser.y"
+#line 777 "parser.y"
{
psmsg ("allow file: ", laststr);
yyval.n = 1;
@@ -1807,7 +1830,7 @@ case 62:
;
break;}
case 63:
-#line 766 "parser.y"
+#line 789 "parser.y"
{
psmsg ("allow file: ", laststr);
yyval.n = 1;
@@ -1817,7 +1840,7 @@ case 63:
;
break;}
case 64:
-#line 777 "parser.y"
+#line 800 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -1825,20 +1848,24 @@ case 64:
;
break;}
case 65:
-#line 789 "parser.y"
+#line 812 "parser.y"
{
yyval = yyvsp[-1];
;
break;}
case 66:
-#line 796 "parser.y"
+#line 819 "parser.y"
{
- psmsg ("backend name:", yytext);
- cur_backend.name = xstrdup (yytext);
+ psmsg ("backend name:", SYMBOL);
+ for (i = 0; i < cur_service.nbackend; i++)
+ if (!strcmp (cur_service.backend[i].name, SYMBOL))
+ error ("Service %s: back end '%s' multiply defined",
+ cur_service.name, SYMBOL);
+ cur_backend.name = xstrdup (SYMBOL);
;
break;}
case 67:
-#line 804 "parser.y"
+#line 831 "parser.y"
{
yyvsp[-1].n++;
yyvsp[-1].set = xrealloc (yyvsp[-1].set, yyvsp[-1].n * sizeof(Confset));
@@ -1847,152 +1874,152 @@ case 67:
;
break;}
case 68:
-#line 811 "parser.y"
+#line 838 "parser.y"
{
yyval = yyvsp[0];
;
break;}
case 69:
-#line 818 "parser.y"
+#line 845 "parser.y"
{
yyval = yyvsp[0];
;
break;}
case 70:
-#line 824 "parser.y"
+#line 851 "parser.y"
{
psmsg ("backend server:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 71:
-#line 829 "parser.y"
+#line 856 "parser.y"
{
pimsg ("backend port:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 72:
-#line 834 "parser.y"
+#line 861 "parser.y"
{
pimsg ("backend verbosity:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 73:
-#line 839 "parser.y"
+#line 866 "parser.y"
{
psmsg ("backend onstart:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 74:
-#line 844 "parser.y"
+#line 871 "parser.y"
{
psmsg ("backend onend:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 75:
-#line 849 "parser.y"
+#line 876 "parser.y"
{
psmsg ("backend onfail:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 76:
-#line 854 "parser.y"
+#line 881 "parser.y"
{
psmsg ("backend trafficlog:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 77:
-#line 859 "parser.y"
+#line 886 "parser.y"
{
psmsg ("backend trafficlog:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 78:
-#line 864 "parser.y"
+#line 891 "parser.y"
{
pimsg ("backend weight:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 79:
-#line 869 "parser.y"
+#line 896 "parser.y"
{
pimsg ("backend decay:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 80:
-#line 874 "parser.y"
+#line 901 "parser.y"
{
pimsg ("backend maxconnections:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 81:
-#line 879 "parser.y"
+#line 906 "parser.y"
{
psmsg ("backend sticky cookie:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 82:
-#line 884 "parser.y"
+#line 911 "parser.y"
{
psmsg ("addclientheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 83:
-#line 889 "parser.y"
+#line 916 "parser.y"
{
psmsg ("setclientheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 84:
-#line 894 "parser.y"
+#line 921 "parser.y"
{
psmsg ("appendclientheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 85:
-#line 899 "parser.y"
+#line 926 "parser.y"
{
psmsg ("addserverheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 86:
-#line 904 "parser.y"
+#line 931 "parser.y"
{
psmsg ("setserverheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 87:
-#line 909 "parser.y"
+#line 936 "parser.y"
{
psmsg ("appendserverheader:", yyvsp[0].set[0].v.sval);
yyval = yyvsp[0];
;
break;}
case 88:
-#line 914 "parser.y"
+#line 941 "parser.y"
{
pimsg ("backend retries:", yyvsp[0].set[0].v.ival);
yyval = yyvsp[0];
;
break;}
case 89:
-#line 924 "parser.y"
+#line 951 "parser.y"
{
psmsg ("server statement:", laststr);
yyval.n = 1;
@@ -2002,7 +2029,7 @@ case 89:
;
break;}
case 90:
-#line 936 "parser.y"
+#line 963 "parser.y"
{
pimsg ("weight statement", lastnr);
yyval.n = 1;
@@ -2012,7 +2039,7 @@ case 90:
;
break;}
case 91:
-#line 948 "parser.y"
+#line 975 "parser.y"
{
pimsg ("decay statement", lastnr);
yyval.n = 1;
@@ -2022,13 +2049,13 @@ case 91:
;
break;}
case 92:
-#line 958 "parser.y"
+#line 985 "parser.y"
{
setlaststr (laststring);
;
break;}
case 93:
-#line 966 "parser.y"
+#line 993 "parser.y"
{
pimsg ("retries:", lastnr);
yyval.n = 1;
@@ -2038,7 +2065,7 @@ case 93:
;
break;}
case 94:
-#line 978 "parser.y"
+#line 1005 "parser.y"
{
psmsg ("onstart statement:", laststr);
yyval.n = 1;
@@ -2048,7 +2075,7 @@ case 94:
;
break;}
case 95:
-#line 990 "parser.y"
+#line 1017 "parser.y"
{
psmsg ("onfail statement:", laststr);
yyval.n = 1;
@@ -2058,7 +2085,7 @@ case 95:
;
break;}
case 96:
-#line 1002 "parser.y"
+#line 1029 "parser.y"
{
psmsg ("onend statement:", laststr);
yyval.n = 1;
@@ -2068,7 +2095,7 @@ case 96:
;
break;}
case 97:
-#line 1014 "parser.y"
+#line 1041 "parser.y"
{
psmsg ("trafficlog statement:", laststr);
yyval.n = 1;
@@ -2078,7 +2105,7 @@ case 97:
;
break;}
case 98:
-#line 1026 "parser.y"
+#line 1053 "parser.y"
{
psmsg ("throughputlog statement:", laststr);
yyval.n = 1;
@@ -2088,7 +2115,7 @@ case 98:
;
break;}
case 99:
-#line 1037 "parser.y"
+#line 1064 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -2096,7 +2123,7 @@ case 99:
;
break;}
case 100:
-#line 1046 "parser.y"
+#line 1073 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -2104,7 +2131,7 @@ case 100:
;
break;}
case 101:
-#line 1056 "parser.y"
+#line 1083 "parser.y"
{
psmsg ("insertcookie statement:", laststr);
yyval.n = 1;
@@ -2114,7 +2141,7 @@ case 101:
;
break;}
case 102:
-#line 1067 "parser.y"
+#line 1094 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -2122,7 +2149,7 @@ case 102:
;
break;}
case 103:
-#line 1077 "parser.y"
+#line 1104 "parser.y"
{
psmsg ("addclientheader statement:", laststr);
yyval.n = 1;
@@ -2132,7 +2159,7 @@ case 103:
;
break;}
case 104:
-#line 1089 "parser.y"
+#line 1116 "parser.y"
{
psmsg ("setclientheader statement:", laststr);
yyval.n = 1;
@@ -2142,7 +2169,7 @@ case 104:
;
break;}
case 105:
-#line 1101 "parser.y"
+#line 1128 "parser.y"
{
psmsg ("appendclientheader statement:", laststr);
yyval.n = 1;
@@ -2152,7 +2179,7 @@ case 105:
;
break;}
case 106:
-#line 1113 "parser.y"
+#line 1140 "parser.y"
{
psmsg ("addserverheader statement:", laststr);
yyval.n = 1;
@@ -2162,7 +2189,7 @@ case 106:
;
break;}
case 107:
-#line 1125 "parser.y"
+#line 1152 "parser.y"
{
psmsg ("setserverheader statement:", laststr);
yyval.n = 1;
@@ -2172,7 +2199,7 @@ case 107:
;
break;}
case 108:
-#line 1137 "parser.y"
+#line 1164 "parser.y"
{
psmsg ("appendserverheader statement:", laststr);
yyval.n = 1;
@@ -2182,7 +2209,7 @@ case 108:
;
break;}
case 109:
-#line 1148 "parser.y"
+#line 1175 "parser.y"
{
setlaststr (laststring);
free (laststring);
@@ -2190,109 +2217,109 @@ case 109:
;
break;}
case 110:
-#line 1155 "parser.y"
+#line 1182 "parser.y"
{
yyerrmsg = "HTTP header specifier expected";
;
break;}
case 111:
-#line 1160 "parser.y"
+#line 1187 "parser.y"
{
yyerrmsg = "cookie specifier expected";
;
break;}
case 112:
-#line 1165 "parser.y"
+#line 1192 "parser.y"
{
yyerrmsg = "number expected";
;
break;}
case 113:
-#line 1170 "parser.y"
+#line 1197 "parser.y"
{
yyerrmsg = "hostname or IP address expected";
;
break;}
case 114:
-#line 1175 "parser.y"
+#line 1202 "parser.y"
{
yyerrmsg = "'service' expected";
;
break;}
case 115:
-#line 1180 "parser.y"
+#line 1207 "parser.y"
{
yyerrmsg = "backend definition statement expected";
;
break;}
case 116:
-#line 1185 "parser.y"
+#line 1212 "parser.y"
{
yyerrmsg = "service body statement expected";
;
break;}
case 117:
-#line 1190 "parser.y"
+#line 1217 "parser.y"
{
yyerrmsg = "semicolon (;) expected";
;
break;}
case 118:
-#line 1195 "parser.y"
+#line 1222 "parser.y"
{
yyerrmsg = "'on' or 'off' expetcted";
;
break;}
case 119:
-#line 1200 "parser.y"
+#line 1227 "parser.y"
{
yyerrmsg = "dispatch method expected";
;
break;}
case 120:
-#line 1205 "parser.y"
+#line 1232 "parser.y"
{
yyerrmsg = "command line expected";
;
break;}
case 121:
-#line 1210 "parser.y"
+#line 1237 "parser.y"
{
yyerrmsg = "file name expected";
;
break;}
case 122:
-#line 1215 "parser.y"
+#line 1242 "parser.y"
{
yyerrmsg = "service name (identifier) expected";
;
break;}
case 123:
-#line 1220 "parser.y"
+#line 1247 "parser.y"
{
yyerrmsg = "backend name (identifier) expected";
;
break;}
case 124:
-#line 1225 "parser.y"
+#line 1252 "parser.y"
{
yyerrmsg = "IP address or 'any' expected";
;
break;}
case 125:
-#line 1230 "parser.y"
+#line 1257 "parser.y"
{
yyerrmsg = "Service type expected ('any', 'stickyhttp', ...)";
;
break;}
case 126:
-#line 1235 "parser.y"
+#line 1262 "parser.y"
{
yyerrmsg = "IP filter(s) expected";
;
break;}
case 127:
-#line 1240 "parser.y"
+#line 1267 "parser.y"
{
yyerrmsg = "username expected";
;
@@ -2530,4 +2557,4 @@ yyreturn:
#endif
return yyresult;
}
-#line 1244 "parser.y"
+#line 1271 "parser.y"
diff --git a/src/lib/parser.y b/src/lib/parser.y
@@ -29,10 +29,25 @@ static Service cur_service; /* Storage for a handled service */
# define pimsg(x,y)
#endif
+/* Conversion of yytext for symbol table */
+#define SYMBOL (symtab_lookup((yytext)))
+
/* Error handler for yyparse() */
static int yyerror (char *msg) {
- error ("Parse error at line %d, '%s': %s",
- yylineno + 1, yytext, yyerrmsg);
+ char *sym;
+
+ if (! yytext || ! *yytext)
+ sym = "<end of file>";
+ else if (isspace (*yytext))
+ sym = "<white space>";
+ else if (isprint (*yytext))
+ sym = yytext;
+ else
+ sym = "<nonprintable>";
+
+ error ("Parse error at %s, line %d, '%s': %s",
+ parser_filename(), yylineno + 1,
+ sym, yyerrmsg);
}
/* Store an encountered string */
@@ -151,7 +166,9 @@ element:
cur_service.name);
if (!cur_service.shmkey)
- cur_service.shmkey = cur_service.port | SHM_MASK;
+ cur_service.shmkey = (unsigned) hashpjw (cur_service.name);
+ msg ("Service %s: shared memory key set to 0x%8.8x",
+ cur_service.name, cur_service.shmkey);
if (!cur_service.bind)
cur_service.bind = "any";
@@ -171,8 +188,11 @@ service:
servicename:
servicename_expected
IDENTIFIER {
- psmsg ("service:", yytext);
- cur_service.name = xstrdup(yytext);
+ psmsg ("service:", SYMBOL);
+ for (i = 0; i < nservice; i++)
+ if (!strcmp (service[i].name, SYMBOL))
+ error ("Duplicate definition of service '%s'", SYMBOL);
+ cur_service.name = xstrdup(SYMBOL);
}
;
@@ -191,6 +211,9 @@ servicestatement:
servicebody:
portstatement {
pimsg ("sevice port:", $1.set[0].v.ival);
+ for (i = 0; i < nservice; i++)
+ if (service[i].port == $1.set[0].v.ival)
+ error ("Duplicate usage of port %d", $1.set[0].v.ival);
cur_service.port = $1.set[0].v.ival;
free ($1.set);
}
@@ -423,9 +446,9 @@ servicebody:
/* Verify the backend block, supply defaults,
* And so on.
*/
- if (!cur_service.port)
- error ("Back end %s lacks port",
- cur_service.port);
+ if (!cur_backend.port)
+ error ("Service %s: back end %s lacks port",
+ cur_service.name, cur_backend.name);
if (cur_backend.weight < 1)
cur_backend.weight = 1;
if (cur_backend.retries < 1)
@@ -490,7 +513,7 @@ ipaddress:
number:
number_expected
NUMBER {
- setlastnr (yytext);
+ setlastnr (SYMBOL);
}
;
@@ -559,7 +582,7 @@ dispatchover:
overnumber:
number_expected
NUMBER {
- setlastovernr (yytext);
+ setlastovernr (SYMBOL);
}
;
@@ -794,8 +817,12 @@ backendblock:
backendname:
backendname_expected
IDENTIFIER {
- psmsg ("backend name:", yytext);
- cur_backend.name = xstrdup (yytext);
+ psmsg ("backend name:", SYMBOL);
+ for (i = 0; i < cur_service.nbackend; i++)
+ if (!strcmp (cur_service.backend[i].name, SYMBOL))
+ error ("Service %s: back end '%s' multiply defined",
+ cur_service.name, SYMBOL);
+ cur_backend.name = xstrdup (SYMBOL);
}
;
diff --git a/src/lib/parserclose.c b/src/lib/parserclose.c
@@ -0,0 +1,29 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 parser_close () {
+ nparserstate--;
+ int remaining = 0;
+
+ if (nparserstate > 0) {
+ /* We still have files in the parserstate stack. Set up yyin and
+ * yylineno, and return 0 to signal that yyin has been set up
+ * again. */
+ yyin = parserstate[nparserstate - 1].file;
+ yylineno = parserstate[nparserstate - 1].lineno;
+ if (parserstate[nparserstate - 1].buf &&
+ *parserstate[nparserstate - 1].buf)
+ remaining = strlen(parserstate[nparserstate - 1].buf);
+ msg ("Returning to configuration '%s' (line %d), %d bytes remain",
+ parserstate[nparserstate - 1].name, yylineno, remaining);
+ return (0);
+ }
+
+ /* The parser stack is empty. Return 1 to signal that we're really done. */
+ return (1);
+}
diff --git a/src/lib/parserfilename.c b/src/lib/parserfilename.c
@@ -0,0 +1,13 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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"
+
+char const *parser_filename() {
+ if (nparserstate > 0)
+ return (parserstate[nparserstate - 1].name);
+ return ("<unknown file>");
+}
diff --git a/src/lib/parserinput.c b/src/lib/parserinput.c
@@ -0,0 +1,40 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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"
+
+// #define DEBUG
+
+int parser_input (char *buf, int max) {
+ int i, ndef = 0;
+ char *cp, *newbuf;
+
+ if (! nparserstate ||
+ ! parserstate[nparserstate - 1].buf ||
+ ! *parserstate[nparserstate - 1].buf)
+ return (0);
+
+ for (i = 0; i < nsymtab; i++) {
+ if (!strncmp (parserstate[nparserstate - 1].buf, symtab[i].symbol,
+ strlen(symtab[i].symbol))) {
+ if (ndef++ >= DEF_MAX)
+ error ("Too many #defines (%d) at %s (circular definition?",
+ ndef, symtab[i].symbol);
+ cp = parserstate[nparserstate - 1].buf + strlen(symtab[i].symbol);
+ newbuf = xstrdup (symtab[i].redef);
+ newbuf = xstrcat (newbuf, cp);
+ free (parserstate[nparserstate - 1].buf);
+ parserstate[nparserstate - 1].buf = newbuf;
+ }
+ }
+
+ *buf = *parserstate[nparserstate - 1].buf;
+ #ifdef DEBUG
+ fprintf (stderr, "LEXER input char: %c (%d)\n", *buf, *buf);
+ #endif
+ parser_skipchar();
+ return (1);
+}
diff --git a/src/lib/parseropen.c b/src/lib/parseropen.c
@@ -0,0 +1,56 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 parser_open (char const *name) {
+ FILE *f;
+ struct stat statbuf;
+ int nread;
+ char *actual, *cp;
+
+ /* "name" or <name> is converted to name */
+ actual = xstrdup (name);
+ cp = actual + strlen(actual) - 1;
+ if (*actual == '"' && *cp == '"' ||
+ *actual == '<' && *cp == '>') {
+ *cp = 0;
+ strcpy (actual, actual + 1);
+ }
+
+ if (! (f = fopen (actual, "r")) )
+ error ("Cannot read configuration %s: %s", actual, strerror(errno));
+ if (fstat(fileno(f), &statbuf))
+ error ("Cannot stat configuration %s: %s", actual, strerror(errno));
+
+ /* Anticipate the terminating \n, process it and store. */
+ yylineno++;
+ if (nparserstate > 0) {
+ parserstate[nparserstate - 1].lineno = yylineno;
+ msg ("%d bytes remain in configuration %s beyond line %d",
+ strlen(parserstate[nparserstate - 1].buf),
+ parserstate[nparserstate - 1].name, yylineno);
+ }
+
+ parserstate = xrealloc (parserstate,
+ (nparserstate + 1) * sizeof(ParserState));
+ parserstate[nparserstate].name = actual;
+ parserstate[nparserstate].file = f;
+ parserstate[nparserstate].lineno = 0;
+ parserstate[nparserstate].buf = xmalloc (statbuf.st_size + 1);
+ nread = fread (parserstate[nparserstate].buf, 1, statbuf.st_size, f);
+ msg ("Got %d bytes from configuration %s", nread, actual);
+ if (nread < statbuf.st_size)
+ error ("Read only %d bytes from configuration %s (out of %d)",
+ nread, actual, (int) statbuf.st_size);
+ parserstate[nparserstate].buf[statbuf.st_size] = 0;
+ nparserstate++;
+
+ yylineno = 0;
+ yyin = f;
+}
+
+
diff --git a/src/lib/parserrun.c b/src/lib/parserrun.c
@@ -0,0 +1,11 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 parser_run () {
+ yyparse();
+}
diff --git a/src/lib/parserskipchar.c b/src/lib/parserskipchar.c
@@ -0,0 +1,26 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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"
+
+// #define DEBUG
+
+void parser_skipchar () {
+ if (! parserstate[nparserstate - 1].buf ||
+ ! *parserstate[nparserstate - 1].buf)
+ return;
+
+ #ifdef DEBUG
+ fprintf (stderr, "LEXER skipping %c (%d)\n",
+ *parserstate[nparserstate - 1].buf,
+ *parserstate[nparserstate - 1].buf);
+ #endif
+
+ memmove (parserstate[nparserstate - 1].buf,
+ parserstate[nparserstate - 1].buf + 1,
+ strlen(parserstate[nparserstate - 1].buf));
+}
+
diff --git a/src/lib/parserskipline.c b/src/lib/parserskipline.c
@@ -0,0 +1,21 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 parser_skipline () {
+ char ch;
+
+ while (parserstate[nparserstate - 1].buf &&
+ *parserstate[nparserstate - 1].buf) {
+ ch = *parserstate[nparserstate - 1].buf;
+ parser_skipchar();
+ if (ch == '\n') {
+ yylineno++;
+ break;
+ }
+ }
+}
diff --git a/src/lib/restart.c b/src/lib/restart.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/runservice.c b/src/lib/runservice.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/serve.c b/src/lib/serve.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/setprogramtitle.c b/src/lib/setprogramtitle.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/showconfig.c b/src/lib/showconfig.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -12,27 +12,37 @@
void show_config () {
printf ("VER version: %s\n"
"REVVER revision version: %s\n"
+ "YEARS it's been around since: %s\n"
+ "AUTHORNAME author: %s\n"
+ "MAINTAINERNAME maintainer: %s\n"
+ "MAINTAINEREMAIL e-mail of maintainer: %s\n"
"DEFAULT_CONF default configuration file: %s\n"
"MAX_BACKEND max nr. of backends in service: %d\n"
- "SHM_MASK magic shared memory number: 0x%x\n"
- "SLEEP_TIME service inactivy pause %d\n"
- "CONNECT_TIMEOUT backend connect timeout %d\n"
- "RETRY_WAIT backend retry pause %d\n"
- "TCP_BUFSZ network buffer size %d\n"
- "BINDIR installation directory %s\n"
- "SET_PROC_TITLE_BY_ARGV argv assumed linear array %d\n"
- "EXTRALIBS extra library dependencies %s\n"
- "LIBS standard library dependencies %s\n"
- ,
- VER, REVVER, DEFAULT_CONF, MAX_BACKEND, SHM_MASK, SLEEP_TIME,
- CONNECT_TIMEOUT, RETRY_WAIT, TCP_BUFSZ, BINDIR,
+ "SLEEP_TIME service inactivy pause: %d\n"
+ "DEF_MAX max nr of defines in a file %d\n"
+ "DNS_CACHESIZE size of the DNS cache: %d\n"
+ "DNS_CACHETTL default ttl of cached DNS: %d\n"
+ "CONNECT_TIMEOUT backend connect timeout: %d\n"
+ "RETRY_WAIT backend retry pause: %d\n"
+ "TCP_BUFSZ network buffer size: %d\n"
+ "PREFIX installation tree prefix: %s\n"
+ "BINDIR directory for binaries: %s\n"
+ "SET_PROC_TITLE_BY_ARGV argv assumed linear array: %d\n"
+ "EXTRALIBS extra library dependencies: %s\n"
+ "LIBS standard library dependencies: %s\n"
+ ,
+ VER, REVVER, YEARS, AUTHORNAME, MAINTAINERNAME,
+ MAINTAINEREMAIL,
+ DEFAULT_CONF, MAX_BACKEND, SLEEP_TIME, DEF_MAX,
+ DNS_CACHESIZE, DNS_CACHETTL,
+ CONNECT_TIMEOUT, RETRY_WAIT, TCP_BUFSZ, PREFIX, BINDIR,
SET_PROC_TITLE_BY_ARGV, EXTRALIBS, LIBS);
- SHOWDEF (HAVE_MALLOC_H, "HAVE_MALLOC_H", "<malloc.h> present");
- SHOWDEF (HAVE_STDINT_H, "HAVE_STDINT_H", "<stdint.h> present");
- SHOWDEF (HAVE_FLOCK, "HAVE_FLOCK", "flock() present");
- SHOWDEF (HAVE_LOCKF, "HAVE_LOCKF", "lockf() present");
- SHOWDEF (HAVE_STRLCAT, "HAVE_STRLCAT", "strlcat() present");
- SHOWDEF (HAVE_SRANDDEV, "HAVE_SRANDDEV", "sranddev() present");
- SHOWDEF (HAVE_VSYSLOG, "HAVE_VSYSLOG", "vsyslog() present");
- SHOWDEF (HAVE_STRCASESTR, "HAVE_STRCASESTR", "strcasestr() present");
+ SHOWDEF (HAVE_MALLOC_H, "HAVE_MALLOC_H", "<malloc.h> present:");
+ SHOWDEF (HAVE_STDINT_H, "HAVE_STDINT_H", "<stdint.h> present:");
+ SHOWDEF (HAVE_FLOCK, "HAVE_FLOCK", "flock() present:");
+ SHOWDEF (HAVE_LOCKF, "HAVE_LOCKF", "lockf() present:");
+ SHOWDEF (HAVE_STRLCAT, "HAVE_STRLCAT", "strlcat() present:");
+ SHOWDEF (HAVE_SRANDDEV, "HAVE_SRANDDEV", "sranddev() present:");
+ SHOWDEF (HAVE_VSYSLOG, "HAVE_VSYSLOG", "vsyslog() present:");
+ SHOWDEF (HAVE_STRCASESTR, "HAVE_STRCASESTR", "strcasestr() present:");
}
diff --git a/src/lib/showservices.c b/src/lib/showservices.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/showstatus.c b/src/lib/showstatus.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/stagetostring.c b/src/lib/stagetostring.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/statetostring.c b/src/lib/statetostring.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/stopdaemon.c b/src/lib/stopdaemon.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/strcasestr.c b/src/lib/strcasestr.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/strexpandformat.c b/src/lib/strexpandformat.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/stringtostate.c b/src/lib/stringtostate.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/strlcat.c b/src/lib/strlcat.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/strprintf.c b/src/lib/strprintf.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/strvprintf.c b/src/lib/strvprintf.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/symtabend.c b/src/lib/symtabend.c
@@ -0,0 +1,13 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 symtab_end () {
+ if (!symtab[nsymtab].redef)
+ error ("#define %s lacks a redefinition", symtab[nsymtab].symbol);
+ nsymtab++;
+}
diff --git a/src/lib/symtablookup.c b/src/lib/symtablookup.c
@@ -0,0 +1,16 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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"
+
+char const *symtab_lookup (char const *txt) {
+ int i;
+
+ for (i = 0; i < nsymtab; i++)
+ if (!strcmp (symtab[i].symbol, txt))
+ return (symtab[i].redef);
+ return (txt);
+}
diff --git a/src/lib/symtabset.c b/src/lib/symtabset.c
@@ -0,0 +1,11 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 symtab_set (char const *redef) {
+ symtab[nsymtab].redef = xstrdup (redef);
+}
diff --git a/src/lib/symtabstart.c b/src/lib/symtabstart.c
@@ -0,0 +1,13 @@
+/*************************************************************************
+ * This file is part of Crosroads 1.44, 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 symtab_start (char const *sym) {
+ symtab = xrealloc (symtab, (nsymtab + 1) * sizeof(Symtab));
+ symtab[nsymtab].symbol = xstrdup (sym);
+ symtab[nsymtab].redef = 0;
+}
diff --git a/src/lib/sysrun.c b/src/lib/sysrun.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/tcpserve.c b/src/lib/tcpserve.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/tellservice.c b/src/lib/tellservice.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/thruputlog.c b/src/lib/thruputlog.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/trafficlog.c b/src/lib/trafficlog.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/uidassume.c b/src/lib/uidassume.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/uidrestore.c b/src/lib/uidrestore.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/unlockreporter.c b/src/lib/unlockreporter.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/usage.c b/src/lib/usage.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
@@ -8,6 +8,8 @@
#include "usage.h"
void usage () {
- fprintf (stderr, "\n" USAGETEXT "\n", VER, DEFAULT_CONF);
+ fprintf (stderr, "\n" USAGETEXT "\n", VER, AUTHORNAME, YEARS,
+ MAINTAINERNAME, MAINTAINEREMAIL,
+ DEFAULT_CONF, DNS_CACHETTL);
exit (1);
}
diff --git a/src/lib/usage.txt b/src/lib/usage.txt
@@ -1,7 +1,7 @@
This is Crossroads %s, a load balancer and fail-over utility for TCP.
-Copyright (c) Karel Kubat / e-tunity 2005-2007 ff. All rights reserved.
-For information, contact <info@e-tunity.com> or see <http://www.e-tunity.com>.
-For distributions and updates, visit <http://crossroads.e-tunity.com>.
+Copyright (c) %s / e-tunity %s ff. All rights reserved.
+Maintained by %s / %s.
+For distributions and updates, visit http://crossroads.e-tunity.com.
Usage:
** Controlling the daemon: **
@@ -24,6 +24,8 @@ Supported flags:
-C: shows compile-time configuration and stops
-c CONFIG: Uses the named configuration, instead of the default
%s
+ -d TTL: Specifies the time to live of cached DNS entries,
+ default %d (sec)
-l FAC: Specifies the openlog(3) facility to use when
logging. Default is LOG_DAEMON. Allowed values are 0..7
for LOG_LOCAL0 to LOG_LOCAL7.
diff --git a/src/lib/vsyslog.c b/src/lib/vsyslog.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/wakeuphandler.c b/src/lib/wakeuphandler.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/warning.c b/src/lib/warning.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/writelog.c b/src/lib/writelog.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xcalloc.c b/src/lib/xcalloc.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xmalloc.c b/src/lib/xmalloc.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xrealloc.c b/src/lib/xrealloc.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xstrcat.c b/src/lib/xstrcat.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xstrcatch.c b/src/lib/xstrcatch.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/lib/xstrdup.c b/src/lib/xstrdup.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * This file is part of Crosroads 1.42, a load balancer and fail over
+ * This file is part of Crosroads 1.44, a load balancer and fail over
* utility for TCP. Copyright (c) Karel Kubat, distributed under GPL.
* Visit http://crossroads.e-tunity.com for information.
*************************************************************************/
diff --git a/src/shared/parseopt.inc b/src/shared/parseopt.inc
@@ -0,0 +1,97 @@
+ /* Parse the command line options.
+ * This file gets included from crossroads AND crossroads-daemon.
+ * NOTE: When changing the options list, remember to update:
+ * - src/lib/usage.txt
+ * - doc/main/using.yo
+ * - doc/man/crossroads.yo
+ */
+ while ( (opt = getopt (argc, argv, "b?c:fhvi:Val:stCm:xd:")) > 0 )
+ switch (opt) {
+ case 'a':
+ log_activity++;
+ break;
+ case 'b':
+ #ifdef TARGET_CROSSROADS
+ msg ("Parsing configuration %s", config_file);
+ parser_open (config_file);
+ parser_run();
+ parser_close();
+ config_write (1);
+ exit (0);
+ #endif
+ break;
+ case 'c':
+ config_file = optarg;
+ break;
+ case 'd':
+ dns_cachettl = atoi (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:
+ #ifdef TARGET_CROSSROADS
+ usage();
+ #else
+ error ("Bad invocation of crossroads-daemon");
+ #endif
+ }
+ break;
+ case 'm':
+ shmperm = strtol (optarg, 0, 8);
+ break;
+ case 's':
+ sloppyportbind++;
+ break;
+ case 't':
+ tabular_status++;
+ break;
+ case 'x':
+ xml_status++;
+ break;
+ case 'C':
+ #ifdef TARGET_CROSSROADS
+ show_config();
+ #endif
+ exit (0);
+ case 'V':
+ puts (VER);
+ exit (0);
+ case '?':
+ case 'h':
+ default:
+ #ifdef TARGET_CROSSROADS
+ usage ();
+ #else
+ error ("Bad invocation of crossroads-daemon");
+ #endif
+ }
diff --git a/test/Makefile b/test/Makefile
@@ -0,0 +1,13 @@
+foo:
+ @echo 'Running simplistic tests...'
+ @for f in t*.conf ; do \
+ echo "Testing $$f: should succeed" ; \
+ ../src/crossroads/crossroads -vc $$f services || exit 1 ; \
+ echo ; \
+ done
+ @for f in bad*.conf ; do \
+ echo "Testing $$f: should fail" ; \
+ ../src/crossroads/crossroads -vc $$f services && exit 1 ; \
+ true ; \
+ echo ; \
+ done
diff --git a/test/bad01.conf b/test/bad01.conf
@@ -0,0 +1,16 @@
+/* Bad configuration
+ * multiple service 'bla' definitions */
+service bla {
+ port 10000;
+ backend one {
+ server x:80;
+ }
+}
+
+service bla {
+ port 10001;
+ backend one {
+ server x:80;
+ }
+}
+
diff --git a/test/bad02.conf b/test/bad02.conf
@@ -0,0 +1,11 @@
+/* Bad configuration
+ * multiple backend 'one' definitions */
+service bla {
+ port 10000;
+ backend one {
+ server x:80;
+ }
+ backend one {
+ server x:80;
+ }
+}
diff --git a/test/bad03.conf b/test/bad03.conf
@@ -0,0 +1,3 @@
+/* Bad configuration
+ * no services */
+
diff --git a/test/bad04.conf b/test/bad04.conf
@@ -0,0 +1,5 @@
+/* Bad configuration
+ * no back ends */
+service bla {
+ port 10000;
+}
diff --git a/test/bad05.conf b/test/bad05.conf
@@ -0,0 +1,9 @@
+/* Bad configuration
+ * no back end port */
+service bla {
+ port 10000;
+ backend one {
+ server x;
+ }
+}
+
diff --git a/test/bad06.conf b/test/bad06.conf
@@ -0,0 +1,8 @@
+/* Bad configuration
+ * no service port */
+service bla {
+ backend one {
+ server x:10000;
+ }
+}
+
diff --git a/test/bad07.conf b/test/bad07.conf
@@ -0,0 +1,11 @@
+/* Bad configuration
+ * bad define 1 */
+
+#define
+service bla {
+ port 80;
+ backend one {
+ server x:10000;
+ }
+}
+
diff --git a/test/bad08.conf b/test/bad08.conf
@@ -0,0 +1,11 @@
+/* Bad configuration
+ * bad define 2 */
+
+#define bla
+service bla {
+ port 80;
+ backend one {
+ server x:10000;
+ }
+}
+
diff --git a/test/bad09.conf b/test/bad09.conf
@@ -0,0 +1,5 @@
+/* Bad configuration
+ * bad define 3 */
+
+#define
+
diff --git a/test/bad10.conf b/test/bad10.conf
@@ -0,0 +1,6 @@
+/* Bad configuration
+ * bad include */
+
+#include
+
+
diff --git a/test/bad11.conf b/test/bad11.conf
@@ -0,0 +1,12 @@
+/* Bad configuration
+ * bad statement in bad11a.inc */
+
+#include "bad11a.inc"
+
+service bla {
+ port 80;
+ backend one {
+ server localhost:91;
+ }
+}
+
diff --git a/test/bad11a.inc b/test/bad11a.inc
@@ -0,0 +1,6 @@
+service tester {
+ port xyzzy;
+ backend two {
+ server localhost:80;
+ }
+}
diff --git a/test/bad12.conf b/test/bad12.conf
@@ -0,0 +1,12 @@
+/* Bad configuration
+ * bad statement in bad12.inc */
+
+#include "bad12a.inc"
+
+service bla {
+ port xyzzy;
+ backend one {
+ server localhost:91;
+ }
+}
+
diff --git a/test/bad12a.inc b/test/bad12a.inc
@@ -0,0 +1,6 @@
+service tester {
+ port 10000;
+ backend two {
+ server localhost:80;
+ }
+}
diff --git a/test/bad13.conf b/test/bad13.conf
@@ -0,0 +1,40 @@
+/* Bad configuration
+ simple parse error */
+
+service test {
+ port 10001;
+ type http;
+ bindto any;
+ dispatchmode bysize;
+ connectiontimeout 600;
+ verbosity on;
+
+ backend a {
+ server localhost;
+ port 10000;
+ weight 2;
+ decay 5;
+ stickycookie BalancerID=Backend_A;
+ addclientheader "Set-Cookie: BalancerID=Backend_A; Path=/";
+ }
+
+ backend b {
+ server localhost;
+ port 10000;
+ weight 2;
+ decay 5;
+ stickycookie BalancerID=Backend_B;
+ addclientheader "Set-Cookie: BalancerID=Backend_B; Path=/";
+ }
+
+ backend c {
+ server localhost;
+ port 10000;
+ weight 3;
+ decay 5;
+ stickycookie BalancerID=Backend_C;
+ addclientheader "Set-Cookie: BalancerID=Backend_C; Path=/";
+ }
+}
+
+error is here
diff --git a/test/runtest b/test/runtest
@@ -1,40 +1,43 @@
#!/usr/bin/perl
+
+# Small test runner. For debugging only.
+
use strict;
my $tests = <<'ENDTEST';
- ../src/crossroads -c t1.conf start
+ ../src/crossroads/crossroads -c t01.conf start
./server 12 10000 &
./client 200 localhost 10001
sleep 5
- ../src/crossroads -c t1.conf status
- ../src/crossroads -c t1.conf stop
+ ../src/crossroads/crossroads -c t01.conf status
+ ../src/crossroads/crossroads -c t01.conf stop
- ../src/crossroads -c t2.conf start
+ ../src/crossroads/crossroads -c t02.conf start
./server 12 10000 &
./client 200 localhost 10001
sleep 5
- ../src/crossroads -c t2.conf status
- ../src/crossroads -c t2.conf stop
+ ../src/crossroads/crossroads -c t02.conf status
+ ../src/crossroads/crossroads -c t02.conf stop
- ../src/crossroads -c t3.conf start
+ ../src/crossroads/crossroads -c t03.conf start
time ssh -p23 root@localhost; true
- ../src/crossroads -c t3.conf status
- ../src/crossroads -c t3.conf stop
+ ../src/crossroads/crossroads -c t03.conf status
+ ../src/crossroads/crossroads -c t03.conf stop
- ../src/crossroads -c t4.conf start
+ ../src/crossroads/crossroads -c t04.conf start
./server 12 10000 &
./client 200 localhost 10001
sleep 5
- ../src/crossroads -c t4.conf status
- ../src/crossroads -c t4.conf stop
+ ../src/crossroads/crossroads -c t04.conf status
+ ../src/crossroads/crossroads -c t04.conf stop
- ../src/crossroads -c t6.conf start
+ ../src/crossroads/crossroads -c t06.conf start
./server 12 10000 &
./client 200 localhost 10001
sleep 5
- ../src/crossroads -c t6.conf status
- ../src/crossroads -c t6.conf stop
+ ../src/crossroads/crossroads -c t06.conf status
+ ../src/crossroads/crossroads -c t06.conf stop
ENDTEST
diff --git a/test/t1.conf b/test/t01.conf
diff --git a/test/t2.conf b/test/t02.conf
diff --git a/test/t3.conf b/test/t03.conf
diff --git a/test/t4.conf b/test/t04.conf
diff --git a/test/t5.conf b/test/t05.conf
diff --git a/test/t6.conf b/test/t06.conf
diff --git a/test/t7.conf b/test/t07.conf
diff --git a/test/t8.conf b/test/t08.conf
diff --git a/test/t09.conf b/test/t09.conf
@@ -0,0 +1,13 @@
+#include t09a.inc
+
+service second {
+ port 10001;
+ backend one {
+ server localhost:80;
+ }
+ backend two {
+ server localhost:80;
+ }
+}
+
+#include t09b.inc
diff --git a/test/t09a.inc b/test/t09a.inc
@@ -0,0 +1,10 @@
+service first {
+ port 10000;
+ backend one {
+ server localhost:80;
+ }
+ backend two {
+ server localhost:80;
+ }
+}
+
diff --git a/test/t09b.inc b/test/t09b.inc
@@ -0,0 +1,10 @@
+service third {
+ port 10002;
+ backend one {
+ server localhost:80;
+ }
+ backend two {
+ server localhost:80;
+ }
+}
+
+\ No newline at end of file
diff --git a/test/t10.conf b/test/t10.conf
@@ -0,0 +1,40 @@
+#define SERVICENAME test
+#define SERVICEPORT 10001
+#define BACKENDSERVER localhost
+#define BACKPORT 80
+
+service test {
+ port SERVICEPORT;
+ type http;
+ bindto any;
+ dispatchmode bysize;
+ connectiontimeout 600;
+ verbosity on;
+
+ backend a {
+ server BACKENDSERVER;
+ port BACKPORT;
+ weight 2;
+ decay 5;
+ stickycookie BalancerID=Backend_A;
+ addclientheader "Set-Cookie: BalancerID=Backend_A; Path=/";
+ }
+
+ backend b {
+ server BACKENDSERVER:BACKPORT;
+ port BACKPORT;
+ weight 2;
+ decay 5;
+ stickycookie BalancerID=Backend_B;
+ addclientheader "Set-Cookie: BalancerID=Backend_B; Path=/";
+ }
+
+ backend c {
+ server BACKENDSERVER;
+ port BACKPORT;
+ weight 3;
+ decay 5;
+ stickycookie BalancerID=Backend_C;
+ addclientheader "Set-Cookie: BalancerID=Backend_C; Path=/";
+ }
+}
diff --git a/tools/c-conf b/tools/c-conf
@@ -4,7 +4,8 @@ use strict;
use Getopt::Std;
# Globals
-my $VER = "1.07";
+my $VER = "1.08";
+# 1.08 [KK 2007-05-22] -L{dir} shown only once for identical dirs during 'lib'
# 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.
@@ -325,6 +326,8 @@ LDFLAGS = \$(shell c-conf lib xml2)
ENDHELP
usage() if ($#_ == -1);
+
+ my %dirshown;
foreach my $lib (@_) {
msg ("Looking for lib '$lib'\n");
my $found = 0;
@@ -335,7 +338,11 @@ ENDHELP
msg ("Found as '$hit'\n");
$found++;
$hit =~ s{/[^/]*$}{};
- output ("-L$hit -l$lib");
+ if (! $dirshown{$hit}) {
+ output ("-L$hit");
+ $dirshown{$hit} = 1;
+ }
+ output ("-l$lib");
}
}
warning ("Library '$lib' not found\n")
diff --git a/tools/installdoc b/tools/installdoc
@@ -0,0 +1,34 @@
+#!/usr/bin/perl
+
+use strict;
+
+sub basename ($) {
+ my $f = shift;
+ $f =~ s{^.*/}{};
+ return ($f);
+}
+
+die ("Usage: installdoc PREFIX MANFILES\n") if ($#ARGV < 1);
+my $prefix = shift (@ARGV);
+die ("Prefix directory '$prefix' not accessible\n") unless (-d $prefix);
+for my $f (@ARGV) {
+ die ("Cannot see man page '$f' to install\n") unless (-f $f);
+ my $targetdir = '';
+ my $sect = $f;
+ $sect =~ s{.*(\d)}{$1};
+ for my $d ("$prefix/share/man", "$prefix/man") {
+ if (-d "$d/man$sect") {
+ $targetdir = "$d/man$sect";
+ last;
+ }
+ }
+ if ($targetdir eq '') {
+ print STDERR ("No suitable man/ subdir found under $prefix,\n",
+ "manual pages not installed\n");
+ exit (0);
+ }
+ my $dest = "$targetdir/" . basename($f);
+ next if (stat($dest) and (stat($dest))[9] >= (stat($f))[9]);
+ print ("$f -> $dest\n");
+ system ("cp $f $dest") and die ("Failed to copy $f to $dest\n");
+}