~ubuntu-branches/ubuntu/vivid/haproxy/vivid

« back to all changes in this revision

Viewing changes to src/connection.c

  • Committer: Package Import Robot
  • Author(s): Apollon Oikonomopoulos
  • Date: 2014-06-20 11:05:17 UTC
  • mfrom: (1.1.15) (15.1.12 experimental)
  • Revision ID: package-import@ubuntu.com-20140620110517-u6q5p9kyy2f3ozw9
Tags: 1.5.0-1
* New upstream stable series. Notable changes since the 1.4 series:
  + Native SSL support on both sides with SNI/NPN/ALPN and OCSP stapling.
  + IPv6 and UNIX sockets are supported everywhere
  + End-to-end HTTP keep-alive for better support of NTLM and improved
    efficiency in static farms
  + HTTP/1.1 response compression (deflate, gzip) to save bandwidth
  + PROXY protocol versions 1 and 2 on both sides
  + Data sampling on everything in request or response, including payload
  + ACLs can use any matching method with any input sample
  + Maps and dynamic ACLs updatable from the CLI
  + Stick-tables support counters to track activity on any input sample
  + Custom format for logs, unique-id, header rewriting, and redirects
  + Improved health checks (SSL, scripted TCP, check agent, ...)
  + Much more scalable configuration supports hundreds of thousands of
    backends and certificates without sweating

* Upload to unstable, merge all 1.5 work from experimental. Most important
  packaging changes since 1.4.25-1 include:
  + systemd support.
  + A more sane default config file.
  + Zero-downtime upgrades between 1.5 releases by gracefully reloading
    HAProxy during upgrades.
  + HTML documentation shipped in the haproxy-doc package.
  + kqueue support for kfreebsd.

* Packaging changes since 1.5~dev26-2:
  + Drop patches merged upstream:
    o Fix-reference-location-in-manpage.patch
    o 0001-BUILD-stats-workaround-stupid-and-bogus-Werror-forma.patch
  + d/watch: look for stable 1.5 releases
  + systemd: respect CONFIG and EXTRAOPTS when specified in
    /etc/default/haproxy.
  + initscript: test the configuration before start or reload.
  + initscript: remove the ENABLED flag and logic.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Connection management functions
 
3
 *
 
4
 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 */
 
12
 
 
13
#include <errno.h>
 
14
 
 
15
#include <common/compat.h>
 
16
#include <common/config.h>
 
17
 
 
18
#include <proto/connection.h>
 
19
#include <proto/fd.h>
 
20
#include <proto/frontend.h>
 
21
#include <proto/proto_tcp.h>
 
22
#include <proto/session.h>
 
23
#include <proto/stream_interface.h>
 
24
 
 
25
#ifdef USE_OPENSSL
 
26
#include <proto/ssl_sock.h>
 
27
#endif
 
28
 
 
29
struct pool_head *pool2_connection;
 
30
 
 
31
/* perform minimal intializations, report 0 in case of error, 1 if OK. */
 
32
int init_connection()
 
33
{
 
34
        pool2_connection = create_pool("connection", sizeof (struct connection), MEM_F_SHARED);
 
35
        return pool2_connection != NULL;
 
36
}
 
37
 
 
38
/* I/O callback for fd-based connections. It calls the read/write handlers
 
39
 * provided by the connection's sock_ops, which must be valid. It returns 0.
 
40
 */
 
41
int conn_fd_handler(int fd)
 
42
{
 
43
        struct connection *conn = fdtab[fd].owner;
 
44
        unsigned int flags;
 
45
 
 
46
        if (unlikely(!conn))
 
47
                return 0;
 
48
 
 
49
        conn_refresh_polling_flags(conn);
 
50
        flags = conn->flags & ~CO_FL_ERROR; /* ensure to call the wake handler upon error */
 
51
 
 
52
 process_handshake:
 
53
        /* The handshake callbacks are called in sequence. If either of them is
 
54
         * missing something, it must enable the required polling at the socket
 
55
         * layer of the connection. Polling state is not guaranteed when entering
 
56
         * these handlers, so any handshake handler which does not complete its
 
57
         * work must explicitly disable events it's not interested in. Error
 
58
         * handling is also performed here in order to reduce the number of tests
 
59
         * around.
 
60
         */
 
61
        while (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR))) {
 
62
                if (unlikely(conn->flags & CO_FL_ERROR))
 
63
                        goto leave;
 
64
 
 
65
                if (conn->flags & CO_FL_ACCEPT_PROXY)
 
66
                        if (!conn_recv_proxy(conn, CO_FL_ACCEPT_PROXY))
 
67
                                goto leave;
 
68
 
 
69
                if (conn->flags & CO_FL_SEND_PROXY)
 
70
                        if (!conn_si_send_proxy(conn, CO_FL_SEND_PROXY))
 
71
                                goto leave;
 
72
#ifdef USE_OPENSSL
 
73
                if (conn->flags & CO_FL_SSL_WAIT_HS)
 
74
                        if (!ssl_sock_handshake(conn, CO_FL_SSL_WAIT_HS))
 
75
                                goto leave;
 
76
#endif
 
77
        }
 
78
 
 
79
        /* Once we're purely in the data phase, we disable handshake polling */
 
80
        if (!(conn->flags & CO_FL_POLL_SOCK))
 
81
                __conn_sock_stop_both(conn);
 
82
 
 
83
        /* The data layer might not be ready yet (eg: when using embryonic
 
84
         * sessions). If we're about to move data, we must initialize it first.
 
85
         * The function may fail and cause the connection to be destroyed, thus
 
86
         * we must not use it anymore and should immediately leave instead.
 
87
         */
 
88
        if ((conn->flags & CO_FL_INIT_DATA) && conn->data->init(conn) < 0)
 
89
                return 0;
 
90
 
 
91
        /* The data transfer starts here and stops on error and handshakes. Note
 
92
         * that we must absolutely test conn->xprt at each step in case it suddenly
 
93
         * changes due to a quick unexpected close().
 
94
         */
 
95
        if (conn->xprt && fd_recv_ready(fd) &&
 
96
            ((conn->flags & (CO_FL_DATA_RD_ENA|CO_FL_WAIT_ROOM|CO_FL_ERROR|CO_FL_HANDSHAKE)) == CO_FL_DATA_RD_ENA)) {
 
97
                /* force detection of a flag change : it's impossible to have both
 
98
                 * CONNECTED and WAIT_CONN so we're certain to trigger a change.
 
99
                 */
 
100
                flags = CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED;
 
101
                conn->data->recv(conn);
 
102
        }
 
103
 
 
104
        if (conn->xprt && fd_send_ready(fd) &&
 
105
            ((conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_WAIT_DATA|CO_FL_ERROR|CO_FL_HANDSHAKE)) == CO_FL_DATA_WR_ENA)) {
 
106
                /* force detection of a flag change : it's impossible to have both
 
107
                 * CONNECTED and WAIT_CONN so we're certain to trigger a change.
 
108
                 */
 
109
                flags = CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED;
 
110
                conn->data->send(conn);
 
111
        }
 
112
 
 
113
        /* It may happen during the data phase that a handshake is
 
114
         * enabled again (eg: SSL)
 
115
         */
 
116
        if (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR)))
 
117
                goto process_handshake;
 
118
 
 
119
        if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN)) {
 
120
                /* still waiting for a connection to establish and nothing was
 
121
                 * attempted yet to probe the connection. Then let's retry the
 
122
                 * connect().
 
123
                 */
 
124
                if (!tcp_connect_probe(conn))
 
125
                        goto leave;
 
126
        }
 
127
 
 
128
 leave:
 
129
        /* The wake callback may be used to process a critical error and abort the
 
130
         * connection. If so, we don't want to go further as the connection will
 
131
         * have been released and the FD destroyed.
 
132
         */
 
133
        if ((conn->flags & CO_FL_WAKE_DATA) &&
 
134
            ((conn->flags ^ flags) & CO_FL_CONN_STATE) &&
 
135
            conn->data->wake(conn) < 0)
 
136
                return 0;
 
137
 
 
138
        /* Last check, verify if the connection just established */
 
139
        if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
 
140
                conn->flags |= CO_FL_CONNECTED;
 
141
 
 
142
        /* remove the events before leaving */
 
143
        fdtab[fd].ev &= FD_POLL_STICKY;
 
144
 
 
145
        /* commit polling changes */
 
146
        conn_cond_update_polling(conn);
 
147
        return 0;
 
148
}
 
149
 
 
150
/* Update polling on connection <c>'s file descriptor depending on its current
 
151
 * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
 
152
 * in CO_FL_WAIT_*, and the data layer expectations indicated by CO_FL_DATA_*.
 
153
 * The connection flags are updated with the new flags at the end of the
 
154
 * operation. Polling is totally disabled if an error was reported.
 
155
 */
 
156
void conn_update_data_polling(struct connection *c)
 
157
{
 
158
        unsigned int f = c->flags;
 
159
 
 
160
        if (!conn_ctrl_ready(c))
 
161
                return;
 
162
 
 
163
        /* update read status if needed */
 
164
        if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_DATA_RD_ENA)) == CO_FL_DATA_RD_ENA)) {
 
165
                fd_want_recv(c->t.sock.fd);
 
166
                f |= CO_FL_CURR_RD_ENA;
 
167
        }
 
168
        else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_DATA_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
 
169
                fd_stop_recv(c->t.sock.fd);
 
170
                f &= ~CO_FL_CURR_RD_ENA;
 
171
        }
 
172
 
 
173
        /* update write status if needed */
 
174
        if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_DATA_WR_ENA)) == CO_FL_DATA_WR_ENA)) {
 
175
                fd_want_send(c->t.sock.fd);
 
176
                f |= CO_FL_CURR_WR_ENA;
 
177
        }
 
178
        else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_DATA_WR_ENA)) == CO_FL_CURR_WR_ENA)) {
 
179
                fd_stop_send(c->t.sock.fd);
 
180
                f &= ~CO_FL_CURR_WR_ENA;
 
181
        }
 
182
        c->flags = f;
 
183
}
 
184
 
 
185
/* Update polling on connection <c>'s file descriptor depending on its current
 
186
 * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
 
187
 * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
 
188
 * The connection flags are updated with the new flags at the end of the
 
189
 * operation. Polling is totally disabled if an error was reported.
 
190
 */
 
191
void conn_update_sock_polling(struct connection *c)
 
192
{
 
193
        unsigned int f = c->flags;
 
194
 
 
195
        if (!conn_ctrl_ready(c))
 
196
                return;
 
197
 
 
198
        /* update read status if needed */
 
199
        if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_SOCK_RD_ENA)) {
 
200
                fd_want_recv(c->t.sock.fd);
 
201
                f |= CO_FL_CURR_RD_ENA;
 
202
        }
 
203
        else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
 
204
                fd_stop_recv(c->t.sock.fd);
 
205
                f &= ~CO_FL_CURR_RD_ENA;
 
206
        }
 
207
 
 
208
        /* update write status if needed */
 
209
        if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_SOCK_WR_ENA)) {
 
210
                fd_want_send(c->t.sock.fd);
 
211
                f |= CO_FL_CURR_WR_ENA;
 
212
        }
 
213
        else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_CURR_WR_ENA)) {
 
214
                fd_stop_send(c->t.sock.fd);
 
215
                f &= ~CO_FL_CURR_WR_ENA;
 
216
        }
 
217
        c->flags = f;
 
218
}
 
219
 
 
220
/* This handshake handler waits a PROXY protocol header at the beginning of the
 
221
 * raw data stream. The header looks like this :
 
222
 *
 
223
 *   "PROXY" <SP> PROTO <SP> SRC3 <SP> DST3 <SP> SRC4 <SP> <DST4> "\r\n"
 
224
 *
 
225
 * There must be exactly one space between each field. Fields are :
 
226
 *  - PROTO : layer 4 protocol, which must be "TCP4" or "TCP6".
 
227
 *  - SRC3  : layer 3 (eg: IP) source address in standard text form
 
228
 *  - DST3  : layer 3 (eg: IP) destination address in standard text form
 
229
 *  - SRC4  : layer 4 (eg: TCP port) source address in standard text form
 
230
 *  - DST4  : layer 4 (eg: TCP port) destination address in standard text form
 
231
 *
 
232
 * This line MUST be at the beginning of the buffer and MUST NOT wrap.
 
233
 *
 
234
 * The header line is small and in all cases smaller than the smallest normal
 
235
 * TCP MSS. So it MUST always be delivered as one segment, which ensures we
 
236
 * can safely use MSG_PEEK and avoid buffering.
 
237
 *
 
238
 * Once the data is fetched, the values are set in the connection's address
 
239
 * fields, and data are removed from the socket's buffer. The function returns
 
240
 * zero if it needs to wait for more data or if it fails, or 1 if it completed
 
241
 * and removed itself.
 
242
 */
 
243
int conn_recv_proxy(struct connection *conn, int flag)
 
244
{
 
245
        char *line, *end;
 
246
        struct proxy_hdr_v2 *hdr_v2;
 
247
        const char v2sig[] = PP2_SIGNATURE;
 
248
 
 
249
        /* we might have been called just after an asynchronous shutr */
 
250
        if (conn->flags & CO_FL_SOCK_RD_SH)
 
251
                goto fail;
 
252
 
 
253
        if (!conn_ctrl_ready(conn))
 
254
                goto fail;
 
255
 
 
256
        if (!fd_recv_ready(conn->t.sock.fd))
 
257
                return 0;
 
258
 
 
259
        do {
 
260
                trash.len = recv(conn->t.sock.fd, trash.str, trash.size, MSG_PEEK);
 
261
                if (trash.len < 0) {
 
262
                        if (errno == EINTR)
 
263
                                continue;
 
264
                        if (errno == EAGAIN) {
 
265
                                fd_cant_recv(conn->t.sock.fd);
 
266
                                return 0;
 
267
                        }
 
268
                        goto recv_abort;
 
269
                }
 
270
        } while (0);
 
271
 
 
272
        if (!trash.len) {
 
273
                /* client shutdown */
 
274
                conn->err_code = CO_ER_PRX_EMPTY;
 
275
                goto fail;
 
276
        }
 
277
 
 
278
        if (trash.len < 6)
 
279
                goto missing;
 
280
 
 
281
        line = trash.str;
 
282
        end = trash.str + trash.len;
 
283
 
 
284
        /* Decode a possible proxy request, fail early if it does not match */
 
285
        if (strncmp(line, "PROXY ", 6) != 0)
 
286
                goto not_v1;
 
287
 
 
288
        line += 6;
 
289
        if (trash.len < 9) /* shortest possible line */
 
290
                goto missing;
 
291
 
 
292
        if (!memcmp(line, "TCP4 ", 5) != 0) {
 
293
                u32 src3, dst3, sport, dport;
 
294
 
 
295
                line += 5;
 
296
 
 
297
                src3 = inetaddr_host_lim_ret(line, end, &line);
 
298
                if (line == end)
 
299
                        goto missing;
 
300
                if (*line++ != ' ')
 
301
                        goto bad_header;
 
302
 
 
303
                dst3 = inetaddr_host_lim_ret(line, end, &line);
 
304
                if (line == end)
 
305
                        goto missing;
 
306
                if (*line++ != ' ')
 
307
                        goto bad_header;
 
308
 
 
309
                sport = read_uint((const char **)&line, end);
 
310
                if (line == end)
 
311
                        goto missing;
 
312
                if (*line++ != ' ')
 
313
                        goto bad_header;
 
314
 
 
315
                dport = read_uint((const char **)&line, end);
 
316
                if (line > end - 2)
 
317
                        goto missing;
 
318
                if (*line++ != '\r')
 
319
                        goto bad_header;
 
320
                if (*line++ != '\n')
 
321
                        goto bad_header;
 
322
 
 
323
                /* update the session's addresses and mark them set */
 
324
                ((struct sockaddr_in *)&conn->addr.from)->sin_family      = AF_INET;
 
325
                ((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr = htonl(src3);
 
326
                ((struct sockaddr_in *)&conn->addr.from)->sin_port        = htons(sport);
 
327
 
 
328
                ((struct sockaddr_in *)&conn->addr.to)->sin_family        = AF_INET;
 
329
                ((struct sockaddr_in *)&conn->addr.to)->sin_addr.s_addr   = htonl(dst3);
 
330
                ((struct sockaddr_in *)&conn->addr.to)->sin_port          = htons(dport);
 
331
                conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 
332
        }
 
333
        else if (!memcmp(line, "TCP6 ", 5) != 0) {
 
334
                u32 sport, dport;
 
335
                char *src_s;
 
336
                char *dst_s, *sport_s, *dport_s;
 
337
                struct in6_addr src3, dst3;
 
338
 
 
339
                line += 5;
 
340
 
 
341
                src_s = line;
 
342
                dst_s = sport_s = dport_s = NULL;
 
343
                while (1) {
 
344
                        if (line > end - 2) {
 
345
                                goto missing;
 
346
                        }
 
347
                        else if (*line == '\r') {
 
348
                                *line = 0;
 
349
                                line++;
 
350
                                if (*line++ != '\n')
 
351
                                        goto bad_header;
 
352
                                break;
 
353
                        }
 
354
 
 
355
                        if (*line == ' ') {
 
356
                                *line = 0;
 
357
                                if (!dst_s)
 
358
                                        dst_s = line + 1;
 
359
                                else if (!sport_s)
 
360
                                        sport_s = line + 1;
 
361
                                else if (!dport_s)
 
362
                                        dport_s = line + 1;
 
363
                        }
 
364
                        line++;
 
365
                }
 
366
 
 
367
                if (!dst_s || !sport_s || !dport_s)
 
368
                        goto bad_header;
 
369
 
 
370
                sport = read_uint((const char **)&sport_s,dport_s - 1);
 
371
                if (*sport_s != 0)
 
372
                        goto bad_header;
 
373
 
 
374
                dport = read_uint((const char **)&dport_s,line - 2);
 
375
                if (*dport_s != 0)
 
376
                        goto bad_header;
 
377
 
 
378
                if (inet_pton(AF_INET6, src_s, (void *)&src3) != 1)
 
379
                        goto bad_header;
 
380
 
 
381
                if (inet_pton(AF_INET6, dst_s, (void *)&dst3) != 1)
 
382
                        goto bad_header;
 
383
 
 
384
                /* update the session's addresses and mark them set */
 
385
                ((struct sockaddr_in6 *)&conn->addr.from)->sin6_family      = AF_INET6;
 
386
                memcpy(&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr, &src3, sizeof(struct in6_addr));
 
387
                ((struct sockaddr_in6 *)&conn->addr.from)->sin6_port        = htons(sport);
 
388
 
 
389
                ((struct sockaddr_in6 *)&conn->addr.to)->sin6_family        = AF_INET6;
 
390
                memcpy(&((struct sockaddr_in6 *)&conn->addr.to)->sin6_addr, &dst3, sizeof(struct in6_addr));
 
391
                ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port          = htons(dport);
 
392
                conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 
393
        }
 
394
        else if (memcmp(line, "UNKNOWN\r\n", 9) == 0) {
 
395
                /* This can be a UNIX socket forwarded by an haproxy upstream */
 
396
                line += 9;
 
397
        }
 
398
        else {
 
399
                /* The protocol does not match something known (TCP4/TCP6/UNKNOWN) */
 
400
                conn->err_code = CO_ER_PRX_BAD_PROTO;
 
401
                goto fail;
 
402
        }
 
403
 
 
404
        trash.len = line - trash.str;
 
405
        goto eat_header;
 
406
 
 
407
 not_v1:
 
408
        /* try PPv2 */
 
409
        if (trash.len < PP2_HEADER_LEN)
 
410
                goto missing;
 
411
 
 
412
        hdr_v2 = (struct proxy_hdr_v2 *)trash.str;
 
413
 
 
414
        if (memcmp(hdr_v2->sig, v2sig, PP2_SIGNATURE_LEN) != 0 ||
 
415
            (hdr_v2->ver_cmd & PP2_VERSION_MASK) != PP2_VERSION) {
 
416
                conn->err_code = CO_ER_PRX_NOT_HDR;
 
417
                goto fail;
 
418
        }
 
419
 
 
420
        if (trash.len < PP2_HEADER_LEN + ntohs(hdr_v2->len))
 
421
                goto missing;
 
422
 
 
423
        switch (hdr_v2->ver_cmd & PP2_CMD_MASK) {
 
424
        case 0x01: /* PROXY command */
 
425
                switch (hdr_v2->fam) {
 
426
                case 0x11:  /* TCPv4 */
 
427
                        ((struct sockaddr_in *)&conn->addr.from)->sin_family = AF_INET;
 
428
                        ((struct sockaddr_in *)&conn->addr.from)->sin_addr.s_addr = hdr_v2->addr.ip4.src_addr;
 
429
                        ((struct sockaddr_in *)&conn->addr.from)->sin_port = hdr_v2->addr.ip4.src_port;
 
430
                        ((struct sockaddr_in *)&conn->addr.to)->sin_family = AF_INET;
 
431
                        ((struct sockaddr_in *)&conn->addr.to)->sin_addr.s_addr = hdr_v2->addr.ip4.dst_addr;
 
432
                        ((struct sockaddr_in *)&conn->addr.to)->sin_port = hdr_v2->addr.ip4.dst_port;
 
433
                        conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 
434
                        break;
 
435
                case 0x21:  /* TCPv6 */
 
436
                        ((struct sockaddr_in6 *)&conn->addr.from)->sin6_family = AF_INET6;
 
437
                        memcpy(&((struct sockaddr_in6 *)&conn->addr.from)->sin6_addr, hdr_v2->addr.ip6.src_addr, 16);
 
438
                        ((struct sockaddr_in6 *)&conn->addr.from)->sin6_port = hdr_v2->addr.ip6.src_port;
 
439
                        ((struct sockaddr_in6 *)&conn->addr.to)->sin6_family = AF_INET6;
 
440
                        memcpy(&((struct sockaddr_in6 *)&conn->addr.to)->sin6_addr, hdr_v2->addr.ip6.dst_addr, 16);
 
441
                        ((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = hdr_v2->addr.ip6.dst_port;
 
442
                        conn->flags |= CO_FL_ADDR_FROM_SET | CO_FL_ADDR_TO_SET;
 
443
                        break;
 
444
                }
 
445
                /* unsupported protocol, keep local connection address */
 
446
                break;
 
447
        case 0x00: /* LOCAL command */
 
448
                /* keep local connection address for LOCAL */
 
449
                break;
 
450
        default:
 
451
                goto bad_header; /* not a supported command */
 
452
        }
 
453
 
 
454
        trash.len = PP2_HEADER_LEN + ntohs(hdr_v2->len);
 
455
        goto eat_header;
 
456
 
 
457
 eat_header:
 
458
        /* remove the PROXY line from the request. For this we re-read the
 
459
         * exact line at once. If we don't get the exact same result, we
 
460
         * fail.
 
461
         */
 
462
        do {
 
463
                int len2 = recv(conn->t.sock.fd, trash.str, trash.len, 0);
 
464
                if (len2 < 0 && errno == EINTR)
 
465
                        continue;
 
466
                if (len2 != trash.len)
 
467
                        goto recv_abort;
 
468
        } while (0);
 
469
 
 
470
        conn->flags &= ~flag;
 
471
        return 1;
 
472
 
 
473
 missing:
 
474
        /* Missing data. Since we're using MSG_PEEK, we can only poll again if
 
475
         * we have not read anything. Otherwise we need to fail because we won't
 
476
         * be able to poll anymore.
 
477
         */
 
478
        conn->err_code = CO_ER_PRX_TRUNCATED;
 
479
        goto fail;
 
480
 
 
481
 bad_header:
 
482
        /* This is not a valid proxy protocol header */
 
483
        conn->err_code = CO_ER_PRX_BAD_HDR;
 
484
        goto fail;
 
485
 
 
486
 recv_abort:
 
487
        conn->err_code = CO_ER_PRX_ABORT;
 
488
        conn->flags |= CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
 
489
        goto fail;
 
490
 
 
491
 fail:
 
492
        __conn_sock_stop_both(conn);
 
493
        conn->flags |= CO_FL_ERROR;
 
494
        return 0;
 
495
}
 
496
 
 
497
int make_proxy_line(char *buf, int buf_len, struct server *srv, struct connection *remote)
 
498
{
 
499
        int ret = 0;
 
500
 
 
501
        if (srv && (srv->pp_opts & SRV_PP_V2)) {
 
502
                ret = make_proxy_line_v2(buf, buf_len, srv, remote);
 
503
        }
 
504
        else {
 
505
                if (remote)
 
506
                        ret = make_proxy_line_v1(buf, buf_len, &remote->addr.from, &remote->addr.to);
 
507
                else
 
508
                        ret = make_proxy_line_v1(buf, buf_len, NULL, NULL);
 
509
        }
 
510
 
 
511
        return ret;
 
512
}
 
513
 
 
514
/* Makes a PROXY protocol line from the two addresses. The output is sent to
 
515
 * buffer <buf> for a maximum size of <buf_len> (including the trailing zero).
 
516
 * It returns the number of bytes composing this line (including the trailing
 
517
 * LF), or zero in case of failure (eg: not enough space). It supports TCP4,
 
518
 * TCP6 and "UNKNOWN" formats. If any of <src> or <dst> is null, UNKNOWN is
 
519
 * emitted as well.
 
520
 */
 
521
int make_proxy_line_v1(char *buf, int buf_len, struct sockaddr_storage *src, struct sockaddr_storage *dst)
 
522
{
 
523
        int ret = 0;
 
524
 
 
525
        if (src && dst && src->ss_family == dst->ss_family && src->ss_family == AF_INET) {
 
526
                ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP4 ");
 
527
                if (ret >= buf_len)
 
528
                        return 0;
 
529
 
 
530
                /* IPv4 src */
 
531
                if (!inet_ntop(src->ss_family, &((struct sockaddr_in *)src)->sin_addr, buf + ret, buf_len - ret))
 
532
                        return 0;
 
533
 
 
534
                ret += strlen(buf + ret);
 
535
                if (ret >= buf_len)
 
536
                        return 0;
 
537
 
 
538
                buf[ret++] = ' ';
 
539
 
 
540
                /* IPv4 dst */
 
541
                if (!inet_ntop(dst->ss_family, &((struct sockaddr_in *)dst)->sin_addr, buf + ret, buf_len - ret))
 
542
                        return 0;
 
543
 
 
544
                ret += strlen(buf + ret);
 
545
                if (ret >= buf_len)
 
546
                        return 0;
 
547
 
 
548
                /* source and destination ports */
 
549
                ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
 
550
                                ntohs(((struct sockaddr_in *)src)->sin_port),
 
551
                                ntohs(((struct sockaddr_in *)dst)->sin_port));
 
552
                if (ret >= buf_len)
 
553
                        return 0;
 
554
        }
 
555
        else if (src && dst && src->ss_family == dst->ss_family && src->ss_family == AF_INET6) {
 
556
                ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP6 ");
 
557
                if (ret >= buf_len)
 
558
                        return 0;
 
559
 
 
560
                /* IPv6 src */
 
561
                if (!inet_ntop(src->ss_family, &((struct sockaddr_in6 *)src)->sin6_addr, buf + ret, buf_len - ret))
 
562
                        return 0;
 
563
 
 
564
                ret += strlen(buf + ret);
 
565
                if (ret >= buf_len)
 
566
                        return 0;
 
567
 
 
568
                buf[ret++] = ' ';
 
569
 
 
570
                /* IPv6 dst */
 
571
                if (!inet_ntop(dst->ss_family, &((struct sockaddr_in6 *)dst)->sin6_addr, buf + ret, buf_len - ret))
 
572
                        return 0;
 
573
 
 
574
                ret += strlen(buf + ret);
 
575
                if (ret >= buf_len)
 
576
                        return 0;
 
577
 
 
578
                /* source and destination ports */
 
579
                ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
 
580
                                ntohs(((struct sockaddr_in6 *)src)->sin6_port),
 
581
                                ntohs(((struct sockaddr_in6 *)dst)->sin6_port));
 
582
                if (ret >= buf_len)
 
583
                        return 0;
 
584
        }
 
585
        else {
 
586
                /* unknown family combination */
 
587
                ret = snprintf(buf, buf_len, "PROXY UNKNOWN\r\n");
 
588
                if (ret >= buf_len)
 
589
                        return 0;
 
590
        }
 
591
        return ret;
 
592
}
 
593
 
 
594
#ifdef USE_OPENSSL
 
595
static int make_tlv(char *dest, int dest_len, char type, uint16_t length, char *value)
 
596
{
 
597
        struct tlv *tlv;
 
598
 
 
599
        if (!dest || (length + sizeof(*tlv) > dest_len))
 
600
                return 0;
 
601
 
 
602
        tlv = (struct tlv *)dest;
 
603
 
 
604
        tlv->type = type;
 
605
        tlv->length_hi = length >> 8;
 
606
        tlv->length_lo = length & 0x00ff;
 
607
        memcpy(tlv->value, value, length);
 
608
        return length + sizeof(*tlv);
 
609
}
 
610
#endif
 
611
 
 
612
int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connection *remote)
 
613
{
 
614
        const char pp2_signature[] = PP2_SIGNATURE;
 
615
        int ret = 0;
 
616
        struct proxy_hdr_v2 *hdr = (struct proxy_hdr_v2 *)buf;
 
617
        struct sockaddr_storage null_addr = {0};
 
618
        struct sockaddr_storage *src = &null_addr;
 
619
        struct sockaddr_storage *dst = &null_addr;
 
620
#ifdef USE_OPENSSL
 
621
        int tlv_len = 0;
 
622
        char *value = NULL;
 
623
        struct tlv_ssl *tlv;
 
624
        int ssl_tlv_len = 0;
 
625
#endif
 
626
 
 
627
        if (buf_len < PP2_HEADER_LEN)
 
628
                return 0;
 
629
        memcpy(hdr->sig, pp2_signature, PP2_SIGNATURE_LEN);
 
630
 
 
631
        if (remote) {
 
632
                src = &remote->addr.from;
 
633
                dst = &remote->addr.to;
 
634
        }
 
635
        if (src && dst && src->ss_family == dst->ss_family && src->ss_family == AF_INET) {
 
636
                if (buf_len < PP2_HDR_LEN_INET)
 
637
                        return 0;
 
638
                hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
 
639
                hdr->fam = PP2_FAM_INET | PP2_TRANS_STREAM;
 
640
                hdr->addr.ip4.src_addr = ((struct sockaddr_in *)src)->sin_addr.s_addr;
 
641
                hdr->addr.ip4.dst_addr = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
 
642
                hdr->addr.ip4.src_port = ((struct sockaddr_in *)src)->sin_port;
 
643
                hdr->addr.ip4.dst_port = ((struct sockaddr_in *)dst)->sin_port;
 
644
                ret = PP2_HDR_LEN_INET;
 
645
        }
 
646
        else if (src && dst && src->ss_family == dst->ss_family && src->ss_family == AF_INET6) {
 
647
                if (buf_len < PP2_HDR_LEN_INET6)
 
648
                        return 0;
 
649
                hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
 
650
                hdr->fam = PP2_FAM_INET6 | PP2_TRANS_STREAM;
 
651
                memcpy(hdr->addr.ip6.src_addr, &((struct sockaddr_in6 *)src)->sin6_addr, 16);
 
652
                memcpy(hdr->addr.ip6.dst_addr, &((struct sockaddr_in6 *)dst)->sin6_addr, 16);
 
653
                hdr->addr.ip6.src_port = ((struct sockaddr_in6 *)src)->sin6_port;
 
654
                hdr->addr.ip6.dst_port = ((struct sockaddr_in6 *)dst)->sin6_port;
 
655
                ret = PP2_HDR_LEN_INET6;
 
656
        }
 
657
        else {
 
658
                if (buf_len < PP2_HDR_LEN_UNSPEC)
 
659
                        return 0;
 
660
                hdr->ver_cmd = PP2_VERSION | PP2_CMD_LOCAL;
 
661
                hdr->fam = PP2_FAM_UNSPEC | PP2_TRANS_UNSPEC;
 
662
                ret = PP2_HDR_LEN_UNSPEC;
 
663
        }
 
664
 
 
665
#ifdef USE_OPENSSL
 
666
        if (srv->pp_opts & SRV_PP_V2_SSL) {
 
667
                if ((buf_len - ret) < sizeof(struct tlv_ssl))
 
668
                        return 0;
 
669
                tlv = (struct tlv_ssl *)&buf[ret];
 
670
                memset(tlv, 0, sizeof(struct tlv_ssl));
 
671
                ssl_tlv_len += sizeof(struct tlv_ssl);
 
672
                tlv->tlv.type = PP2_TYPE_SSL;
 
673
                if (ssl_sock_is_ssl(remote)) {
 
674
                        tlv->client |= PP2_CLIENT_SSL;
 
675
                        value = ssl_sock_get_version(remote);
 
676
                        if (value) {
 
677
                                tlv_len = make_tlv(&buf[ret+ssl_tlv_len], (buf_len-ret-ssl_tlv_len), PP2_TYPE_SSL_VERSION, strlen(value), value);
 
678
                                ssl_tlv_len += tlv_len;
 
679
                        }
 
680
                        if (ssl_sock_get_cert_used(remote)) {
 
681
                                tlv->client |= PP2_CLIENT_CERT;
 
682
                                tlv->verify = htonl(ssl_sock_get_verify_result(remote));
 
683
                        }
 
684
                        if (srv->pp_opts & SRV_PP_V2_SSL_CN) {
 
685
                                value = ssl_sock_get_common_name(remote);
 
686
                                if (value) {
 
687
                                        tlv_len = make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_TYPE_SSL_CN, strlen(value), value);
 
688
                                        ssl_tlv_len += tlv_len;
 
689
                                }
 
690
                        }
 
691
                }
 
692
                tlv->tlv.length_hi = (uint16_t)(ssl_tlv_len - sizeof(struct tlv)) >> 8;
 
693
                tlv->tlv.length_lo = (uint16_t)(ssl_tlv_len - sizeof(struct tlv)) & 0x00ff;
 
694
                ret += ssl_tlv_len;
 
695
        }
 
696
#endif
 
697
 
 
698
        hdr->len = htons((uint16_t)(ret - PP2_HEADER_LEN));
 
699
 
 
700
        return ret;
 
701
}