浏览代码

haproxy: import from packages, add myself as the maintainer

Signed-off-by: Thomas Heil <heil@terminal-consulting.de>
Thomas Heil 10 年前
父节点
当前提交
db5d567e7d

+ 62
- 0
net/haproxy/Makefile 查看文件

@@ -0,0 +1,62 @@
1
+#
2
+# Copyright (C) 2009-2014 Thomas Heil <heil@terminal-consulting.de>
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=haproxy
11
+PKG_VERSION:=1.4.25
12
+PKG_RELEASE:=01
13
+
14
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
15
+PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src
16
+PKG_MD5SUM:=74b5ec1f0f9b4d148c8083bcfb512ccd
17
+PKG_MAINTAINER:=Thomas Heil <heil@terminal-consulting.de>
18
+PKG_LICENSE:=GPL-2.0
19
+
20
+include $(INCLUDE_DIR)/package.mk
21
+
22
+define Package/haproxy
23
+  SUBMENU:=Web Servers/Proxies
24
+  SECTION:=net
25
+  CATEGORY:=Network
26
+  TITLE:=The Reliable, High Performance TCP/HTTP Load Balancer
27
+  URL:=http://haproxy.1wt.eu/
28
+  DEPENDS:=+libpcre +libltdl
29
+endef
30
+
31
+define Package/haproxy/conffiles
32
+/etc/haproxy.cfg
33
+endef
34
+
35
+define Package/haproxy/description
36
+  Open source High Performance TCP/HTTP Load Balancer
37
+endef
38
+
39
+define Build/Compile
40
+	$(MAKE) TARGET=linux2628 -C $(PKG_BUILD_DIR) \
41
+		DESTDIR="$(PKG_INSTALL_DIR)" \
42
+		CC="$(TARGET_CC)" \
43
+		CFLAGS="$(TARGET_CFLAGS)" \
44
+		LD="$(TARGET_CC)" \
45
+		LDFLAGS="$(TARGET_LDFLAGS)" \
46
+		SMALL_OPTS="-DBUFSIZE=16384 -DMAXREWRITE=8192 -DSYSTEM_MAXCONN=65530" USE_LINUX_TPROXY=1 USE_LINUX_SPLICE=1 \
47
+		VERSION="$(PKG_VERSION)-patch$(PKG_RELEASE)" \
48
+		all install
49
+endef
50
+
51
+define Package/haproxy/install
52
+	$(INSTALL_DIR) $(1)/usr/sbin
53
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/haproxy $(1)/usr/sbin/
54
+	$(INSTALL_DIR) $(1)/etc
55
+	$(INSTALL_CONF) ./files/haproxy.cfg $(1)/etc/
56
+	$(INSTALL_DIR) $(1)/etc/init.d
57
+	$(INSTALL_BIN) ./files/haproxy.init $(1)/etc/init.d/haproxy
58
+	$(INSTALL_DIR) $(1)/etc/hotplug.d/net
59
+	$(INSTALL_BIN) ./files/haproxy.hotplug $(1)/etc/hotplug.d/net/90-haproxy
60
+endef
61
+
62
+$(eval $(call BuildPackage,haproxy))

+ 100
- 0
net/haproxy/files/haproxy.cfg 查看文件

@@ -0,0 +1,100 @@
1
+# Example configuration file for HAProxy 1.3, refer to the url below for
2
+# a full documentation and examples for configuration:
3
+# http://haproxy.1wt.eu/download/1.3/doc/configuration.txt
4
+
5
+
6
+# Global parameters
7
+global
8
+
9
+	# Log events to a remote syslog server at given address using the
10
+	# specified facility and verbosity level. Multiple log options 
11
+	# are allowed.
12
+	#log 10.0.0.1 daemon info
13
+
14
+	# Specifiy the maximum number of allowed connections.
15
+	maxconn 32000
16
+
17
+	# Raise the ulimit for the maximum allowed number of open socket
18
+	# descriptors per process. This is usually at least twice the
19
+	# number of allowed connections (maxconn * 2 + nb_servers + 1) .
20
+	ulimit-n 65535
21
+
22
+	# Drop privileges (setuid, setgid), default is "root" on OpenWrt.
23
+	uid 0
24
+	gid 0
25
+
26
+	# Perform chroot into the specified directory.
27
+	#chroot /var/run/haproxy/
28
+
29
+	# Daemonize on startup
30
+	daemon
31
+
32
+	nosplice
33
+	# Enable debugging
34
+	#debug
35
+
36
+	# Spawn given number of processes and distribute load among them,
37
+	# used for multi-core environments or to circumvent per-process
38
+	# limits like number of open file descriptors. Default is 1.
39
+	#nbproc 2
40
+
41
+
42
+# Example HTTP proxy listener
43
+listen my_http_proxy
44
+
45
+	# Bind to port 81 and 444 on all interfaces (0.0.0.0)
46
+	bind :81,:444
47
+
48
+	# We're proxying HTTP here...
49
+	mode http
50
+
51
+	# Simple HTTP round robin over two servers using the specified
52
+	# source ip 192.168.1.1 .
53
+	balance roundrobin
54
+	server server01 192.168.1.10:80 source 192.168.1.1
55
+	server server02 192.168.1.20:80 source 192.168.1.1
56
+
57
+	# Serve an internal statistics page on /stats:
58
+	stats enable
59
+	stats uri /stats
60
+
61
+	# Enable HTTP basic auth for the statistics:
62
+	stats realm HA_Stats
63
+	stats auth username:password
64
+
65
+
66
+# Example SMTP proxy listener
67
+listen my_smtp_proxy
68
+
69
+	# Disable this instance without commenting out the section.
70
+	disabled
71
+
72
+	# Bind to port 26 and 588 on localhost
73
+	bind 127.0.0.1:26,127.0.0.1:588
74
+
75
+	# This is a TCP proxy
76
+	mode tcp
77
+
78
+	# Round robin load balancing over two servers on port 123 forcing
79
+	# the address 192.168.1.1 and port 25 as source.
80
+	balance roundrobin
81
+  #use next line for transparent proxy, so the servers can see the 
82
+  #original ip-address and remove source keyword in server definition
83
+  #source 0.0.0.0 usesrc clientip
84
+	server server01 192.168.1.10:123 source 192.168.1.1:25
85
+	server server02 192.168.1.20:123 source 192.168.1.1:25
86
+	
87
+
88
+# Special health check listener for integration with external load
89
+# balancers.
90
+listen local_health_check
91
+
92
+	# Listen on port 60000
93
+	bind :60000
94
+
95
+	# This is a health check
96
+	mode health
97
+
98
+	# Enable HTTP-style responses: "HTTP/1.0 200 OK"
99
+	# else just print "OK".
100
+	#option httpchk

+ 8
- 0
net/haproxy/files/haproxy.hotplug 查看文件

@@ -0,0 +1,8 @@
1
+#!/bin/sh
2
+
3
+if [ "$ACTION" = add ]; then
4
+
5
+	/etc/init.d/haproxy enabled && \
6
+		/etc/init.d/haproxy start
7
+fi
8
+

+ 23
- 0
net/haproxy/files/haproxy.init 查看文件

@@ -0,0 +1,23 @@
1
+#!/bin/sh /etc/rc.common
2
+# Copyright (C) 2009-2010 OpenWrt.org
3
+
4
+START=99
5
+STOP=80
6
+
7
+SERVICE_USE_PID=1
8
+
9
+HAPROXY_BIN="/usr/sbin/haproxy"
10
+HAPROXY_CONFIG="/etc/haproxy.cfg"
11
+HAPROXY_PID="/var/run/haproxy.pid"
12
+
13
+start() {
14
+	service_start $HAPROXY_BIN -q -D -f "$HAPROXY_CONFIG" -p "$HAPROXY_PID"
15
+}
16
+
17
+stop() {
18
+	service_stop $HAPROXY_BIN
19
+}
20
+
21
+reload() {
22
+	$HAPROXY_BIN -D -q -f $HAPROXY_CONFIG -p $HAPROXY_PID -sf $(cat $HAPROXY_PID)
23
+}

+ 506
- 0
net/haproxy/patches/001-haproxy-1.4.x-sendproxy.patch 查看文件

@@ -0,0 +1,506 @@
1
+From af2038557a14bf6e2915bed545e216a0f1a95fc5 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Cyril=20Bont=C3=A9?= <cyril.bonte@free.fr>
3
+Date: Mon, 15 Apr 2013 22:05:00 +0200
4
+Subject: [PATCH] Proxy Protocol based on haproxy 1.4.23
5
+
6
+---
7
+ doc/configuration.txt     |  26 ++++++-
8
+ include/common/standard.h |  25 ++++++-
9
+ include/proto/client.h    |   1 +
10
+ include/types/buffers.h   |  20 ++---
11
+ include/types/protocols.h |   1 +
12
+ src/cfgparse.c            |  15 +++-
13
+ src/client.c              | 186 ++++++++++++++++++++++++++++++++++++++++++++++
14
+ src/proto_http.c          |   4 +-
15
+ src/session.c             |   7 ++
16
+ src/standard.c            |   9 ++-
17
+ 10 files changed, 275 insertions(+), 19 deletions(-)
18
+
19
+Index: haproxy-1.4.25/doc/configuration.txt
20
+===================================================================
21
+--- haproxy-1.4.25.orig/doc/configuration.txt
22
++++ haproxy-1.4.25/doc/configuration.txt
23
+@@ -1343,6 +1343,7 @@ bind [<address>]:<port_range> [, ...] tr
24
+ bind [<address>]:<port_range> [, ...] id <id>
25
+ bind [<address>]:<port_range> [, ...] name <name>
26
+ bind [<address>]:<port_range> [, ...] defer-accept
27
++bind [<address>]:<port_range> [, ...] accept-proxy
28
+   Define one or several listening addresses and/or ports in a frontend.
29
+   May be used in sections :   defaults | frontend | listen | backend
30
+                                   no   |    yes   |   yes  |   no
31
+@@ -1423,6 +1424,19 @@ bind [<address>]:<port_range> [, ...] de
32
+                   with front firewalls which would see an established
33
+                   connection while the proxy will only see it in SYN_RECV.
34
+ 
35
++    accept-proxy  is an optional keyword which enforces use of the PROXY
36
++                  protocol over any connection accepted by this listener. The
37
++                  PROXY protocol dictates the layer 3/4 addresses of the
38
++                  incoming connection to be used everywhere an address is used,
39
++                  with the only exception of "tcp-request connection" rules
40
++                  which will only see the real connection address. Logs will
41
++                  reflect the addresses indicated in the protocol, unless it is
42
++                  violated, in which case the real address will still be used.
43
++                  This keyword combined with support from external components
44
++                  can be used as an efficient and reliable alternative to the
45
++                  X-Forwarded-For mechanism which is not always reliable and
46
++                  not even always usable.
47
++
48
+   It is possible to specify a list of address:port combinations delimited by
49
+   commas. The frontend will then listen on all of these addresses. There is no
50
+   fixed limit to the number of addresses and ports which can be listened on in
51
+@@ -1433,8 +1447,10 @@ bind [<address>]:<port_range> [, ...] de
52
+         listen http_proxy
53
+             bind :80,:443
54
+             bind 10.0.0.1:10080,10.0.0.1:10443
55
++            bind 127.0.0.1:8443 accept-proxy
56
+ 
57
+-  See also : "source".
58
++  See also : "source", "option forwardfor" and the PROXY protocol
59
++             documentation.
60
+ 
61
+ 
62
+ bind-process [ all | odd | even | <number 1-32> ] ...
63
+@@ -7257,7 +7273,9 @@ marked with a star ('*') after the field
64
+ 
65
+ Detailed fields description :
66
+   - "client_ip" is the IP address of the client which initiated the TCP
67
+-    connection to haproxy.
68
++    connection to haproxy. Note that when the connection is accepted on a
69
++    socket configured with "accept-proxy" and the PROXY protocol is correctly
70
++    used, then the logs will reflect the forwarded connection's information.
71
+ 
72
+   - "client_port" is the TCP port of the client which initiated the connection.
73
+ 
74
+@@ -7430,7 +7448,9 @@ with a star ('*') after the field name b
75
+ 
76
+ Detailed fields description :
77
+   - "client_ip" is the IP address of the client which initiated the TCP
78
+-    connection to haproxy.
79
++    connection to haproxy. Note that when the connection is accepted on a
80
++    socket configured with "accept-proxy" and the PROXY protocol is correctly
81
++    used, then the logs will reflect the forwarded connection's information.
82
+ 
83
+   - "client_port" is the TCP port of the client which initiated the connection.
84
+ 
85
+Index: haproxy-1.4.25/include/common/standard.h
86
+===================================================================
87
+--- haproxy-1.4.25.orig/include/common/standard.h
88
++++ haproxy-1.4.25/include/common/standard.h
89
+@@ -269,6 +269,28 @@ static inline unsigned int __strl2uic(co
90
+ 	return i;
91
+ }
92
+ 
93
++/* This function reads an unsigned integer from the string pointed to by <s>
94
++ * and returns it. The <s> pointer is adjusted to point to the first unread
95
++ * char. The function automatically stops at <end>.
96
++ */
97
++static inline unsigned int __read_uint(const char **s, const char *end)
98
++{
99
++	const char *ptr = *s;
100
++	unsigned int i = 0;
101
++	unsigned int j, k;
102
++
103
++	while (ptr < end) {
104
++		j = *ptr - '0';
105
++		k = i * 10;
106
++		if (j > 9)
107
++			break;
108
++		i = k + j;
109
++		ptr++;
110
++	}
111
++	*s = ptr;
112
++	return i;
113
++}
114
++
115
+ extern unsigned int str2ui(const char *s);
116
+ extern unsigned int str2uic(const char *s);
117
+ extern unsigned int strl2ui(const char *s, int len);
118
+@@ -276,9 +298,10 @@ extern unsigned int strl2uic(const char 
119
+ extern int strl2ic(const char *s, int len);
120
+ extern int strl2irc(const char *s, int len, int *ret);
121
+ extern int strl2llrc(const char *s, int len, long long *ret);
122
++extern unsigned int read_uint(const char **s, const char *end);
123
+ unsigned int inetaddr_host(const char *text);
124
+ unsigned int inetaddr_host_lim(const char *text, const char *stop);
125
+-unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **ret);
126
++unsigned int inetaddr_host_lim_ret(char *text, char *stop, char **ret);
127
+ 
128
+ static inline char *cut_crlf(char *s) {
129
+ 
130
+Index: haproxy-1.4.25/include/proto/client.h
131
+===================================================================
132
+--- haproxy-1.4.25.orig/include/proto/client.h
133
++++ haproxy-1.4.25/include/proto/client.h
134
+@@ -25,6 +25,7 @@
135
+ #include <common/config.h>
136
+ #include <types/session.h>
137
+ 
138
++int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit);
139
+ void get_frt_addr(struct session *s);
140
+ int event_accept(int fd);
141
+ 
142
+Index: haproxy-1.4.25/include/types/buffers.h
143
+===================================================================
144
+--- haproxy-1.4.25.orig/include/types/buffers.h
145
++++ haproxy-1.4.25/include/types/buffers.h
146
+@@ -135,16 +135,16 @@
147
+  * The field is blanked by buffer_init() and only by analysers themselves
148
+  * afterwards.
149
+  */
150
+-#define AN_REQ_INSPECT          0x00000001  /* inspect request contents */
151
+-#define AN_REQ_WAIT_HTTP        0x00000002  /* wait for an HTTP request */
152
+-#define AN_REQ_HTTP_PROCESS_FE  0x00000004  /* process the frontend's HTTP part */
153
+-#define AN_REQ_SWITCHING_RULES  0x00000008  /* apply the switching rules */
154
+-#define AN_REQ_HTTP_PROCESS_BE  0x00000010  /* process the backend's HTTP part */
155
+-#define AN_REQ_HTTP_INNER       0x00000020  /* inner processing of HTTP request */
156
+-#define AN_REQ_HTTP_TARPIT      0x00000040  /* wait for end of HTTP tarpit */
157
+-#define AN_REQ_HTTP_BODY        0x00000080  /* inspect HTTP request body */
158
+-#define AN_REQ_STICKING_RULES   0x00000100  /* table persistence matching */
159
+-/* unused: 0x200 */
160
++#define AN_REQ_DECODE_PROXY     0x00000001  /* take the proxied address from a 'PROXY' line */
161
++#define AN_REQ_INSPECT          0x00000002  /* inspect request contents */
162
++#define AN_REQ_WAIT_HTTP        0x00000004  /* wait for an HTTP request */
163
++#define AN_REQ_HTTP_PROCESS_FE  0x00000008  /* process the frontend's HTTP part */
164
++#define AN_REQ_SWITCHING_RULES  0x00000010  /* apply the switching rules */
165
++#define AN_REQ_HTTP_PROCESS_BE  0x00000020  /* process the backend's HTTP part */
166
++#define AN_REQ_HTTP_INNER       0x00000040  /* inner processing of HTTP request */
167
++#define AN_REQ_HTTP_TARPIT      0x00000080  /* wait for end of HTTP tarpit */
168
++#define AN_REQ_HTTP_BODY        0x00000100  /* inspect HTTP request body */
169
++#define AN_REQ_STICKING_RULES   0x00000200  /* table persistence matching */
170
+ #define AN_REQ_PRST_RDP_COOKIE  0x00000400  /* persistence on rdp cookie */
171
+ #define AN_REQ_HTTP_XFER_BODY   0x00000800  /* forward request body */
172
+ 
173
+Index: haproxy-1.4.25/include/types/protocols.h
174
+===================================================================
175
+--- haproxy-1.4.25.orig/include/types/protocols.h
176
++++ haproxy-1.4.25/include/types/protocols.h
177
+@@ -72,6 +72,7 @@
178
+ #define LI_O_FOREIGN	0x0002	/* permit listening on foreing addresses */
179
+ #define LI_O_NOQUICKACK	0x0004	/* disable quick ack of immediate data (linux) */
180
+ #define LI_O_DEF_ACCEPT	0x0008	/* wait up to 1 second for data before accepting */
181
++#define LI_O_ACC_PROXY  0x0010  /* find the proxied address in the first request line */
182
+ 
183
+ /* The listener will be directly referenced by the fdtab[] which holds its
184
+  * socket. The listener provides the protocol-specific accept() function to
185
+Index: haproxy-1.4.25/src/cfgparse.c
186
+===================================================================
187
+--- haproxy-1.4.25.orig/src/cfgparse.c
188
++++ haproxy-1.4.25/src/cfgparse.c
189
+@@ -1467,6 +1467,16 @@ int cfg_parse_listen(const char *file, i
190
+ #endif
191
+ 			}
192
+ 
193
++			if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
194
++				struct listener *l;
195
++
196
++				for (l = curproxy->listen; l != last_listen; l = l->next)
197
++					l->options |= LI_O_ACC_PROXY;
198
++
199
++				cur_arg ++;
200
++				continue;
201
++			}
202
++
203
+ 			if (!strcmp(args[cur_arg], "name")) {
204
+ 				struct listener *l;
205
+ 
206
+@@ -1519,7 +1529,7 @@ int cfg_parse_listen(const char *file, i
207
+ 				continue;
208
+ 			}
209
+ 
210
+-			Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
211
++			Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
212
+ 			      file, linenum, args[0]);
213
+ 			err_code |= ERR_ALERT | ERR_FATAL;
214
+ 			goto out;
215
+@@ -5743,6 +5753,9 @@ out_uri_auth_compat:
216
+ 			listener->handler = process_session;
217
+ 			listener->analysers |= curproxy->fe_req_ana;
218
+ 
219
++			if (listener->options & LI_O_ACC_PROXY)
220
++				listener->analysers |= AN_REQ_DECODE_PROXY;
221
++
222
+ 			/* smart accept mode is automatic in HTTP mode */
223
+ 			if ((curproxy->options2 & PR_O2_SMARTACC) ||
224
+ 			    (curproxy->mode == PR_MODE_HTTP &&
225
+Index: haproxy-1.4.25/src/client.c
226
+===================================================================
227
+--- haproxy-1.4.25.orig/src/client.c
228
++++ haproxy-1.4.25/src/client.c
229
+@@ -22,6 +22,7 @@
230
+ 
231
+ #include <common/compat.h>
232
+ #include <common/config.h>
233
++#include <common/debug.h>
234
+ #include <common/time.h>
235
+ 
236
+ #include <types/global.h>
237
+@@ -43,6 +44,191 @@
238
+ #include <proto/task.h>
239
+ 
240
+ 
241
++/* This analyser tries to fetch a line from the request buffer which looks like :
242
++ *
243
++ *   "PROXY" <SP> PROTO <SP> SRC3 <SP> DST3 <SP> SRC4 <SP> <DST4> "\r\n"
244
++ *
245
++ * There must be exactly one space between each field. Fields are :
246
++ *  - PROTO : layer 4 protocol, which must be "TCP4" or "TCP6".
247
++ *  - SRC3  : layer 3 (eg: IP) source address in standard text form
248
++ *  - DST3  : layer 3 (eg: IP) destination address in standard text form
249
++ *  - SRC4  : layer 4 (eg: TCP port) source address in standard text form
250
++ *  - DST4  : layer 4 (eg: TCP port) destination address in standard text form
251
++ *
252
++ * This line MUST be at the beginning of the buffer and MUST NOT wrap.
253
++ *
254
++ * Once the data is fetched, the values are set in the session's field and data
255
++ * are removed from the buffer. The function returns zero if it needs to wait
256
++ * for more data (max: timeout_client), or 1 if it has finished and removed itself.
257
++ */
258
++int frontend_decode_proxy_request(struct session *s, struct buffer *req, int an_bit)
259
++{
260
++	char *line = req->data;
261
++	char *end = req->data + req->l;
262
++	int len;
263
++
264
++	DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
265
++		now_ms, __FUNCTION__,
266
++		s,
267
++		req,
268
++		req->rex, req->wex,
269
++		req->flags,
270
++		req->l,
271
++		req->analysers);
272
++
273
++	if (req->flags & (BF_READ_ERROR|BF_READ_TIMEOUT))
274
++		goto fail;
275
++
276
++	len = MIN(req->l, 6);
277
++	if (!len)
278
++		goto missing;
279
++
280
++	/* Decode a possible proxy request, fail early if it does not match */
281
++	if (strncmp(line, "PROXY ", len) != 0)
282
++		goto fail;
283
++
284
++	line += 6;
285
++	if (req->l < 18) /* shortest possible line */
286
++		goto missing;
287
++
288
++	if (!memcmp(line, "TCP4 ", 5) != 0) {
289
++		u32 src3, dst3, sport, dport;
290
++
291
++		line += 5;
292
++
293
++		src3 = inetaddr_host_lim_ret(line, end, &line);
294
++		if (line == end)
295
++			goto missing;
296
++		if (*line++ != ' ')
297
++			goto fail;
298
++
299
++		dst3 = inetaddr_host_lim_ret(line, end, &line);
300
++		if (line == end)
301
++			goto missing;
302
++		if (*line++ != ' ')
303
++			goto fail;
304
++
305
++		sport = read_uint((const char **)&line, end);
306
++		if (line == end)
307
++			goto missing;
308
++		if (*line++ != ' ')
309
++			goto fail;
310
++
311
++		dport = read_uint((const char **)&line, end);
312
++		if (line > end - 2)
313
++			goto missing;
314
++		if (*line++ != '\r')
315
++			goto fail;
316
++		if (*line++ != '\n')
317
++			goto fail;
318
++
319
++		/* update the session's addresses and mark them set */
320
++		((struct sockaddr_in *)&s->cli_addr)->sin_family      = AF_INET;
321
++		((struct sockaddr_in *)&s->cli_addr)->sin_addr.s_addr = htonl(src3);
322
++		((struct sockaddr_in *)&s->cli_addr)->sin_port        = htons(sport);
323
++
324
++		((struct sockaddr_in *)&s->frt_addr)->sin_family      = AF_INET;
325
++		((struct sockaddr_in *)&s->frt_addr)->sin_addr.s_addr = htonl(dst3);
326
++		((struct sockaddr_in *)&s->frt_addr)->sin_port        = htons(dport);
327
++		s->flags |= SN_FRT_ADDR_SET;
328
++
329
++	}
330
++	else if (!memcmp(line, "TCP6 ", 5) != 0) {
331
++		u32 sport, dport;
332
++		char *src_s;
333
++		char *dst_s, *sport_s, *dport_s;
334
++		struct in6_addr src3, dst3;
335
++
336
++		line+=5;
337
++
338
++		src_s = line;
339
++		dst_s = sport_s = dport_s = NULL;
340
++		while (1) {
341
++			if (line > end - 2) {
342
++				goto missing;
343
++			}
344
++			else if (*line == '\r') {
345
++				*line = 0;
346
++				line++;
347
++				if (*line++ != '\n')
348
++					goto fail;
349
++				break;
350
++			}
351
++
352
++			if (*line == ' ') {
353
++				*line = 0;
354
++				if (!dst_s)
355
++					dst_s = line+1;
356
++				else if (!sport_s)
357
++					sport_s = line+1;
358
++				else if (!dport_s)
359
++					dport_s = line+1;
360
++			}
361
++			line++;
362
++		}
363
++
364
++		if (!dst_s || !sport_s || !dport_s)
365
++			goto fail;
366
++
367
++		sport = read_uint((const char **)&sport_s,dport_s-1);
368
++		if ( *sport_s != 0 )
369
++			goto fail;
370
++
371
++		dport = read_uint((const char **)&dport_s,line-2);
372
++		if ( *dport_s != 0 )
373
++			goto fail;
374
++
375
++		if (inet_pton(AF_INET6, src_s, (void *)&src3) != 1)
376
++			goto fail;
377
++
378
++		if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
379
++			goto fail;
380
++
381
++		/* update the session's addresses and mark them set */
382
++		((struct sockaddr_in6 *)&s->cli_addr)->sin6_family      = AF_INET6;
383
++		memcpy(&((struct sockaddr_in6 *)&s->cli_addr)->sin6_addr, &src3, sizeof(struct in6_addr));
384
++		((struct sockaddr_in6 *)&s->cli_addr)->sin6_port        = htons(sport);
385
++
386
++		((struct sockaddr_in6 *)&s->frt_addr)->sin6_family      = AF_INET6;
387
++		memcpy(&((struct sockaddr_in6 *)&s->frt_addr)->sin6_addr, &dst3, sizeof(struct in6_addr));
388
++		((struct sockaddr_in6 *)&s->frt_addr)->sin6_port        = htons(dport);
389
++		s->flags |= SN_FRT_ADDR_SET;
390
++	}
391
++	else {
392
++		goto fail;
393
++	}
394
++
395
++	/* remove the PROXY line from the request */
396
++	len = line - req->data;
397
++	buffer_replace2(req, req->data, line, NULL, 0);
398
++	req->total -= len; /* don't count the header line */
399
++
400
++	req->analysers &= ~an_bit;
401
++	return 1;
402
++
403
++ missing:
404
++	if (!(req->flags & (BF_SHUTR|BF_FULL))) {
405
++		buffer_dont_connect(s->req);
406
++		return 0;
407
++	}
408
++	/* missing data and buffer is either full or shutdown => fail */
409
++
410
++ fail:
411
++	buffer_abort(req);
412
++	buffer_abort(s->rep);
413
++	req->analysers = 0;
414
++
415
++	s->fe->counters.failed_req++;
416
++	if (s->listener->counters)
417
++		s->listener->counters->failed_req++;
418
++
419
++	if (!(s->flags & SN_ERR_MASK))
420
++		s->flags |= SN_ERR_PRXCOND;
421
++	if (!(s->flags & SN_FINST_MASK))
422
++		s->flags |= SN_FINST_R;
423
++	return 0;
424
++}
425
++
426
+ /* Retrieves the original destination address used by the client, and sets the
427
+  * SN_FRT_ADDR_SET flag.
428
+  */
429
+Index: haproxy-1.4.25/src/proto_http.c
430
+===================================================================
431
+--- haproxy-1.4.25.orig/src/proto_http.c
432
++++ haproxy-1.4.25/src/proto_http.c
433
+@@ -4209,7 +4209,8 @@ void http_end_txn_clean_session(struct s
434
+ 	if (s->rep->lr >= s->rep->data + s->rep->size)
435
+ 		s->rep->lr -= s->req->size;
436
+ 
437
+-	s->req->analysers |= s->fe->fe_req_ana;
438
++	s->req->analysers = s->fe->fe_req_ana;
439
++	s->req->analysers &= ~AN_REQ_DECODE_PROXY;
440
+ 	s->rep->analysers = 0;
441
+ 
442
+ 	http_silent_debug(__LINE__, s);
443
+@@ -7807,7 +7808,6 @@ void http_reset_txn(struct session *s)
444
+ 	http_init_txn(s);
445
+ 
446
+ 	s->be = s->fe;
447
+-	s->req->analysers = s->listener->analysers;
448
+ 	s->logs.logwait = s->fe->to_log;
449
+ 	s->srv = s->prev_srv = s->srv_conn = NULL;
450
+ 	/* re-init store persistence */
451
+Index: haproxy-1.4.25/src/session.c
452
+===================================================================
453
+--- haproxy-1.4.25.orig/src/session.c
454
++++ haproxy-1.4.25/src/session.c
455
+@@ -34,6 +34,7 @@
456
+ #include <proto/proxy.h>
457
+ #include <proto/queue.h>
458
+ #include <proto/server.h>
459
++#include <proto/client.h>
460
+ #include <proto/stick_table.h>
461
+ #include <proto/stream_interface.h>
462
+ #include <proto/stream_sock.h>
463
+@@ -1083,6 +1084,12 @@ resync_stream_interface:
464
+ 			while (ana_list && max_loops--) {
465
+ 				/* Warning! ensure that analysers are always placed in ascending order! */
466
+ 
467
++				if (ana_list & AN_REQ_DECODE_PROXY) {
468
++					if (!frontend_decode_proxy_request(s, s->req, AN_REQ_DECODE_PROXY))
469
++						break;
470
++					UPDATE_ANALYSERS(s->req->analysers, ana_list, ana_back, AN_REQ_DECODE_PROXY);
471
++				}
472
++
473
+ 				if (ana_list & AN_REQ_INSPECT) {
474
+ 					if (!tcp_inspect_request(s, s->req, AN_REQ_INSPECT))
475
+ 						break;
476
+Index: haproxy-1.4.25/src/standard.c
477
+===================================================================
478
+--- haproxy-1.4.25.orig/src/standard.c
479
++++ haproxy-1.4.25/src/standard.c
480
+@@ -569,6 +569,11 @@ unsigned int strl2uic(const char *s, int
481
+ 	return __strl2uic(s, len);
482
+ }
483
+ 
484
++unsigned int read_uint(const char **s, const char *end)
485
++{
486
++	return __read_uint(s, end);
487
++}
488
++
489
+ /* This one is 7 times faster than strtol() on athlon with checks.
490
+  * It returns the value of the number composed of all valid digits read,
491
+  * and can process negative numbers too.
492
+@@ -993,12 +998,12 @@ unsigned int inetaddr_host_lim(const cha
493
+  * Idem except the pointer to first unparsed byte is returned into <ret> which
494
+  * must not be NULL.
495
+  */
496
+-unsigned int inetaddr_host_lim_ret(const char *text, char *stop, const char **ret)
497
++unsigned int inetaddr_host_lim_ret(char *text, char *stop, char **ret)
498
+ {
499
+ 	const unsigned int ascii_zero = ('0' << 24) | ('0' << 16) | ('0' << 8) | '0';
500
+ 	register unsigned int dig100, dig10, dig1;
501
+ 	int s;
502
+-	const char *p, *d;
503
++	char *p, *d;
504
+ 
505
+ 	dig1 = dig10 = dig100 = ascii_zero;
506
+ 	s = 24;