varnish-cache/bin/varnishd/proxy/cache_proxy_proto.c
0
/*-
1
 * Copyright (c) 2015 Varnish Software AS
2
 * Copyright (c) 2018 GANDI SAS
3
 * All rights reserved.
4
 *
5
 * Authors: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *          Emmanuel Hocdet <manu@gandi.net>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 */
32
33
#include "config.h"
34
35
#include <netinet/in.h>
36
#include <netdb.h>
37
38
#include "cache/cache_varnishd.h"
39
#include "cache/cache_transport.h"
40
#include "proxy/cache_proxy.h"
41
42
#include "vend.h"
43
#include "vsa.h"
44
#include "vss.h"
45
#include "vtcp.h"
46
47
// max. PROXY payload length (excl. sig) - XXX parameter?
48
#define VPX_MAX_LEN 1024
49
50
struct vpx_tlv {
51
        unsigned                magic;
52
#define VPX_TLV_MAGIC           0xdeb9a4a5
53
        unsigned                len;
54
        char                    tlv[] v_counted_by_(len);
55
};
56
57
static inline int
58 80
vpx_ws_err(const struct req *req)
59
{
60 80
        VSL(SLT_Error, req->sp->vxid, "insufficient workspace");
61 80
        return (-1);
62
}
63
64
/**********************************************************************
65
 * PROXY 1 protocol
66
 */
67
68
static const char vpx1_sig[] = {'P', 'R', 'O', 'X', 'Y'};
69
70
static int
71 1323
vpx_proto1(const struct worker *wrk, const struct req *req)
72
{
73
        const char *fld[5];
74
        int i;
75
        char *p, *q;
76
        struct suckaddr *sa;
77
        ssize_t sz;
78 1323
        int pfam = -1;
79
80 1323
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
81 1323
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
82 1323
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
83
84 2646
        q = memchr(req->htc->rxbuf_b, '\r',
85 1323
            req->htc->rxbuf_e - req->htc->rxbuf_b);
86 1323
        if (q == NULL)
87 40
                return (-1);
88
89 1283
        *q++ = '\0';
90
        /* Nuke the CRLF */
91 1283
        if (q == req->htc->rxbuf_e || *q != '\n')
92 0
                return (-1);
93 1283
        *q++ = '\0';
94
95
        /* Split the fields */
96 1283
        p = req->htc->rxbuf_b;
97 7658
        for (i = 0; i < 5; i++) {
98 6415
                p = strchr(p, ' ');
99 6415
                if (p == NULL) {
100 40
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
101
                            "PROXY1: Too few fields");
102 40
                        return (-1);
103
                }
104 6375
                *p++ = '\0';
105 6375
                fld[i] = p;
106 6375
        }
107
108 1243
        if (strchr(p, ' ')) {
109 120
                VSL(SLT_ProxyGarbage, req->sp->vxid,
110
                    "PROXY1: Too many fields");
111 120
                return (-1);
112
        }
113
114 1123
        if (!strcmp(fld[0], "TCP4"))
115 643
                pfam = PF_INET;
116 480
        else if (!strcmp(fld[0], "TCP6"))
117 440
                pfam = PF_INET6;
118
        else {
119 40
                VSL(SLT_ProxyGarbage, req->sp->vxid,
120
                    "PROXY1: Wrong TCP[46] field");
121 40
                return (-1);
122
        }
123
124 1083
        if (! SES_Reserve_client_addr(req->sp, &sa, &sz))
125 0
                return (vpx_ws_err(req));
126 1083
        assert (sz == vsa_suckaddr_len);
127
128 3249
        if (VSS_ResolveOne(sa, fld[1], fld[3],
129 2166
            pfam, SOCK_STREAM, AI_NUMERICHOST | AI_NUMERICSERV) == NULL) {
130 280
                VSL(SLT_ProxyGarbage, req->sp->vxid,
131
                    "PROXY1: Cannot resolve source address");
132 280
                return (-1);
133
        }
134 803
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_IP, fld[1]))
135 0
                return (vpx_ws_err(req));
136 803
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, fld[3]))
137 0
                return (vpx_ws_err(req));
138
139 803
        if (! SES_Reserve_server_addr(req->sp, &sa, &sz))
140 0
                return (vpx_ws_err(req));
141 803
        assert (sz == vsa_suckaddr_len);
142
143 2409
        if (VSS_ResolveOne(sa, fld[2], fld[4],
144 1606
            pfam, SOCK_STREAM, AI_NUMERICHOST | AI_NUMERICSERV) == NULL) {
145 120
                VSL(SLT_ProxyGarbage, req->sp->vxid,
146
                    "PROXY1: Cannot resolve destination address");
147 120
                return (-1);
148
        }
149
150 1366
        VSL(SLT_Proxy, req->sp->vxid, "1 %s %s %s %s",
151 683
            fld[1], fld[3], fld[2], fld[4]);
152 683
        HTC_RxPipeline(req->htc, q);
153 683
        return (0);
154 1323
}
155
156
/**********************************************************************
157
 * PROXY 2 protocol
158
 */
159
160
static const char vpx2_sig[] = {
161
        '\r', '\n', '\r', '\n', '\0', '\r', '\n',
162
        'Q', 'U', 'I', 'T', '\n',
163
};
164
165
static const uint32_t crctable[256] = {
166
        0x00000000UL, 0xF26B8303UL, 0xE13B70F7UL, 0x1350F3F4UL,
167
        0xC79A971FUL, 0x35F1141CUL, 0x26A1E7E8UL, 0xD4CA64EBUL,
168
        0x8AD958CFUL, 0x78B2DBCCUL, 0x6BE22838UL, 0x9989AB3BUL,
169
        0x4D43CFD0UL, 0xBF284CD3UL, 0xAC78BF27UL, 0x5E133C24UL,
170
        0x105EC76FUL, 0xE235446CUL, 0xF165B798UL, 0x030E349BUL,
171
        0xD7C45070UL, 0x25AFD373UL, 0x36FF2087UL, 0xC494A384UL,
172
        0x9A879FA0UL, 0x68EC1CA3UL, 0x7BBCEF57UL, 0x89D76C54UL,
173
        0x5D1D08BFUL, 0xAF768BBCUL, 0xBC267848UL, 0x4E4DFB4BUL,
174
        0x20BD8EDEUL, 0xD2D60DDDUL, 0xC186FE29UL, 0x33ED7D2AUL,
175
        0xE72719C1UL, 0x154C9AC2UL, 0x061C6936UL, 0xF477EA35UL,
176
        0xAA64D611UL, 0x580F5512UL, 0x4B5FA6E6UL, 0xB93425E5UL,
177
        0x6DFE410EUL, 0x9F95C20DUL, 0x8CC531F9UL, 0x7EAEB2FAUL,
178
        0x30E349B1UL, 0xC288CAB2UL, 0xD1D83946UL, 0x23B3BA45UL,
179
        0xF779DEAEUL, 0x05125DADUL, 0x1642AE59UL, 0xE4292D5AUL,
180
        0xBA3A117EUL, 0x4851927DUL, 0x5B016189UL, 0xA96AE28AUL,
181
        0x7DA08661UL, 0x8FCB0562UL, 0x9C9BF696UL, 0x6EF07595UL,
182
        0x417B1DBCUL, 0xB3109EBFUL, 0xA0406D4BUL, 0x522BEE48UL,
183
        0x86E18AA3UL, 0x748A09A0UL, 0x67DAFA54UL, 0x95B17957UL,
184
        0xCBA24573UL, 0x39C9C670UL, 0x2A993584UL, 0xD8F2B687UL,
185
        0x0C38D26CUL, 0xFE53516FUL, 0xED03A29BUL, 0x1F682198UL,
186
        0x5125DAD3UL, 0xA34E59D0UL, 0xB01EAA24UL, 0x42752927UL,
187
        0x96BF4DCCUL, 0x64D4CECFUL, 0x77843D3BUL, 0x85EFBE38UL,
188
        0xDBFC821CUL, 0x2997011FUL, 0x3AC7F2EBUL, 0xC8AC71E8UL,
189
        0x1C661503UL, 0xEE0D9600UL, 0xFD5D65F4UL, 0x0F36E6F7UL,
190
        0x61C69362UL, 0x93AD1061UL, 0x80FDE395UL, 0x72966096UL,
191
        0xA65C047DUL, 0x5437877EUL, 0x4767748AUL, 0xB50CF789UL,
192
        0xEB1FCBADUL, 0x197448AEUL, 0x0A24BB5AUL, 0xF84F3859UL,
193
        0x2C855CB2UL, 0xDEEEDFB1UL, 0xCDBE2C45UL, 0x3FD5AF46UL,
194
        0x7198540DUL, 0x83F3D70EUL, 0x90A324FAUL, 0x62C8A7F9UL,
195
        0xB602C312UL, 0x44694011UL, 0x5739B3E5UL, 0xA55230E6UL,
196
        0xFB410CC2UL, 0x092A8FC1UL, 0x1A7A7C35UL, 0xE811FF36UL,
197
        0x3CDB9BDDUL, 0xCEB018DEUL, 0xDDE0EB2AUL, 0x2F8B6829UL,
198
        0x82F63B78UL, 0x709DB87BUL, 0x63CD4B8FUL, 0x91A6C88CUL,
199
        0x456CAC67UL, 0xB7072F64UL, 0xA457DC90UL, 0x563C5F93UL,
200
        0x082F63B7UL, 0xFA44E0B4UL, 0xE9141340UL, 0x1B7F9043UL,
201
        0xCFB5F4A8UL, 0x3DDE77ABUL, 0x2E8E845FUL, 0xDCE5075CUL,
202
        0x92A8FC17UL, 0x60C37F14UL, 0x73938CE0UL, 0x81F80FE3UL,
203
        0x55326B08UL, 0xA759E80BUL, 0xB4091BFFUL, 0x466298FCUL,
204
        0x1871A4D8UL, 0xEA1A27DBUL, 0xF94AD42FUL, 0x0B21572CUL,
205
        0xDFEB33C7UL, 0x2D80B0C4UL, 0x3ED04330UL, 0xCCBBC033UL,
206
        0xA24BB5A6UL, 0x502036A5UL, 0x4370C551UL, 0xB11B4652UL,
207
        0x65D122B9UL, 0x97BAA1BAUL, 0x84EA524EUL, 0x7681D14DUL,
208
        0x2892ED69UL, 0xDAF96E6AUL, 0xC9A99D9EUL, 0x3BC21E9DUL,
209
        0xEF087A76UL, 0x1D63F975UL, 0x0E330A81UL, 0xFC588982UL,
210
        0xB21572C9UL, 0x407EF1CAUL, 0x532E023EUL, 0xA145813DUL,
211
        0x758FE5D6UL, 0x87E466D5UL, 0x94B49521UL, 0x66DF1622UL,
212
        0x38CC2A06UL, 0xCAA7A905UL, 0xD9F75AF1UL, 0x2B9CD9F2UL,
213
        0xFF56BD19UL, 0x0D3D3E1AUL, 0x1E6DCDEEUL, 0xEC064EEDUL,
214
        0xC38D26C4UL, 0x31E6A5C7UL, 0x22B65633UL, 0xD0DDD530UL,
215
        0x0417B1DBUL, 0xF67C32D8UL, 0xE52CC12CUL, 0x1747422FUL,
216
        0x49547E0BUL, 0xBB3FFD08UL, 0xA86F0EFCUL, 0x5A048DFFUL,
217
        0x8ECEE914UL, 0x7CA56A17UL, 0x6FF599E3UL, 0x9D9E1AE0UL,
218
        0xD3D3E1ABUL, 0x21B862A8UL, 0x32E8915CUL, 0xC083125FUL,
219
        0x144976B4UL, 0xE622F5B7UL, 0xF5720643UL, 0x07198540UL,
220
        0x590AB964UL, 0xAB613A67UL, 0xB831C993UL, 0x4A5A4A90UL,
221
        0x9E902E7BUL, 0x6CFBAD78UL, 0x7FAB5E8CUL, 0x8DC0DD8FUL,
222
        0xE330A81AUL, 0x115B2B19UL, 0x020BD8EDUL, 0xF0605BEEUL,
223
        0x24AA3F05UL, 0xD6C1BC06UL, 0xC5914FF2UL, 0x37FACCF1UL,
224
        0x69E9F0D5UL, 0x9B8273D6UL, 0x88D28022UL, 0x7AB90321UL,
225
        0xAE7367CAUL, 0x5C18E4C9UL, 0x4F48173DUL, 0xBD23943EUL,
226
        0xF36E6F75UL, 0x0105EC76UL, 0x12551F82UL, 0xE03E9C81UL,
227
        0x34F4F86AUL, 0xC69F7B69UL, 0xD5CF889DUL, 0x27A40B9EUL,
228
        0x79B737BAUL, 0x8BDCB4B9UL, 0x988C474DUL, 0x6AE7C44EUL,
229
        0xBE2DA0A5UL, 0x4C4623A6UL, 0x5F16D052UL, 0xAD7D5351UL
230
};
231
232 200
static uint32_t crc32c(const uint8_t *buf, int len)
233
{
234 200
        uint32_t crc = 0xffffffff;
235 31200
        while (len-- > 0) {
236 31000
                crc = (crc >> 8) ^ crctable[(crc ^ (*buf++)) & 0xff];
237
        }
238 200
        return (crc ^ 0xffffffff);
239
}
240
241
struct vpx_tlv_iter {
242
        uint8_t         t;
243
        void            *p;
244
        uint16_t        l;
245
        const char      *e;
246
247
        unsigned char   *_p;
248
        uint16_t        _l;
249
};
250
251
static void
252 2480
vpx_tlv_iter0(struct vpx_tlv_iter *vpi, void *p, unsigned l)
253
{
254
255 2480
        AN(p);
256 2480
        assert(l < 65536);
257 2480
        memset(vpi, 0, sizeof *vpi);
258 2480
        vpi->_p = p;
259 2480
        vpi->_l = l;
260 2480
}
261
262
static int
263 6720
vpx_tlv_itern(struct vpx_tlv_iter *vpi)
264
{
265 6720
        if (vpi->_l == 0 || vpi->e != NULL)
266 1320
                return (0);
267 5400
        if (vpi->_l < 3) {
268 40
                vpi->e = "Dribble bytes";
269 40
                return (0);
270
        }
271 5360
        vpi->t = *vpi->_p;
272 5360
        vpi->l = vbe16dec(vpi->_p + 1);
273 5360
        if (vpi->l + 3 > vpi->_l) {
274 80
                vpi->e = "Length Error";
275 80
                return (0);
276
        }
277 5280
        vpi->p = vpi->_p + 3;
278 5280
        vpi->_p += 3 + vpi->l;
279 5280
        vpi->_l -= 3 + vpi->l;
280 5280
        return (1);
281 6720
}
282
283
#define VPX_TLV_FOREACH(ptr, len, itv)                          \
284
        for (vpx_tlv_iter0(itv, ptr, len);                      \
285
                (vpi->e == NULL) && vpx_tlv_itern(itv);)
286
287
int
288 1040
VPX_tlv(const struct req *req, int typ, const void **dst, int *len)
289
{
290
        struct vpx_tlv *tlv;
291
        struct vpx_tlv_iter vpi[1], vpi2[1];
292
        uintptr_t *up;
293
294 1040
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
295 1040
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
296 1040
        AN(dst);
297 1040
        AN(len);
298 1040
        *dst = NULL;
299 1040
        *len = 0;
300
301 1040
        if (SES_Get_proxy_tlv(req->sp, &up) != 0 || *up == 0)
302 200
                return (-1);
303 840
        CAST_OBJ_NOTNULL(tlv, (void*)(*up), VPX_TLV_MAGIC);
304
305 2080
        VPX_TLV_FOREACH(tlv->tlv, tlv->len, vpi) {
306 2000
                if (vpi->t == typ) {
307 600
                        *dst = vpi->p;
308 600
                        *len = vpi->l;
309 600
                        return (0);
310
                }
311 1400
                if (vpi->t != PP2_TYPE_SSL)
312 1200
                        continue;
313 600
                VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
314 560
                        if (vpi2->t == typ) {
315 160
                                *dst = vpi2->p;
316 160
                                *len = vpi2->l;
317 160
                                return (0);
318
                        }
319
                }
320
        }
321 80
        return (-1);
322 1040
}
323
324
static int
325 1938
vpx_proto2(const struct worker *wrk, const struct req *req)
326
{
327
        uintptr_t *up;
328
        uint16_t tlv_len;
329
        const uint8_t *p, *ap, *pp;
330
        char *d, *tlv_start;
331 1938
        sa_family_t pfam = 0xff;
332 1938
        struct suckaddr *sa = NULL;
333
        ssize_t sz;
334
        char ha[VTCP_ADDRBUFSIZE];
335
        char pa[VTCP_PORTBUFSIZE];
336
        char hb[VTCP_ADDRBUFSIZE];
337
        char pb[VTCP_PORTBUFSIZE];
338
        struct vpx_tlv_iter vpi[1], vpi2[1];
339
        struct vpx_tlv *tlv;
340
        uint16_t l;
341
        unsigned hdr_len, flen, alen;
342 1938
        unsigned const plen = 2, aoff = 16;
343
344 1938
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
345 1938
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
346 1938
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
347
348 1938
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= 16L);
349 1938
        l = vbe16dec(req->htc->rxbuf_b + 14);
350 1938
        assert(l <= VPX_MAX_LEN); // vpx_complete()
351 1938
        hdr_len = l + 16L;
352 1938
        assert(req->htc->rxbuf_e >= req->htc->rxbuf_b + hdr_len);
353 1938
        HTC_RxPipeline(req->htc, req->htc->rxbuf_b + hdr_len);
354 1938
        p = (const void *)req->htc->rxbuf_b;
355 1938
        d = req->htc->rxbuf_b + 16L;
356
357
        /* Version @12 top half */
358 1938
        if ((p[12] >> 4) != 2) {
359 0
                VSL(SLT_ProxyGarbage, req->sp->vxid,
360 0
                    "PROXY2: bad version (%d)", p[12] >> 4);
361 0
                return (-1);
362
        }
363
364
        /* Command @12 bottom half */
365 1938
        switch (p[12] & 0x0f) {
366
        case 0x0:
367 378
                VSL(SLT_Proxy, req->sp->vxid, "2 local local local local");
368 378
                return (0);
369
        case 0x1:
370
                /* Proxied connection */
371 1480
                break;
372
        default:
373 160
                VSL(SLT_ProxyGarbage, req->sp->vxid,
374 80
                    "PROXY2: bad command (%d)", p[12] & 0x0f);
375 80
                return (-1);
376
        }
377
378
        /* Address family & protocol @13 */
379 1480
        switch (p[13]) {
380
        case 0x00:
381
                /* UNSPEC|UNSPEC, ignore proxy header */
382 120
                VSL(SLT_ProxyGarbage, req->sp->vxid,
383
                    "PROXY2: Ignoring UNSPEC|UNSPEC addresses");
384 120
                return (0);
385
        case 0x11:
386
                /* IPv4|TCP */
387 960
                pfam = AF_INET;
388 960
                alen = 4;
389 960
                break;
390
        case 0x21:
391
                /* IPv6|TCP */
392 320
                pfam = AF_INET6;
393 320
                alen = 16;
394 320
                break;
395
        default:
396
                /* Ignore proxy header */
397 160
                VSL(SLT_ProxyGarbage, req->sp->vxid,
398 80
                    "PROXY2: Ignoring unsupported protocol (0x%02x)", p[13]);
399 80
                return (0);
400
        }
401
402 1280
        flen = 2 * alen + 2 * plen;
403
404 1280
        if (l < flen) {
405 320
                VSL(SLT_ProxyGarbage, req->sp->vxid,
406
                    "PROXY2: Ignoring short %s addresses (%u)",
407 160
                    pfam == AF_INET ? "IPv4" : "IPv6", l);
408 160
                return (0);
409
        }
410
411 1120
        l -= flen;
412 1120
        d += flen;
413
414 1120
        ap = p + aoff;
415 1120
        pp = ap + 2 * alen;
416
417
        /* src/client */
418 1120
        if (! SES_Reserve_client_addr(req->sp, &sa, &sz))
419 0
                return (vpx_ws_err(req));
420 1120
        assert(sz == vsa_suckaddr_len);
421 1120
        AN(VSA_BuildFAP(sa, pfam, ap, alen, pp, plen));
422 1120
        VTCP_name(sa, hb, sizeof hb, pb, sizeof pb);
423
424 1120
        ap += alen;
425 1120
        pp += plen;
426
427
        /* dst/server */
428 1120
        if (! SES_Reserve_server_addr(req->sp, &sa, &sz))
429 0
                return (vpx_ws_err(req));
430 1120
        assert(sz == vsa_suckaddr_len);
431 1120
        AN(VSA_BuildFAP(sa, pfam, ap, alen, pp, plen));
432 1120
        VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
433
434 1120
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_IP, hb))
435 0
                return (vpx_ws_err(req));
436 1120
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, pb))
437 0
                return (vpx_ws_err(req));
438
439 1120
        VSL(SLT_Proxy, req->sp->vxid, "2 %s %s %s %s", hb, pb, ha, pa);
440
441 1120
        tlv_start = d;
442 1120
        tlv_len = l;
443
444 2680
        VPX_TLV_FOREACH(d, l, vpi) {
445 1640
                if (vpi->t == PP2_TYPE_SSL) {
446 360
                        if (vpi->l < 5) {
447 40
                                vpi->e = "Length Error";
448 40
                                break;
449
                        }
450 1400
                        VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
451
                        }
452 320
                        vpi->e = vpi2->e;
453 1600
                } else if (vpi->t == PP2_TYPE_CRC32C) {
454 200
                        uint32_t n_crc32c = vbe32dec(vpi->p);
455 200
                        vbe32enc(vpi->p, 0);
456 200
                        if (crc32c(p, hdr_len) != n_crc32c) {
457 40
                                VSL(SLT_ProxyGarbage, req->sp->vxid,
458
                                    "PROXY2: CRC error");
459 40
                                return (-1);
460
                        }
461 160
                }
462
        }
463 1080
        if (vpi->e != NULL) {
464 160
                VSL(SLT_ProxyGarbage, req->sp->vxid, "PROXY2: TLV %s", vpi->e);
465 160
                return (-1);
466
        }
467 920
        tlv = WS_Alloc(req->sp->ws, sizeof *tlv + tlv_len);
468 920
        if (tlv == NULL)
469 80
                return (vpx_ws_err(req));
470 840
        INIT_OBJ(tlv, VPX_TLV_MAGIC);
471 840
        tlv->len = tlv_len;
472 840
        memcpy(tlv->tlv, tlv_start, tlv_len);
473 840
        if (! SES_Reserve_proxy_tlv(req->sp, &up, &sz))
474 0
                return (vpx_ws_err(req));
475 840
        assert(sz == sizeof up);
476 840
        *up = (uintptr_t)tlv;
477 840
        return (0);
478 1938
}
479
480
/**********************************************************************
481
 * HTC_Rx completion detector
482
 */
483
484
static enum htc_status_e v_matchproto_(htc_complete_f)
485 6949
vpx_complete(struct http_conn *htc)
486
{
487
        size_t z, l;
488
        uint16_t j;
489
        char *p, *q;
490
491 6949
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
492 6949
        AN(WS_Reservation(htc->ws));
493 6949
        assert(pdiff(htc->rxbuf_b, htc->rxbuf_e) <= WS_ReservationSize(htc->ws));
494
495 6949
        l = htc->rxbuf_e - htc->rxbuf_b;
496 6949
        p = htc->rxbuf_b;
497 6949
        j = 0x3;
498 38499
        for (z = 0; z < l; z++) {
499 35037
                if (z < sizeof vpx1_sig && p[z] != vpx1_sig[z])
500 10265
                        j &= ~1;
501 35037
                if (z < sizeof vpx2_sig && p[z] != vpx2_sig[z])
502 8458
                        j &= ~2;
503 35037
                if (j == 0)
504 40
                        return (HTC_S_JUNK);
505 34997
                if (j == 1 && z == sizeof vpx1_sig) {
506 1403
                        q = memchr(p + z, '\n', htc->rxbuf_e - (p + z));
507 1403
                        if (q != NULL && (q - htc->rxbuf_b) > 107)
508 40
                                return (HTC_S_OVERFLOW);
509 1363
                        if (q == NULL)
510 40
                                return (HTC_S_MORE);
511 1323
                        return (HTC_S_COMPLETE);
512
                }
513 33594
                if (j == 2 && z == sizeof vpx2_sig) {
514 2044
                        if (l < 16)
515 0
                                return (HTC_S_MORE);
516 2044
                        j = vbe16dec(p + 14);
517 2044
                        if (j > VPX_MAX_LEN)
518 80
                                return (HTC_S_OVERFLOW);
519 1964
                        if (l < 16L + j)
520 26
                                return (HTC_S_MORE);
521 1938
                        return (HTC_S_COMPLETE);
522
                }
523 31550
        }
524 3462
        return (HTC_S_MORE);
525 6949
}
526
527
static void v_matchproto_(task_func_t)
528 3461
vpx_new_session(struct worker *wrk, void *arg)
529
{
530
        struct req *req;
531
        struct sess *sp;
532
        enum htc_status_e hs;
533
        char *p;
534
        int i;
535
536 3461
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
537 3461
        CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC);
538 3461
        sp = req->sp;
539 3461
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
540
541
        /* Per specification */
542 3461
        assert(sizeof vpx1_sig == 5);
543 3461
        assert(sizeof vpx2_sig == 12);
544
545 3461
        HTC_RxInit(req->htc, req->ws);
546 6922
        hs = HTC_RxStuff(req->htc, vpx_complete, NULL, NULL, NAN,
547 3461
            sp->t_idle + cache_param->timeout_idle, NAN, VPX_MAX_LEN);
548 3461
        if (hs != HTC_S_COMPLETE) {
549 200
                Req_Release(req);
550 200
                SES_DeleteHS(sp, hs, NAN);
551 200
                return;
552
        }
553 3261
        p = req->htc->rxbuf_b;
554 3261
        if (p[0] == vpx1_sig[0])
555 1323
                i = vpx_proto1(wrk, req);
556 1938
        else if (p[0] == vpx2_sig[0])
557 1938
                i = vpx_proto2(wrk, req);
558
        else
559 0
                WRONG("proxy sig mismatch");
560
561 3261
        if (i) {
562 1000
                Req_Release(req);
563 1000
                SES_Delete(sp, SC_RX_JUNK, NAN);
564 1000
                return;
565
        }
566
567 2261
        SES_SetTransport(wrk, sp, req, &HTTP1_transport);
568 3461
}
569
570
struct transport PROXY_transport = {
571
        .name =                 "PROXY",
572
        .proto_ident =          "PROXY",
573
        .magic =                TRANSPORT_MAGIC,
574
        .new_session =          vpx_new_session,
575
};
576
577
static void
578 960
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
579
{
580
        const struct sockaddr_in *sin4;
581
        const struct sockaddr_in6 *sin6;
582
        socklen_t sl;
583
584 960
        if (proto == PF_INET6) {
585 160
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
586 160
                AN(sin6);
587 160
                assert(sl >= sizeof *sin6);
588 160
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
589 160
        } else {
590 800
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
591 800
                AN(sin4);
592 800
                assert(sl >= sizeof *sin4);
593 800
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
594
        }
595 960
}
596
597
static void
598 960
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
599
{
600
        uint8_t b[2];
601
602 960
        vbe16enc(b, (uint16_t)VSA_Port(s));
603 960
        VSB_bcat(vsb, b, sizeof(b));
604 960
}
605
606
static void
607 480
vpx_enc_authority(struct vsb *vsb, const char *authority, size_t l_authority)
608
{
609
        uint16_t l;
610
611 480
        AN(vsb);
612
613 480
        if (l_authority == 0)
614 160
                return;
615 320
        AN(authority);
616 320
        AN(*authority);
617
618 320
        VSB_putc(vsb, PP2_TYPE_AUTHORITY);
619 320
        vbe16enc(&l, l_authority);
620 320
        VSB_bcat(vsb, &l, sizeof(l));
621 320
        VSB_cat(vsb, authority);
622 480
}
623
624
/* short path for stringified addresses from session attributes */
625
static void
626 120
vpx_format_proxy_v1(struct vsb *vsb, int proto,
627
    const char *cip,  const char *cport,
628
    const char *sip,  const char *sport)
629
{
630 120
        AN(vsb);
631 120
        AN(cip);
632 120
        AN(cport);
633 120
        AN(sip);
634 120
        AN(sport);
635
636 120
        VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
637
638 120
        if (proto == PF_INET6)
639 40
                VSB_cat(vsb, " TCP6 ");
640 80
        else if (proto == PF_INET)
641 80
                VSB_cat(vsb, " TCP4 ");
642
        else
643 0
                WRONG("Wrong proxy v1 proto");
644
645 120
        VSB_printf(vsb, "%s %s %s %s\r\n", cip, sip, cport, sport);
646
647 120
        AZ(VSB_finish(vsb));
648 120
}
649
650
static void
651 480
vpx_format_proxy_v2(struct vsb *vsb, int proto,
652
    const struct suckaddr *sac, const struct suckaddr *sas,
653
    const char *authority)
654
{
655 480
        size_t l_authority = 0;
656 480
        uint16_t l_tlv = 0, l;
657
658 480
        AN(vsb);
659 480
        AN(sac);
660 480
        AN(sas);
661
662 480
        if (authority != NULL && *authority != '\0') {
663 320
                l_authority = strlen(authority);
664
                /* 3 bytes in the TLV before the authority string */
665 320
                assert(3 + l_authority <= UINT16_MAX);
666 320
                l_tlv = 3 + l_authority;
667 320
        }
668
669 480
        VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
670 480
        VSB_putc(vsb, 0x21);
671 480
        if (proto == PF_INET6) {
672 80
                VSB_putc(vsb, 0x21);
673 80
                vbe16enc(&l, 0x24 + l_tlv);
674 80
                VSB_bcat(vsb, &l, sizeof(l));
675 480
        } else if (proto == PF_INET) {
676 400
                VSB_putc(vsb, 0x11);
677 400
                vbe16enc(&l, 0x0c + l_tlv);
678 400
                VSB_bcat(vsb, &l, sizeof(l));
679 400
        } else {
680 0
                WRONG("Wrong proxy v2 proto");
681
        }
682 480
        vpx_enc_addr(vsb, proto, sac);
683 480
        vpx_enc_addr(vsb, proto, sas);
684 480
        vpx_enc_port(vsb, sac);
685 480
        vpx_enc_port(vsb, sas);
686 480
        vpx_enc_authority(vsb, authority, l_authority);
687 480
        AZ(VSB_finish(vsb));
688 480
}
689
690
void
691 400
VPX_Format_Proxy(struct vsb *vsb, int version,
692
    const struct suckaddr *sac, const struct suckaddr *sas,
693
    const char *authority)
694
{
695
        int proto;
696
        char hac[VTCP_ADDRBUFSIZE];
697
        char pac[VTCP_PORTBUFSIZE];
698
        char has[VTCP_ADDRBUFSIZE];
699
        char pas[VTCP_PORTBUFSIZE];
700
701 400
        AN(vsb);
702 400
        AN(sac);
703 400
        AN(sas);
704
705 400
        assert(version == 1 || version == 2);
706
707 400
        proto = VSA_Get_Proto(sas);
708 400
        assert(proto == VSA_Get_Proto(sac));
709
710 400
        if (version == 1) {
711 40
                VTCP_name(sac, hac, sizeof hac, pac, sizeof pac);
712 40
                VTCP_name(sas, has, sizeof has, pas, sizeof pas);
713 40
                vpx_format_proxy_v1(vsb, proto, hac, pac, has, pas);
714 400
        } else if (version == 2) {
715 360
                vpx_format_proxy_v2(vsb, proto, sac, sas, authority);
716 360
        } else
717 0
                WRONG("Wrong proxy version");
718 400
}
719
720
#define PXY_BUFSZ                                               \
721
        (sizeof(vpx1_sig) + 4 /* TCPx */ +                      \
722
        2 * VTCP_ADDRBUFSIZE + 2 * VTCP_PORTBUFSIZE +           \
723
        6 /* spaces, CRLF */ + 16 /* safety */ )
724
725
int
726 200
VPX_Send_Proxy(int fd, int version, const struct sess *sp)
727
{
728
        struct vsb vsb[1], *vsb2;
729
        struct suckaddr *sac, *sas;
730
        char ha[VTCP_ADDRBUFSIZE];
731
        char pa[VTCP_PORTBUFSIZE];
732
        char buf[PXY_BUFSZ];
733
        int proto, r;
734
735 200
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
736 200
        assert(version == 1 || version == 2);
737 200
        AN(VSB_init(vsb, buf, sizeof buf));
738
739 200
        AZ(SES_Get_server_addr(sp, &sas));
740 200
        AN(sas);
741 200
        proto = VSA_Get_Proto(sas);
742
743 200
        if (version == 1) {
744 80
                VTCP_name(sas, ha, sizeof ha, pa, sizeof pa);
745 160
                vpx_format_proxy_v1(vsb, proto,
746 80
                    SES_Get_String_Attr(sp, SA_CLIENT_IP),
747 80
                    SES_Get_String_Attr(sp, SA_CLIENT_PORT),
748 80
                    ha, pa);
749 200
        } else if (version == 2) {
750 120
                AZ(SES_Get_client_addr(sp, &sac));
751 120
                AN(sac);
752 120
                vpx_format_proxy_v2(vsb, proto, sac, sas, NULL);
753 120
        } else
754 0
                WRONG("Wrong proxy version");
755
756 200
        r = write(fd, VSB_data(vsb), VSB_len(vsb));
757 200
        VTCP_Assert(r);
758
759 200
        if (!DO_DEBUG(DBG_PROTOCOL))
760 200
                return (r);
761
762 0
        vsb2 = VSB_new_auto();
763 0
        AN(vsb2);
764 0
        VSB_quote(vsb2, VSB_data(vsb), VSB_len(vsb),
765 0
            version == 2 ? VSB_QUOTE_HEX : 0);
766 0
        AZ(VSB_finish(vsb2));
767 0
        VSL(SLT_Debug, NO_VXID, "PROXY_HDR %s", VSB_data(vsb2));
768 0
        VSB_destroy(&vsb2);
769 0
        VSB_fini(vsb);
770 0
        return (r);
771 200
}
772
773
#undef PXY_BUFSZ