PKG_NAME:=haproxy
PKG_VERSION:=1.4.22
-PKG_RELEASE:=35
+PKG_RELEASE:=42
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src
--- /dev/null
+From 8a92e409e706e503ba76f8863c87409192e9f082 Mon Sep 17 00:00:00 2001
+From: Yves Lafon <ylafon@w3.org>
+Date: Mon, 11 Mar 2013 11:06:05 -0400
+Subject: [PATCH 36/42] MEDIUM: http: implement redirect 307 and 308
+
+I needed to emit a 307 and noticed it was not available so I did it,
+as well as 308.
+(cherry picked from commit 3e8d1ae2d25d3fae659fc560506af2ae9b20da12)
+---
+ src/cfgparse.c | 6 +++---
+ src/proto_http.c | 20 ++++++++++++++++++++
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/src/cfgparse.c b/src/cfgparse.c
+index e55d30a..345b415 100644
+--- a/src/cfgparse.c
++++ b/src/cfgparse.c
+@@ -2215,9 +2215,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
+ }
+ cur_arg++;
+ code = atol(args[cur_arg]);
+- if (code < 301 || code > 303) {
+- Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
+- file, linenum, args[0], code);
++ if (code < 301 || code > 308 || (code > 303 && code < 307)) {
++ Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%s' (must be one of 301, 302, 303, 307 or 308).\n",
++ file, linenum, args[0], args[cur_arg]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+diff --git a/src/proto_http.c b/src/proto_http.c
+index 06b3743..8d9d8e8 100644
+--- a/src/proto_http.c
++++ b/src/proto_http.c
+@@ -90,6 +90,20 @@ const char *HTTP_303 =
+ "Content-length: 0\r\n"
+ "Location: "; /* not terminated since it will be concatenated with the URL */
+
++
++/* same as 302 except that the browser MUST retry with the same method */
++const char *HTTP_307 =
++ "HTTP/1.1 307 Temporary Redirect\r\n"
++ "Cache-Control: no-cache\r\n"
++ "Content-length: 0\r\n"
++ "Location: "; /* not terminated since it will be concatenated with the URL */
++
++/* same as 301 except that the browser MUST retry with the same method */
++const char *HTTP_308 =
++ "HTTP/1.1 308 Permanent Redirect\r\n"
++ "Content-length: 0\r\n"
++ "Location: "; /* not terminated since it will be concatenated with the URL */
++
+ /* Warning: this one is an sprintf() fmt string, with <realm> as its only argument */
+ const char *HTTP_401_fmt =
+ "HTTP/1.0 401 Unauthorized\r\n"
+@@ -3355,6 +3369,12 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
+
+ /* build redirect message */
+ switch(rule->code) {
++ case 308:
++ msg_fmt = HTTP_308;
++ break;
++ case 307:
++ msg_fmt = HTTP_307;
++ break;
+ case 303:
+ msg_fmt = HTTP_303;
+ break;
+--
+1.8.1.5
+
--- /dev/null
+From 6c9ba3562cf57dc033a52c0973962c642b3aaf18 Mon Sep 17 00:00:00 2001
+From: Yves Lafon <ylafon@w3.org>
+Date: Mon, 11 Mar 2013 11:06:05 -0400
+Subject: [PATCH 37/42] MINOR: http: status 301 should not be marked
+ non-cacheable
+
+Also, browsers behaviour is inconsistent regarding the Cache-Control
+header field on a 301.
+(cherry picked from commit e267421e93eb35272a104c9c8fa6878880f42be8)
+---
+ src/proto_http.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/proto_http.c b/src/proto_http.c
+index 8d9d8e8..a52c038 100644
+--- a/src/proto_http.c
++++ b/src/proto_http.c
+@@ -73,7 +73,6 @@ const struct chunk http_100_chunk = {
+ /* Warning: no "connection" header is provided with the 3xx messages below */
+ const char *HTTP_301 =
+ "HTTP/1.1 301 Moved Permanently\r\n"
+- "Cache-Control: no-cache\r\n"
+ "Content-length: 0\r\n"
+ "Location: "; /* not terminated since it will be concatenated with the URL */
+
+--
+1.8.1.5
+
--- /dev/null
+From 89c12b19f9e42976c9c205cd1a42bb2e148b3235 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Fri, 29 Mar 2013 19:28:11 +0100
+Subject: [PATCH 38/42] DOC: mention the new HTTP 307 and 308 redirect statues
+ (cherry picked from commit b67fdc4cd8bde202f2805d98683ddab929469a05)
+
+---
+ doc/configuration.txt | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/doc/configuration.txt b/doc/configuration.txt
+index 20b89c2..9a99267 100644
+--- a/doc/configuration.txt
++++ b/doc/configuration.txt
+@@ -309,6 +309,8 @@ Haproxy may emit the following status codes by itself :
+ 301 when performing a redirection, depending on the configured code
+ 302 when performing a redirection, depending on the configured code
+ 303 when performing a redirection, depending on the configured code
++ 307 when performing a redirection, depending on the configured code
++ 308 when performing a redirection, depending on the configured code
+ 400 for an invalid or too large request
+ 401 when an authentication is required to perform the action (when
+ accessing the stats page)
+@@ -4057,12 +4059,14 @@ redirect prefix <to> [code <code>] <option> [{if | unless} <condition>]
+ URL.
+
+ <code> The code is optional. It indicates which type of HTTP redirection
+- is desired. Only codes 301, 302 and 303 are supported, and 302 is
+- used if no code is specified. 301 means "Moved permanently", and
+- a browser may cache the Location. 302 means "Moved permanently"
+- and means that the browser should not cache the redirection. 303
+- is equivalent to 302 except that the browser will fetch the
+- location with a GET method.
++ is desired. Only codes 301, 302, 303, 307 and 308 are supported,
++ with 302 used by default if no code is specified. 301 means
++ "Moved permanently", and a browser may cache the Location. 302
++ means "Moved permanently" and means that the browser should not
++ cache the redirection. 303 is equivalent to 302 except that the
++ browser will fetch the location with a GET method. 307 is just
++ like 302 but makes it clear that the same method must be reused.
++ Likewise, 308 replaces 301 if the same method must be used.
+
+ <option> There are several options which can be specified to adjust the
+ expected behaviour of a redirection :
+--
+1.8.1.5
+
--- /dev/null
+From d9185dbab66e8ea3bafd1d43660ae44311da7a81 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Sun, 31 Mar 2013 14:06:57 +0200
+Subject: [PATCH 39/42] MEDIUM: poll: do not use FD_* macros anymore
+
+Some recent glibc updates have added controls on FD_SET/FD_CLR/FD_ISSET
+that crash the program if it tries to use a file descriptor larger than
+FD_SETSIZE.
+
+Do not rely on FD_* macros anymore and replace them with bit fields.
+(cherry picked from commit 80da05a4cfb881663dc1f38a94d613f37e54552a)
+---
+ src/ev_poll.c | 87 +++++++++++++++++++++++++++++------------------------------
+ 1 file changed, 43 insertions(+), 44 deletions(-)
+
+diff --git a/src/ev_poll.c b/src/ev_poll.c
+index f5d011e..02e89ad 100644
+--- a/src/ev_poll.c
++++ b/src/ev_poll.c
+@@ -27,12 +27,25 @@
+ #include <proto/task.h>
+
+
+-static fd_set *fd_evts[2];
++static unsigned int *fd_evts[2];
+
+ /* private data */
+ static struct pollfd *poll_events = NULL;
+
++static inline unsigned int hap_fd_isset(int fd, unsigned int *evts)
++{
++ return evts[fd / (8*sizeof(*evts))] & (1U << (fd & (8*sizeof(*evts) - 1)));
++}
++
++static inline void hap_fd_set(int fd, unsigned int *evts)
++{
++ evts[fd / (8*sizeof(*evts))] |= 1U << (fd & (8*sizeof(*evts) - 1));
++}
+
++static inline void hap_fd_clr(int fd, unsigned int *evts)
++{
++ evts[fd / (8*sizeof(*evts))] &= ~(1U << (fd & (8*sizeof(*evts) - 1)));
++}
+ /*
+ * Benchmarks performed on a Pentium-M notebook show that using functions
+ * instead of the usual macros improve the FD_* performance by about 80%,
+@@ -40,43 +53,43 @@ static struct pollfd *poll_events = NULL;
+ */
+ REGPRM2 static int __fd_is_set(const int fd, int dir)
+ {
+- return FD_ISSET(fd, fd_evts[dir]);
++ return hap_fd_isset(fd, fd_evts[dir]);
+ }
+
+ REGPRM2 static int __fd_set(const int fd, int dir)
+ {
+- FD_SET(fd, fd_evts[dir]);
++ hap_fd_set(fd, fd_evts[dir]);
+ return 0;
+ }
+
+ REGPRM2 static int __fd_clr(const int fd, int dir)
+ {
+- FD_CLR(fd, fd_evts[dir]);
++ hap_fd_clr(fd, fd_evts[dir]);
+ return 0;
+ }
+
+ REGPRM2 static int __fd_cond_s(const int fd, int dir)
+ {
+ int ret;
+- ret = !FD_ISSET(fd, fd_evts[dir]);
++ ret = !hap_fd_isset(fd, fd_evts[dir]);
+ if (ret)
+- FD_SET(fd, fd_evts[dir]);
++ hap_fd_set(fd, fd_evts[dir]);
+ return ret;
+ }
+
+ REGPRM2 static int __fd_cond_c(const int fd, int dir)
+ {
+ int ret;
+- ret = FD_ISSET(fd, fd_evts[dir]);
++ ret = hap_fd_isset(fd, fd_evts[dir]);
+ if (ret)
+- FD_CLR(fd, fd_evts[dir]);
++ hap_fd_clr(fd, fd_evts[dir]);
+ return ret;
+ }
+
+ REGPRM1 static void __fd_rem(const int fd)
+ {
+- FD_CLR(fd, fd_evts[DIR_RD]);
+- FD_CLR(fd, fd_evts[DIR_WR]);
++ hap_fd_clr(fd, fd_evts[DIR_RD]);
++ hap_fd_clr(fd, fd_evts[DIR_WR]);
+ }
+
+ /*
+@@ -93,33 +106,20 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
+ unsigned rn, wn; /* read new, write new */
+
+ nbfd = 0;
+- for (fds = 0; (fds * BITS_PER_INT) < maxfd; fds++) {
+-
+- rn = ((int*)fd_evts[DIR_RD])[fds];
+- wn = ((int*)fd_evts[DIR_WR])[fds];
++ for (fds = 0; (fds * 8*sizeof(**fd_evts)) < maxfd; fds++) {
++ rn = fd_evts[DIR_RD][fds];
++ wn = fd_evts[DIR_WR][fds];
+
+- if ((rn|wn)) {
+- for (count = 0, fd = fds * BITS_PER_INT; count < BITS_PER_INT && fd < maxfd; count++, fd++) {
+-#define FDSETS_ARE_INT_ALIGNED
+-#ifdef FDSETS_ARE_INT_ALIGNED
+-
+-#define WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS
+-#ifdef WE_REALLY_KNOW_THAT_FDSETS_ARE_INTS
+- sr = (rn >> count) & 1;
+- sw = (wn >> count) & 1;
+-#else
+- sr = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&rn);
+- sw = FD_ISSET(fd&(BITS_PER_INT-1), (typeof(fd_set*))&wn);
+-#endif
+-#else
+- sr = FD_ISSET(fd, fd_evts[DIR_RD]);
+- sw = FD_ISSET(fd, fd_evts[DIR_WR]);
+-#endif
+- if ((sr|sw)) {
+- poll_events[nbfd].fd = fd;
+- poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0);
+- nbfd++;
+- }
++ if (!(rn|wn))
++ continue;
++
++ for (count = 0, fd = fds * 8*sizeof(**fd_evts); count < 8*sizeof(**fd_evts) && fd < maxfd; count++, fd++) {
++ sr = (rn >> count) & 1;
++ sw = (wn >> count) & 1;
++ if ((sr|sw)) {
++ poll_events[nbfd].fd = fd;
++ poll_events[nbfd].events = (sr ? POLLIN : 0) | (sw ? POLLOUT : 0);
++ nbfd++;
+ }
+ }
+ }
+@@ -149,14 +149,14 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
+ /* ok, we found one active fd */
+ status--;
+
+- if (FD_ISSET(fd, fd_evts[DIR_RD])) {
++ if (hap_fd_isset(fd, fd_evts[DIR_RD])) {
+ if (fdtab[fd].state == FD_STCLOSE)
+ continue;
+ if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP ))
+ fdtab[fd].cb[DIR_RD].f(fd);
+ }
+
+- if (FD_ISSET(fd, fd_evts[DIR_WR])) {
++ if (hap_fd_isset(fd, fd_evts[DIR_WR])) {
+ if (fdtab[fd].state == FD_STCLOSE)
+ continue;
+ if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP ))
+@@ -174,21 +174,20 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
+ REGPRM1 static int _do_init(struct poller *p)
+ {
+ __label__ fail_swevt, fail_srevt, fail_pe;
+- int fd_set_bytes;
++ int fd_evts_bytes;
+
+ p->private = NULL;
+- fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE;
++ fd_evts_bytes = (global.maxsock + sizeof(**fd_evts) - 1) / sizeof(**fd_evts) * sizeof(**fd_evts);
+
+- poll_events = (struct pollfd*)
+- calloc(1, sizeof(struct pollfd) * global.maxsock);
++ poll_events = calloc(1, sizeof(struct pollfd) * global.maxsock);
+
+ if (poll_events == NULL)
+ goto fail_pe;
+
+- if ((fd_evts[DIR_RD] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
++ if ((fd_evts[DIR_RD] = calloc(1, fd_evts_bytes)) == NULL)
+ goto fail_srevt;
+
+- if ((fd_evts[DIR_WR] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
++ if ((fd_evts[DIR_WR] = calloc(1, fd_evts_bytes)) == NULL)
+ goto fail_swevt;
+
+ return 1;
+--
+1.8.1.5
+
--- /dev/null
+From f4096052b9397e29c3638651e7487c047081c00c Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Sun, 31 Mar 2013 14:41:15 +0200
+Subject: [PATCH 40/42] BUG/MAJOR: ev_select: disable the select() poller if
+ maxsock > FD_SETSIZE
+
+Some recent glibc updates have added controls on FD_SET/FD_CLR/FD_ISSET
+that crash the program if it tries to use a file descriptor larger than
+FD_SETSIZE.
+
+For this reason, we now control the compatibility between global.maxsock
+and FD_SETSIZE, and refuse to use select() if there too many FDs are
+expected to be used. Note that on Solaris, FD_SETSIZE is already forced
+to 65536, and that FreeBSD and OpenBSD allow it to be redefined, though
+this is not needed thanks to kqueue which is much more efficient.
+
+In practice, since poll() is enabled on all targets, it should not cause
+any problem, unless it is explicitly disabled.
+
+This change must be backported to 1.4 because the crashes caused by glibc
+have already been reported on this version.
+(cherry picked from commit 3fa87b1db95bc4d6640999462bdae620bff147c6)
+---
+ src/ev_select.c | 7 +++++++
+ src/haproxy.c | 11 ++++++++++-
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/src/ev_select.c b/src/ev_select.c
+index 5a87282..1f35b54 100644
+--- a/src/ev_select.c
++++ b/src/ev_select.c
+@@ -170,6 +170,10 @@ REGPRM1 static int _do_init(struct poller *p)
+ int fd_set_bytes;
+
+ p->private = NULL;
++
++ if (global.maxsock > FD_SETSIZE)
++ goto fail_revt;
++
+ fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE;
+
+ if ((tmp_evts[DIR_RD] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
+@@ -217,6 +221,9 @@ REGPRM1 static void _do_term(struct poller *p)
+ */
+ REGPRM1 static int _do_test(struct poller *p)
+ {
++ if (global.maxsock > FD_SETSIZE)
++ return 0;
++
+ return 1;
+ }
+
+diff --git a/src/haproxy.c b/src/haproxy.c
+index c302143..1d588e1 100644
+--- a/src/haproxy.c
++++ b/src/haproxy.c
+@@ -711,7 +711,16 @@ void init(int argc, char **argv)
+ list_pollers(stderr);
+
+ if (!init_pollers()) {
+- Alert("No polling mechanism available.\n");
++ Alert("No polling mechanism available.\n"
++ " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
++ " is too low on this platform to support maxconn and the number of listeners\n"
++ " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
++ " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
++ " global maxconn setting to accomodate the system's limitation. For reference,\n"
++ " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
++ " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
++ " check build settings using 'haproxy -vv'.\n\n",
++ FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
+ exit(1);
+ }
+ if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
+--
+1.8.1.5
+
--- /dev/null
+From 4c5a09bb3c62070f139159378a8d68897b7ec8d6 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Tue, 2 Apr 2013 08:14:29 +0200
+Subject: [PATCH 41/42] BUILD: enable poll() by default in the makefile
+
+This allows to build haproxy for unknown targets and still have poll().
+If for any reason a target does not support it, just passing USE_POLL=""
+disables it.
+(cherry picked from commit 32e65ef62570cbace7368ebe7262b48c28b31bb7)
+---
+ Makefile | 5 ++++-
+ README | 9 ++++++++-
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 8d82543..f4dbccd 100644
+--- a/Makefile
++++ b/Makefile
+@@ -172,7 +172,10 @@ LDFLAGS = $(ARCH_FLAGS) -g
+ # Depending on the target platform, some options are set, as well as some
+ # CFLAGS and LDFLAGS. The USE_* values are set to "implicit" so that they are
+ # not reported in the build options string. You should not have to change
+-# anything there.
++# anything there. poll() is always supported, unless explicitly disabled by
++# passing USE_POLL="" on the make command line.
++USE_POLL = default
++
+ ifeq ($(TARGET),generic)
+ # generic system target has nothing specific
+ USE_POLL = implicit
+diff --git a/README b/README
+index aca83f9..c99897e 100644
+--- a/README
++++ b/README
+@@ -12,7 +12,7 @@
+ To build haproxy, you will need :
+ - GNU make. Neither Solaris nor OpenBSD's make work with the GNU Makefile.
+ However, specific Makefiles for BSD and OSX are provided.
+- - GCC between 2.91 and 4.5.0. Others may work, but not tested.
++ - GCC between 2.91 and 4.7. Others may work, but not tested.
+ - GNU ld
+
+ Also, you might want to build with libpcre support, which will provide a very
+@@ -100,6 +100,13 @@ otherwise __fd_select() will be used while not being present in the libc.
+ If you get build errors because of strange symbols or section mismatches,
+ simply remove -g from DEBUG_CFLAGS.
+
++You can easily define your own target with the GNU Makefile. Unknown targets
++are processed with no default option except USE_POLL=default. So you can very
++well use that property to define your own set of options. USE_POLL can even be
++disabled by setting USE_POLL="". For example :
++
++ $ gmake TARGET=tiny USE_POLL="" TARGET_CFLAGS=-fomit-frame-pointer
++
+
+ 2) How to install it
+ --------------------
+--
+1.8.1.5
+
--- /dev/null
+From 2d7b45e7321437c1f9c4d0f2c46a793ef9d059c0 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Tue, 2 Apr 2013 08:17:43 +0200
+Subject: [PATCH 42/42] BUILD: add explicit support for Mac OS/X
+
+The "osx" target may now be passed in the TARGET variable. It supports
+the same features as FreeBSD and allows its users to use the GNU makefile
+instead of the platform-specific makefile which lacks some features.
+(cherry picked from commit 8624cab29c52db9052bf022683cfd3d11369cc0d)
+---
+ Makefile | 8 ++++++++
+ README | 3 ++-
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index f4dbccd..57692fe 100644
+--- a/Makefile
++++ b/Makefile
+@@ -245,6 +245,13 @@ ifeq ($(TARGET),freebsd)
+ USE_TPROXY = implicit
+ USE_LIBCRYPT = implicit
+ else
++ifeq ($(TARGET),osx)
++ # This is for Mac OS/X
++ USE_POLL = implicit
++ USE_KQUEUE = implicit
++ USE_TPROXY = implicit
++ USE_LIBCRYPT = implicit
++else
+ ifeq ($(TARGET),openbsd)
+ # This is for OpenBSD >= 3.0
+ USE_POLL = implicit
+@@ -267,6 +274,7 @@ ifeq ($(TARGET),cygwin)
+ endif # cygwin
+ endif # aix52
+ endif # openbsd
++endif # osx
+ endif # freebsd
+ endif # solaris
+ endif # linux2628
+diff --git a/README b/README
+index c99897e..7897cb3 100644
+--- a/README
++++ b/README
+@@ -28,7 +28,8 @@ and assign it to the TARGET variable :
+ - linux2628 for Linux 2.6.28 and above (enables splice and tproxy)
+ - solaris for Solaris 8 or 10 (others untested)
+ - freebsd for FreeBSD 5 to 8.0 (others untested)
+- - openbsd for OpenBSD 3.1 to 4.6 (others untested)
++ - osx for Mac OS/X
++ - openbsd for OpenBSD 3.1 to 5.2 (others untested)
+ - aix52 for AIX 5.2
+ - cygwin for Cygwin
+ - generic for any other OS.
+--
+1.8.1.5
+