package: haproxy

- add backported patches for 1.4.22



git-svn-id: svn://svn.openwrt.org/openwrt/packages@36152 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
heil 2013-04-02 13:52:02 +00:00
parent 12829985fd
commit 89cca70763
8 changed files with 534 additions and 1 deletions

View File

@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=haproxy PKG_NAME:=haproxy
PKG_VERSION:=1.4.22 PKG_VERSION:=1.4.22
PKG_RELEASE:=35 PKG_RELEASE:=42
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src

View File

@ -0,0 +1,71 @@
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

View File

@ -0,0 +1,28 @@
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

View File

@ -0,0 +1,47 @@
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

View File

@ -0,0 +1,193 @@
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

View File

@ -0,0 +1,77 @@
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

View File

@ -0,0 +1,60 @@
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

View File

@ -0,0 +1,57 @@
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