--- haproxy-1.3.15.2.orig/debian/haproxy.default +++ haproxy-1.3.15.2/debian/haproxy.default @@ -0,0 +1,4 @@ +# Set ENABLED to 1 if you want the init script to start haproxy. +ENABLED=0 +# Add extra flags here. +#EXTRAOPTS="-de -m 16" --- haproxy-1.3.15.2.orig/debian/changelog +++ haproxy-1.3.15.2/debian/changelog @@ -0,0 +1,110 @@ +haproxy (1.3.15.2-2~lenny1) testing-proposed-updates; urgency=low + + * Rebuild for lenny to circumvent pcre3 shlibs bump. + + -- Arnaud Cornet Wed, 14 Jan 2009 11:28:36 +0100 + +haproxy (1.3.15.2-2) unstable; urgency=low + + * Add stable branch bug fixes from upstream (Closes: #510185). + - use_backend-consider-unless.patch: consider "unless" in use_backend + - segfault-url_param+check_post.patch: fix segfault with url_param + + check_post + - server-timeout.patch: consider server timeout in all circumstances + - closed-fd-remove.patch: drop info about closed file descriptors + - connection-slot-during-retry.patch: do not release the connection slot + during a retry + - srv_dynamic_maxconn.patch: dynamic connection throttling api fix + - do-not-pause-backends-on-reload.patch: make reload reliable + - acl-in-default.patch: allow acl-related keywords in defaults sections + - cookie-capture-check.patch: cookie capture is declared in the frontend + but checked on the backend + - dead-servers-queue.patch: make dead servers not suck pending connections + * Add quilt build-dependancy. Use quilt in debian/rules to apply + patches. + + -- Arnaud Cornet Wed, 31 Dec 2008 08:50:21 +0100 + +haproxy (1.3.15.2-1) unstable; urgency=low + + * New Upstream Version (Closes: #497186). + + -- Arnaud Cornet Sat, 30 Aug 2008 18:06:31 +0200 + +haproxy (1.3.15.1-1) unstable; urgency=low + + * New Upstream Version + * Upgrade standards version to 3.8.0 (no change needed). + * Build with TARGET=linux26 on linux, TARGET=generic on other systems. + + -- Arnaud Cornet Fri, 20 Jun 2008 00:38:50 +0200 + +haproxy (1.3.14.5-1) unstable; urgency=low + + * New Upstream Version (Closes: #484221) + * Use debhelper 7, drop CDBS. + + -- Arnaud Cornet Wed, 04 Jun 2008 19:21:56 +0200 + +haproxy (1.3.14.3-1) unstable; urgency=low + + * New Upstream Version + * Add status argument support to init-script to conform to LSB. + * Cleanup pidfile after stop in init script. Init script return code fixups. + + -- Arnaud Cornet Sun, 09 Mar 2008 21:30:29 +0100 + +haproxy (1.3.14.2-3) unstable; urgency=low + + * Add init script support for nbproc > 1 in configuration. That is, + multiple haproxy processes. + * Use 'option redispatch' instead of redispatch in debian default + config. + + -- Arnaud Cornet Sun, 03 Feb 2008 18:22:28 +0100 + +haproxy (1.3.14.2-2) unstable; urgency=low + + * Fix init scripts's reload function to use -sf instead of -st (to wait for + active session to finish cleanly). Also support dash. Thanks to + Jean-Baptiste Quenot for noticing. + + -- Arnaud Cornet Thu, 24 Jan 2008 23:47:26 +0100 + +haproxy (1.3.14.2-1) unstable; urgency=low + + * New Upstream Version + * Simplify DEB_MAKE_INVOKE, as upstream now supports us overriding + CFLAGS. + * Move haproxy to usr/sbin. + + -- Arnaud Cornet Mon, 21 Jan 2008 22:42:51 +0100 + +haproxy (1.3.14.1-1) unstable; urgency=low + + * New upstream release. + * Drop dfsg list and hash code rewrite (merged upstream). + * Add a HAPROXY variable in init script. + * Drop makefile patch, fix debian/rules accordingly. Drop build-dependancy + on quilt. + * Manpage now upstream. Ship upstream's and drop ours. + + -- Arnaud Cornet Tue, 01 Jan 2008 22:50:09 +0100 + +haproxy (1.3.12.dfsg2-1) unstable; urgency=low + + * New upstream bugfix release. + * Use new Homepage tag. + * Bump standards-version (no change needed). + * Add build-depend on quilt and add patch to allow proper CFLAGS passing to + make. + + -- Arnaud Cornet Tue, 25 Dec 2007 21:52:59 +0100 + +haproxy (1.3.12.dfsg-1) unstable; urgency=low + + * Initial release (Closes: #416397). + * The DFSG removes files with GPL-incompabitle license and adds a + re-implementation by me. + + -- Arnaud Cornet Fri, 17 Aug 2007 09:33:41 +0200 --- haproxy-1.3.15.2.orig/debian/NEWS.Debian +++ haproxy-1.3.15.2/debian/NEWS.Debian @@ -0,0 +1,8 @@ +haproxy (1.3.14.2-1) unstable; urgency=low + + Configuration has moved to /etc/haproxy/haproxy.cfg. This allows to add the + configurable /etc/haproxy/errors directory. + The haproxy binary was also moved to /usr/sbin rather than /usr/bin, update + your init script or reinstall the one provided with the package. + + -- Arnaud Cornet Mon, 21 Jan 2008 23:38:15 +0100 --- haproxy-1.3.15.2.orig/debian/copyright +++ haproxy-1.3.15.2/debian/copyright @@ -0,0 +1,68 @@ +This package was debianized by Arnaud Cornet +on Fri, 17 Aug 2007 09:33:41 +0200. + +The current Debian maintainer is Arnaud Cornet + +It was downloaded from http://haproxy.1wt.eu/ +Upstream Author: Willy Tarreau + +Copyright: +include/common/base64.h common/uri_auth.h +and all files in src/* except those specified below are +copyright: + 2000-2007 Willy Tarreau + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + +All files in include/ and its subdirectories except those specified below are +copyright: + Copyright (C) 2000-2007 Willy Tarreau - w@1wt.eu + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, version 2.1 exclusively. + +src/rbtree.c +include/common/rbtree.h + (C) 1999 Andrea Arcangeli + (C) 2002 David Woodhouse + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + +src/sessiontable.c +include/common/sessionhash.h + Copyright 2007 Arnaud Cornet + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License, version 2.1 as published by the Free Software Foundation. + +src/appsession.c + Copyright 2004-2006 Alexander Lazic, Klaus Wagner + Copyright 2006-2007 Willy Tarreau + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + +include/import/ip_tproxy.h + Copyright (c) 2002-2004 BalaBit IT Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + +The Debian packaging is (C) 2007, Arnaud Cornet and +is licensed under the GPL version 2. + +On Debian systems, the complete text of the GNU General Public License, version +2, can be found in /usr/share/common-licenses/GPL-2 and the complete text of +the GNU Lesser General Public License, version 2.1, can be found in +/usr/share/common-licenses/GPL-2.1. + --- haproxy-1.3.15.2.orig/debian/control +++ haproxy-1.3.15.2/debian/control @@ -0,0 +1,17 @@ +Source: haproxy +Section: net +Priority: optional +Maintainer: Arnaud Cornet +Standards-Version: 3.8.0 +Build-Depends: debhelper (>= 7), libpcre3-dev, quilt +Homepage: http://haproxy.1wt.eu/ + +Package: haproxy +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, adduser +Description: fast and reliable load balancing reverse proxy + HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high + availability environments. It features connection persistence through HTTP + cookies, load balancing, header addition, modification, deletion both ways. It + has request blocking capabilities and provides interface to display server + status. --- haproxy-1.3.15.2.orig/debian/haproxy.cfg +++ haproxy-1.3.15.2/debian/haproxy.cfg @@ -0,0 +1,86 @@ +# this config needs haproxy-1.1.28 or haproxy-1.2.1 + +global + log 127.0.0.1 local0 + log 127.0.0.1 local1 notice + #log loghost local0 info + maxconn 4096 + #chroot /usr/share/haproxy + user haproxy + group haproxy + daemon + #debug + #quiet + +defaults + log global + mode http + option httplog + option dontlognull + retries 3 + option redispatch + maxconn 2000 + contimeout 5000 + clitimeout 50000 + srvtimeout 50000 + +listen appli1-rewrite 0.0.0.0:10001 + cookie SERVERID rewrite + balance roundrobin + server app1_1 192.168.34.23:8080 cookie app1inst1 check inter 2000 rise 2 fall 5 + server app1_2 192.168.34.32:8080 cookie app1inst2 check inter 2000 rise 2 fall 5 + server app1_3 192.168.34.27:8080 cookie app1inst3 check inter 2000 rise 2 fall 5 + server app1_4 192.168.34.42:8080 cookie app1inst4 check inter 2000 rise 2 fall 5 + +listen appli2-insert 0.0.0.0:10002 + option httpchk + balance roundrobin + cookie SERVERID insert indirect nocache + server inst1 192.168.114.56:80 cookie server01 check inter 2000 fall 3 + server inst2 192.168.114.56:81 cookie server02 check inter 2000 fall 3 + capture cookie vgnvisitor= len 32 + + option httpclose # disable keep-alive + rspidel ^Set-cookie:\ IP= # do not let this cookie tell our internal IP address + +listen appli3-relais 0.0.0.0:10003 + dispatch 192.168.135.17:80 + +listen appli4-backup 0.0.0.0:10004 + option httpchk /index.html + option persist + balance roundrobin + server inst1 192.168.114.56:80 check inter 2000 fall 3 + server inst2 192.168.114.56:81 check inter 2000 fall 3 backup + +listen ssl-relay 0.0.0.0:8443 + option ssl-hello-chk + balance source + server inst1 192.168.110.56:443 check inter 2000 fall 3 + server inst2 192.168.110.57:443 check inter 2000 fall 3 + server back1 192.168.120.58:443 backup + +listen appli5-backup 0.0.0.0:10005 + option httpchk * + balance roundrobin + cookie SERVERID insert indirect nocache + server inst1 192.168.114.56:80 cookie server01 check inter 2000 fall 3 + server inst2 192.168.114.56:81 cookie server02 check inter 2000 fall 3 + server inst3 192.168.114.57:80 backup check inter 2000 fall 3 + capture cookie ASPSESSION len 32 + srvtimeout 20000 + + option httpclose # disable keep-alive + option checkcache # block response if set-cookie & cacheable + + rspidel ^Set-cookie:\ IP= # do not let this cookie tell our internal IP address + + #errorloc 502 http://192.168.114.58/error502.html + #errorfile 503 /etc/haproxy/errors/503.http + errorfile 400 /etc/haproxy/errors/400.http + errorfile 403 /etc/haproxy/errors/403.http + errorfile 408 /etc/haproxy/errors/408.http + errorfile 500 /etc/haproxy/errors/500.http + errorfile 502 /etc/haproxy/errors/502.http + errorfile 503 /etc/haproxy/errors/503.http + errorfile 504 /etc/haproxy/errors/504.http --- haproxy-1.3.15.2.orig/debian/haproxy.manpages +++ haproxy-1.3.15.2/debian/haproxy.manpages @@ -0,0 +1 @@ +doc/haproxy.1 --- haproxy-1.3.15.2.orig/debian/haproxy.examples +++ haproxy-1.3.15.2/debian/haproxy.examples @@ -0,0 +1 @@ +examples/* --- haproxy-1.3.15.2.orig/debian/haproxy.init +++ haproxy-1.3.15.2/debian/haproxy.init @@ -0,0 +1,163 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: haproxy +# Required-Start: $local_fs $network +# Required-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: fast and reliable load balancing reverse proxy +# Description: This file should be used to start and stop haproxy. +### END INIT INFO + +# Author: Arnaud Cornet + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +PIDFILE=/var/run/haproxy.pid +CONFIG=/etc/haproxy/haproxy.cfg +HAPROXY=/usr/sbin/haproxy +EXTRAOPTS= +ENABLED=0 + +test -x $HAPROXY || exit 0 +test -f "$CONFIG" || exit 0 + +if [ -e /etc/default/haproxy ]; then + . /etc/default/haproxy +fi + +test "$ENABLED" != "0" || exit 0 + +[ -f /etc/default/rcS ] && . /etc/default/rcS +. /lib/lsb/init-functions + + +haproxy_start() +{ + start-stop-daemon --start --pidfile "$PIDFILE" \ + --exec $HAPROXY -- -f "$CONFIG" -D -p "$PIDFILE" \ + $EXTRAOPTS || return 2 + return 0 +} + +haproxy_stop() +{ + if [ ! -f $PIDFILE ] ; then + # This is a success according to LSB + return 0 + fi + for pid in $(cat $PIDFILE) ; do + /bin/kill $pid || return 4 + done + rm -f $PIDFILE + return 0 +} + +haproxy_reload() +{ + $HAPROXY -f "$CONFIG" -p $PIDFILE -D $EXTRAOPTS -sf $(cat $PIDFILE) \ + || return 2 + return 0 +} + +haproxy_status() +{ + if [ ! -f $PIDFILE ] ; then + # program not running + return 3 + fi + + for pid in $(cat $PIDFILE) ; do + if ! ps --no-headers p "$pid" | grep haproxy > /dev/null ; then + # program running, bogus pidfile + return 1 + fi + done + + return 0 +} + + +case "$1" in +start) + log_daemon_msg "Starting haproxy" "haproxy" + haproxy_start + ret=$? + case "$ret" in + 0) + log_end_msg 0 + ;; + 1) + log_end_msg 1 + echo "pid file '$PIDFILE' found, haproxy not started." + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +stop) + log_daemon_msg "Stopping haproxy" "haproxy" + haproxy_stop + ret=$? + case "$ret" in + 0|1) + log_end_msg 0 + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +reload|force-reload) + log_daemon_msg "Reloading haproxy" "haproxy" + haproxy_reload + case "$?" in + 0|1) + log_end_msg 0 + ;; + 2) + log_end_msg 1 + ;; + esac + ;; +restart) + log_daemon_msg "Restarting haproxy" "haproxy" + haproxy_stop + haproxy_start + case "$?" in + 0) + log_end_msg 0 + ;; + 1) + log_end_msg 1 + ;; + 2) + log_end_msg 1 + ;; + esac + ;; +status) + haproxy_status + ret=$? + case "$ret" in + 0) + echo "haproxy is running." + ;; + 1) + echo "haproxy dead, but $PIDFILE exists." + ;; + *) + echo "haproxy not running." + ;; + esac + exit $ret + ;; +*) + echo "Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}" + exit 2 + ;; +esac + +: --- haproxy-1.3.15.2.orig/debian/rules +++ haproxy-1.3.15.2/debian/rules @@ -0,0 +1,39 @@ +#!/usr/bin/make -f + +ifeq ($(shell uname -s),Linux) + TARGET=linux26 +else + TARGET=generic +endif + +build: + test -d patches || ln -s debian/patches + quilt push -a || test $$? = 2 + dh build --until dh_auto_configure + make PREFIX=/usr TARGET=$(TARGET) USE_PCRE=1 IGNOREGIT=true + dh build --after dh_auto_build + +clean: + dh clean + quilt pop -a || test $$? = 2 + rm -f patches + rm -rf .pc + +install: build + +binary-arch: install + dh binary-arch --before dh_auto_install + make TARGET=$(TARGET) DESTDIR=debian/haproxy PREFIX=/usr \ + MANDIR=/usr/share/man DOCDIR=/usr/share/doc/haproxy install + cp README debian/haproxy/usr/share/doc/haproxy + mkdir -p debian/haproxy/etc/haproxy + cp -r examples/errorfiles debian/haproxy/etc/haproxy/errors + rm debian/haproxy/etc/haproxy/errors/README + cp debian/haproxy.cfg debian/haproxy/etc/haproxy + dh binary-arch --after dh_auto_install + +binary-indep: install + dh binary-indep + +binary: binary-arch binary-indep + --- haproxy-1.3.15.2.orig/debian/haproxy.postinst +++ haproxy-1.3.15.2/debian/haproxy.postinst @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +USER=haproxy +GROUP=haproxy + +groups "$GROUP" > /dev/null 2>&1 || addgroup --system "$GROUP" +id "$USER" > /dev/null 2>&1 || adduser --system --no-create-home --ingroup "$GROUP" "$USER" + +#DEBHELPER# --- haproxy-1.3.15.2.orig/debian/compat +++ haproxy-1.3.15.2/debian/compat @@ -0,0 +1 @@ +5 --- haproxy-1.3.15.2.orig/debian/haproxy.docs +++ haproxy-1.3.15.2/debian/haproxy.docs @@ -0,0 +1,2 @@ +doc/* +debian/NEWS.Debian --- haproxy-1.3.15.2.orig/debian/patches/server-timeout.patch +++ haproxy-1.3.15.2/debian/patches/server-timeout.patch @@ -0,0 +1,41 @@ +commit df82605d3e73573ae842a1ddaf418997bef33274 +Author: Willy Tarreau +Date: Mon Aug 11 10:35:07 2008 +0200 + + [BUG] server timeout was not considered in some circumstances + + Due to a copy-paste typo, the client timeout was refreshed instead + of the server's when waiting for server response. This means that + the server's timeout remained eternity. + + (cherry picked from commit 9f1f24bb7fb8ebd6b43b5fee1bda0afbdbcb768e) + +diff --git a/src/stream_sock.c b/src/stream_sock.c +index 08cc65b..8bfc55b 100644 +--- a/src/stream_sock.c ++++ b/src/stream_sock.c +@@ -174,7 +174,7 @@ int stream_sock_read(int fd) { + * have at least read something. + */ + +- if (b->flags & BF_PARTIAL_READ) { ++ if (b->flags & BF_PARTIAL_READ && tv_isset(&b->rex)) { + if (tv_add_ifset(&b->rex, &now, &b->rto)) + goto out_wakeup; + out_eternity: +@@ -330,13 +330,13 @@ int stream_sock_write(int fd) { + * written something. + */ + +- if (b->flags & BF_PARTIAL_WRITE) { ++ if (b->flags & BF_PARTIAL_WRITE && tv_isset(&b->wex)) { + if (tv_add_ifset(&b->wex, &now, &b->wto)) { + /* FIXME: to prevent the client from expiring read timeouts during writes, + * we refresh it. A solution would be to merge read+write timeouts into a + * unique one, although that needs some study particularly on full-duplex + * TCP connections. */ +- if (!(b->flags & BF_SHUTR_STATUS)) ++ if (!(b->flags & BF_SHUTR_STATUS) && tv_isset(&b->rex)) + b->rex = b->wex; + goto out_wakeup; + } --- haproxy-1.3.15.2.orig/debian/patches/do-not-pause-backends-on-reload.patch +++ haproxy-1.3.15.2/debian/patches/do-not-pause-backends-on-reload.patch @@ -0,0 +1,133 @@ +Index: haproxy/include/proto/proxy.h +=================================================================== +--- haproxy.orig/include/proto/proxy.h 2008-12-30 18:13:53.000000000 +0100 ++++ haproxy/include/proto/proxy.h 2008-12-30 18:14:05.000000000 +0100 +@@ -30,6 +30,7 @@ + void maintain_proxies(struct timeval *next); + void soft_stop(void); + void pause_proxy(struct proxy *p); ++void stop_proxy(struct proxy *p); + void pause_proxies(void); + void listen_proxies(void); + +Index: haproxy/src/cfgparse.c +=================================================================== +--- haproxy.orig/src/cfgparse.c 2008-12-30 18:14:14.000000000 +0100 ++++ haproxy/src/cfgparse.c 2008-12-30 18:14:53.000000000 +0100 +@@ -2726,6 +2726,8 @@ + struct listener *listener; + + if (curproxy->state == PR_STSTOPPED) { ++ /* ensure we don't keep listeners uselessly bound */ ++ stop_proxy(curproxy); + curproxy = curproxy->next; + continue; + } +Index: haproxy/src/proxy.c +=================================================================== +--- haproxy.orig/src/proxy.c 2008-12-30 18:14:58.000000000 +0100 ++++ haproxy/src/proxy.c 2008-12-30 18:21:47.000000000 +0100 +@@ -352,14 +352,7 @@ + Warning("Proxy %s stopped.\n", p->id); + send_log(p, LOG_WARNING, "Proxy %s stopped.\n", p->id); + +- for (l = p->listen; l != NULL; l = l->next) { +- unbind_listener(l); +- if (l->state >= LI_ASSIGNED) { +- delete_listener(l); +- listeners--; +- } +- } +- p->state = PR_STSTOPPED; ++ stop_proxy(p); + /* try to free more memory */ + pool_gc2(); + } +@@ -388,8 +381,8 @@ + tv_now(&now); /* else, the old time before select will be used */ + while (p) { + if (p->state != PR_STSTOPPED) { +- Warning("Stopping proxy %s in %d ms.\n", p->id, p->grace); +- send_log(p, LOG_WARNING, "Stopping proxy %s in %d ms.\n", p->id, p->grace); ++ Warning("Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace); ++ send_log(p, LOG_WARNING, "Stopping %s %s in %d ms.\n", proxy_cap_str(p->cap), p->id, p->grace); + tv_ms_add(&p->stop_time, &now, p->grace); + } + p = p->next; +@@ -422,6 +415,27 @@ + } + + /* ++ * This function completely stops a proxy and releases its listeners. It has ++ * to be called when going down in order to release the ports so that another ++ * process may bind to them. It must also be called on disabled proxies at the ++ * end of start-up. When all listeners are closed, the proxy is set to the ++ * PR_STSTOPPED state. ++ */ ++void stop_proxy(struct proxy *p) ++{ ++ struct listener *l; ++ ++ for (l = p->listen; l != NULL; l = l->next) { ++ unbind_listener(l); ++ if (l->state >= LI_ASSIGNED) { ++ delete_listener(l); ++ listeners--; ++ } ++ } ++ p->state = PR_STSTOPPED; ++} ++ ++/* + * This function temporarily disables listening so that another new instance + * can start listening. It is designed to be called upon reception of a + * SIGTTOU, after which either a SIGUSR1 can be sent to completely stop +@@ -436,16 +450,17 @@ + p = proxy; + tv_now(&now); /* else, the old time before select will be used */ + while (p) { +- if (p->state != PR_STERROR && ++ if (p->cap & PR_CAP_FE && ++ p->state != PR_STERROR && + p->state != PR_STSTOPPED && + p->state != PR_STPAUSED) { +- Warning("Pausing proxy %s.\n", p->id); +- send_log(p, LOG_WARNING, "Pausing proxy %s.\n", p->id); ++ Warning("Pausing %s %s.\n", proxy_cap_str(p->cap), p->id); ++ send_log(p, LOG_WARNING, "Pausing %s %s.\n", proxy_cap_str(p->cap), p->id); + pause_proxy(p); + if (p->state != PR_STPAUSED) { + err |= 1; +- Warning("Proxy %s failed to enter pause mode.\n", p->id); +- send_log(p, LOG_WARNING, "Proxy %s failed to enter pause mode.\n", p->id); ++ Warning("%s %s failed to enter pause mode.\n", proxy_cap_str(p->cap), p->id); ++ send_log(p, LOG_WARNING, "%s %s failed to enter pause mode.\n", proxy_cap_str(p->cap), p->id); + } + } + p = p->next; +@@ -472,8 +487,8 @@ + tv_now(&now); /* else, the old time before select will be used */ + while (p) { + if (p->state == PR_STPAUSED) { +- Warning("Enabling proxy %s.\n", p->id); +- send_log(p, LOG_WARNING, "Enabling proxy %s.\n", p->id); ++ Warning("Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); ++ send_log(p, LOG_WARNING, "Enabling %s %s.\n", proxy_cap_str(p->cap), p->id); + + for (l = p->listen; l != NULL; l = l->next) { + if (listen(l->fd, p->backlog ? p->backlog : p->maxconn) == 0) { +@@ -491,10 +506,10 @@ + else + port = ntohs(((struct sockaddr_in *)(&l->addr))->sin_port); + +- Warning("Port %d busy while trying to enable proxy %s.\n", +- port, p->id); +- send_log(p, LOG_WARNING, "Port %d busy while trying to enable proxy %s.\n", +- port, p->id); ++ Warning("Port %d busy while trying to enable %s %s.\n", ++ port, proxy_cap_str(p->cap), p->id); ++ send_log(p, LOG_WARNING, "Port %d busy while trying to enable %s %s.\n", ++ port, proxy_cap_str(p->cap), p->id); + /* Another port might have been enabled. Let's stop everything. */ + pause_proxy(p); + break; --- haproxy-1.3.15.2.orig/debian/patches/connection-slot-during-retry.patch +++ haproxy-1.3.15.2/debian/patches/connection-slot-during-retry.patch @@ -0,0 +1,32 @@ +commit 8262d8bd7fdb262c980bd70cb2931e51df07513f +Author: Willy Tarreau +Date: Sun Sep 14 17:40:09 2008 +0200 + + [BUG] do not release the connection slot during a retry + + A bug was introduced during last queue management fix. If a server + connection fails, the allocated connection slot is released, but it + will be needed again after the turn-around. This also causes more + connections than expected to go to the server because it appears to + have less connections than real. + + Many thanks to Rupert Fiasco, Mark Imbriaco, Cody Fauser, Brian + Gupta and Alexander Staubo for promptly providing configuration + and diagnosis elements to help reproduce this problem easily. + +diff --git a/src/proto_http.c b/src/proto_http.c +index 425fde6..7500798 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -2686,10 +2686,8 @@ int process_srv(struct session *t) + } + else { + fd_delete(t->srv_fd); +- if (t->srv) { ++ if (t->srv) + t->srv->cur_sess--; +- sess_change_server(t, NULL); +- } + + if (!(req->flags & BF_WRITE_STATUS)) + conn_err = SN_ERR_SRVTO; // it was a connect timeout. --- haproxy-1.3.15.2.orig/debian/patches/dead-servers-queue.patch +++ haproxy-1.3.15.2/debian/patches/dead-servers-queue.patch @@ -0,0 +1,58 @@ +Index: haproxy/include/proto/queue.h +=================================================================== +--- haproxy.orig/include/proto/queue.h 2008-12-30 18:27:39.000000000 +0100 ++++ haproxy/include/proto/queue.h 2008-12-30 18:29:16.000000000 +0100 +@@ -64,10 +64,10 @@ + } + + /* returns 0 if nothing has to be done for server regarding queued connections, +- * and non-zero otherwise. Suited for and if/else usage. ++ * and non-zero otherwise. If the server is down, we only check its own queue. Suited for and if/else usage. + */ + static inline int may_dequeue_tasks(const struct server *s, const struct proxy *p) { +- return (s && (s->nbpend || p->nbpend) && ++ return (s && (s->nbpend || (p->nbpend && (s->state & SRV_RUNNING))) && + (!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s))); + } + +Index: haproxy/src/queue.c +=================================================================== +--- haproxy.orig/src/queue.c 2008-12-30 18:29:24.000000000 +0100 ++++ haproxy/src/queue.c 2008-12-30 18:30:33.000000000 +0100 +@@ -89,6 +89,10 @@ + * returned. Note that neither nor may be NULL. + * Priority is given to the oldest request in the queue if both and + * have pending requests. This ensures that no request will be left unserved. ++ * The queue is not considered if the server is not RUNNING. The ++ * queue is still considered in this case, because if some connections remain ++ * there, it means that some requests have been forced there after it was seen ++ * down (eg: due to option persist). + * The session is immediately marked as "assigned", and both its and + * are set to , + */ +@@ -100,7 +104,7 @@ + ps = pendconn_from_srv(srv); + pp = pendconn_from_px(px); + /* we want to get the definitive pendconn in */ +- if (!pp) { ++ if (!pp || !(srv->state & SRV_RUNNING)) { + if (!ps) + return NULL; + } else { +Index: haproxy/src/session.c +=================================================================== +--- haproxy.orig/src/session.c 2008-12-30 18:30:52.000000000 +0100 ++++ haproxy/src/session.c 2008-12-30 18:35:40.000000000 +0100 +@@ -41,8 +41,10 @@ + + if (s->pend_pos) + pendconn_free(s->pend_pos); +- if (s->srv) /* there may be requests left pending in queue */ +- process_srv_queue(s->srv); ++ if (s->srv) { /* there may be requests left pending in queue */ ++ if (may_dequeue_tasks(s->srv, s->be)) ++ process_srv_queue(s->srv); ++ } + if (unlikely(s->srv_conn)) { + /* the session still has a reserved slot on a server, but + * it should normally be only the same as the one above, --- haproxy-1.3.15.2.orig/debian/patches/cookie-capture-check.patch +++ haproxy-1.3.15.2/debian/patches/cookie-capture-check.patch @@ -0,0 +1,72 @@ +commit bfca9e51b77b856593a3c4a3215a8e0397e7cdba +Author: Willy Tarreau +Date: Fri Oct 17 12:01:58 2008 +0200 + + [BUG] cookie capture is declared in the frontend but checked on the backend + + Cookie capture would only work by pure luck on the request but did + never work on responses since only the backend was checked. The fix + consists in always checking frontend for cookie captures. + (cherry picked from commit a83c5ba9315a7c47cda2698280b7e49a9d3eb374) + +diff --git a/src/proto_http.c b/src/proto_http.c +index 7500798..0a59fe1 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -2009,7 +2009,7 @@ int process_cli(struct session *t) + * the fields will stay coherent and the URI will not move. + * This should only be performed in the backend. + */ +- if ((t->be->cookie_name || t->be->appsession_name || t->be->capture_name) ++ if ((t->be->cookie_name || t->be->appsession_name || t->fe->capture_name) + && !(txn->flags & (TX_CLDENY|TX_CLTARPIT))) + manage_client_side_cookies(t, req); + +@@ -3193,7 +3193,7 @@ int process_srv(struct session *t) + /* + * 4: check for server cookie. + */ +- if (t->be->cookie_name || t->be->appsession_name || t->be->capture_name ++ if (t->be->cookie_name || t->be->appsession_name || t->fe->capture_name + || (t->be->options & PR_O_CHK_CACHE)) + manage_server_side_cookies(t, rep); + +@@ -4600,10 +4600,12 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr) + txn->flags |= TX_SCK_ANY; + + +- /* maybe we only wanted to see if there was a set-cookie */ ++ /* maybe we only wanted to see if there was a set-cookie. Note that ++ * the cookie capture is declared on the frontend. ++ */ + if (t->be->cookie_name == NULL && + t->be->appsession_name == NULL && +- t->be->capture_name == NULL) ++ t->fe->capture_name == NULL) + return; + + p1 = cur_ptr + val; /* first non-space char after 'Set-Cookie:' */ +@@ -4635,18 +4637,18 @@ void manage_server_side_cookies(struct session *t, struct buffer *rtr) + */ + + /* first, let's see if we want to capture it */ +- if (t->be->capture_name != NULL && ++ if (t->fe->capture_name != NULL && + txn->srv_cookie == NULL && +- (p4 - p1 >= t->be->capture_namelen) && +- memcmp(p1, t->be->capture_name, t->be->capture_namelen) == 0) { ++ (p4 - p1 >= t->fe->capture_namelen) && ++ memcmp(p1, t->fe->capture_name, t->fe->capture_namelen) == 0) { + int log_len = p4 - p1; + + if ((txn->srv_cookie = pool_alloc2(pool2_capture)) == NULL) { + Alert("HTTP logging : out of memory.\n"); + } + +- if (log_len > t->be->capture_len) +- log_len = t->be->capture_len; ++ if (log_len > t->fe->capture_len) ++ log_len = t->fe->capture_len; + memcpy(txn->srv_cookie, p1, log_len); + txn->srv_cookie[log_len] = 0; + } --- haproxy-1.3.15.2.orig/debian/patches/srv_dynamic_maxconn.patch +++ haproxy-1.3.15.2/debian/patches/srv_dynamic_maxconn.patch @@ -0,0 +1,28 @@ +commit 819970098f134453c0934047b3bd3440b0996b55 +Author: Willy Tarreau +Date: Sun Sep 14 17:43:27 2008 +0200 + + [BUG] dynamic connection throttling could return a max of zero conns + + srv_dynamic_maxconn() is clearly documented as returning at least 1 + possible connection under throttling. But the computation was wrong, + the minimum 1 was divided and got lost in case of very low maxconns. + + Apply the MAX(1, max) before returning the result in order to ensure + that a newly appeared server will get some traffic. + +diff --git a/src/queue.c b/src/queue.c +index 178f187..905994a 100644 +--- a/src/queue.c ++++ b/src/queue.c +@@ -55,8 +55,8 @@ unsigned int srv_dynamic_maxconn(const struct server *s) + now.tv_sec < s->last_change + s->slowstart && + now.tv_sec >= s->last_change) { + unsigned int ratio; +- ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart); +- max = max * ratio / 100; ++ ratio = 100 * (now.tv_sec - s->last_change) / s->slowstart; ++ max = MAX(1, max * ratio / 100); + } + return max; + } --- haproxy-1.3.15.2.orig/debian/patches/acl-in-default.patch +++ haproxy-1.3.15.2/debian/patches/acl-in-default.patch @@ -0,0 +1,77 @@ +commit 1c90a6ec20946a713e9c93995a8e91ed3eeb9da4 +Author: Willy Tarreau +Date: Sun Oct 12 17:26:37 2008 +0200 + + [BUG] acl-related keywords are not allowed in defaults sections + + Using an ACL-related keyword in the defaults section causes a + segfault during parsing because the list headers are not initialized. + We must initialize list headers for default instance and reject + keywords relying on ACLs. + +diff --git a/src/cfgparse.c b/src/cfgparse.c +index b33800c..038915a 100644 +--- a/src/cfgparse.c ++++ b/src/cfgparse.c +@@ -516,6 +516,13 @@ static void init_default_instance() + defproxy.maxconn = cfg_maxpconn; + defproxy.conn_retries = CONN_RETRIES; + defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */ ++ ++ LIST_INIT(&defproxy.pendconns); ++ LIST_INIT(&defproxy.acl); ++ LIST_INIT(&defproxy.block_cond); ++ LIST_INIT(&defproxy.mon_fail_cond); ++ LIST_INIT(&defproxy.switching_rules); ++ + proxy_reset_timeouts(&defproxy); + } + +@@ -837,6 +844,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) + curproxy->state = PR_STNEW; + } + else if (!strcmp(args[0], "acl")) { /* add an ACL */ ++ if (curproxy == &defproxy) { ++ Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); ++ return -1; ++ } ++ + err = invalid_char(args[1]); + if (err) { + Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n", +@@ -1076,6 +1088,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) + int pol = ACL_COND_NONE; + struct acl_cond *cond; + ++ if (curproxy == &defproxy) { ++ Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); ++ return -1; ++ } ++ + if (!strcmp(args[1], "if")) + pol = ACL_COND_IF; + else if (!strcmp(args[1], "unless")) +@@ -1099,6 +1116,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) + struct acl_cond *cond; + struct switching_rule *rule; + ++ if (curproxy == &defproxy) { ++ Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); ++ return -1; ++ } ++ + if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL)) + return 0; + +@@ -1376,6 +1398,11 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv) + } + } + else if (!strcmp(args[0], "monitor")) { ++ if (curproxy == &defproxy) { ++ Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); ++ return -1; ++ } ++ + if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL)) + return 0; + --- haproxy-1.3.15.2.orig/debian/patches/use_backend-consider-unless.patch +++ haproxy-1.3.15.2/debian/patches/use_backend-consider-unless.patch @@ -0,0 +1,23 @@ +commit e05484f3ec2f2824c88d3a0c68a415111addadb1 +Author: Willy Tarreau +Date: Wed Jul 9 11:23:31 2008 +0200 + + [BUG] use_backend would not correctly consider "unless" + + A copy-paste typo made use_backend not correctly consider the "unless" + case, depending on the previous "block" rule. + (cherry picked from commit a8cfa34a9c011cecfaedfaf7d91de3e5f7f004a0) + +diff --git a/src/proto_http.c b/src/proto_http.c +index e36f4b0..f80129c 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -1925,7 +1925,7 @@ int process_cli(struct session *t) + int ret; + + ret = acl_exec_cond(rule->cond, cur_proxy, t, txn, ACL_DIR_REQ); +- if (cond->pol == ACL_COND_UNLESS) ++ if (rule->cond->pol == ACL_COND_UNLESS) + ret = !ret; + + if (ret) { --- haproxy-1.3.15.2.orig/debian/patches/closed-fd-remove.patch +++ haproxy-1.3.15.2/debian/patches/closed-fd-remove.patch @@ -0,0 +1,46 @@ +commit 116f4105d4fc6fbd8f2d0a139f691973332176de +Author: Willy Tarreau +Date: Sat Aug 16 16:06:02 2008 +0200 + + [BUG] ev_sepoll: closed file descriptors could persist in the spec list + + If __fd_clo() was called on a file descriptor which was previously + disabled, it was not removed from the spec list. This apparently + could not happen on previous code because the TCP states prevented + this, but now it happens regularly. The effects are spec entries + stuck populated, leading to busy loops. + + (cherry picked from commit 7a52a5c4680477272b2f34eaf5896b85746e6fd6) + +diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c +index 800ac0b..db35423 100644 +--- a/src/ev_sepoll.c ++++ b/src/ev_sepoll.c +@@ -279,8 +279,7 @@ REGPRM1 static void __fd_rem(int fd) + */ + REGPRM1 static void __fd_clo(int fd) + { +- if (fd_list[fd].e & FD_EV_RW_SL) +- release_spec_entry(fd); ++ release_spec_entry(fd); + fd_list[fd].e &= ~(FD_EV_MASK); + } + +@@ -325,7 +324,7 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) + fdtab[fd].ev &= FD_POLL_STICKY; + if ((eo & FD_EV_MASK_R) == FD_EV_SPEC_R) { + /* The owner is interested in reading from this FD */ +- if (fdtab[fd].state != FD_STCLOSE && fdtab[fd].state != FD_STERROR) { ++ if (fdtab[fd].state != FD_STERROR) { + /* Pretend there is something to read */ + fdtab[fd].ev |= FD_POLL_IN; + if (!fdtab[fd].cb[DIR_RD].f(fd)) +@@ -341,7 +340,7 @@ REGPRM2 static void _do_poll(struct poller *p, struct timeval *exp) + + if ((eo & FD_EV_MASK_W) == FD_EV_SPEC_W) { + /* The owner is interested in writing to this FD */ +- if (fdtab[fd].state != FD_STCLOSE && fdtab[fd].state != FD_STERROR) { ++ if (fdtab[fd].state != FD_STERROR) { + /* Pretend there is something to write */ + fdtab[fd].ev |= FD_POLL_OUT; + if (!fdtab[fd].cb[DIR_WR].f(fd)) --- haproxy-1.3.15.2.orig/debian/patches/series +++ haproxy-1.3.15.2/debian/patches/series @@ -0,0 +1,10 @@ +use_backend-consider-unless.patch +segfault-url_param+check_post.patch +server-timeout.patch +closed-fd-remove.patch +connection-slot-during-retry.patch +srv_dynamic_maxconn.patch +do-not-pause-backends-on-reload.patch +acl-in-default.patch +cookie-capture-check.patch +dead-servers-queue.patch --- haproxy-1.3.15.2.orig/debian/patches/segfault-url_param+check_post.patch +++ haproxy-1.3.15.2/debian/patches/segfault-url_param+check_post.patch @@ -0,0 +1,80 @@ +commit 3449d158ad4a44a7743854a9f754d4bd775007da +Author: Willy Tarreau +Date: Mon Aug 11 00:21:56 2008 +0200 + + [BUG] fix segfault with url_param + check_post + + If an HTTP/0.9-like POST request is sent to haproxy while + configured with url_param + check_post, it will crash. The + reason is that the total buffer length was computed based + on req->total (which equals the number of bytes read) and + not req->l (number of bytes in the buffer), thus leading + to wrong size calculations when calling memchr(). + + The affected code does not look like it could have been + exploited to run arbitrary code, only reads were performed + at wrong locations. + (cherry picked from commit fb0528bd56063e9800c7dd6fbd96b3c5c6a687f2) + +diff --git a/src/backend.c b/src/backend.c +index cdd8c90..26e6495 100644 +--- a/src/backend.c ++++ b/src/backend.c +@@ -1201,7 +1201,7 @@ struct server *get_server_ph_post(struct session *s) + return NULL; + + body = msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1; +- len = req->total - body; ++ len = req->l - body; + params = req->data + body; + + if ( len == 0 ) +diff --git a/src/proto_http.c b/src/proto_http.c +index f80129c..425fde6 100644 +--- a/src/proto_http.c ++++ b/src/proto_http.c +@@ -2077,7 +2077,7 @@ int process_cli(struct session *t) + */ + if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) && + t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL && +- t->be->url_param_post_limit != 0 && req->total < BUFSIZE && ++ t->be->url_param_post_limit != 0 && req->l < BUFSIZE && + memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) { + /* are there enough bytes here? total == l || r || rlim ? + * len is unsigned, but eoh is int, +@@ -2085,7 +2085,7 @@ int process_cli(struct session *t) + * eoh is the first empty line of the header + */ + /* already established CRLF or LF at eoh, move to start of message, find message length in buffer */ +- unsigned long len = req->total - (msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1); ++ unsigned long len = req->l - (msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 : msg->eoh + 1); + + /* If we have HTTP/1.1 and Expect: 100-continue, then abort. + * We can't assume responsibility for the server's decision, +@@ -3615,7 +3615,7 @@ int process_srv(struct session *t) + */ + struct http_msg * msg = &t->txn.req; + unsigned long body = msg->sol[msg->eoh] == '\r' ? msg->eoh + 2 :msg->eoh + 1; +- unsigned long len = req->total - body; ++ unsigned long len = req->l - body; + long long limit = t->be->url_param_post_limit; + struct hdr_ctx ctx; + ctx.idx = 0; +@@ -3623,7 +3623,7 @@ int process_srv(struct session *t) + http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx); + if ( ctx.idx && strncasecmp(ctx.line+ctx.val,"chunked",ctx.vlen)==0) { + unsigned int chunk = 0; +- while ( body < req->total && !HTTP_IS_CRLF(msg->sol[body])) { ++ while ( body < req->l && !HTTP_IS_CRLF(msg->sol[body])) { + char c = msg->sol[body]; + if (ishex(c)) { + unsigned int hex = toupper(c) - '0'; +@@ -3635,7 +3635,7 @@ int process_srv(struct session *t) + body++; + len--; + } +- if ( body == req->total ) ++ if ( body + 2 >= req->l ) + return 0; /* end of buffer? data missing! */ + + if ( memcmp(msg->sol+body, "\r\n", 2) != 0 )