vinyl-cache/bin/vinyld/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_int.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 42
vpx_ws_err(const struct req *req)
59
{
60 42
        VSL(SLT_Error, req->sp->vxid, "insufficient workspace");
61 42
        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 715
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 715
        int pfam = -1;
79
80 715
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
81 715
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
82 715
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
83
84 715
        q = vmemchr(req->htc->rxbuf_b, '\r',
85
            req->htc->rxbuf_e - req->htc->rxbuf_b);
86 715
        if (q == NULL)
87 21
                return (-1);
88
89 694
        *q++ = '\0';
90
        /* Nuke the CRLF */
91 694
        if (q == req->htc->rxbuf_e || *q != '\n')
92 0
                return (-1);
93 694
        *q++ = '\0';
94
95
        /* Split the fields */
96 694
        p = req->htc->rxbuf_b;
97 4143
        for (i = 0; i < 5; i++) {
98 3470
                p = strchr(p, ' ');
99 3470
                if (p == NULL) {
100 21
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
101
                            "PROXY1: Too few fields");
102 21
                        return (-1);
103
                }
104 3449
                *p++ = '\0';
105 3449
                fld[i] = p;
106 3449
        }
107
108 673
        if (strchr(p, ' ')) {
109 63
                VSL(SLT_ProxyGarbage, req->sp->vxid,
110
                    "PROXY1: Too many fields");
111 63
                return (-1);
112
        }
113
114 610
        if (!vstrcmp(fld[0], "TCP4"))
115 358
                pfam = PF_INET;
116 252
        else if (!vstrcmp(fld[0], "TCP6"))
117 231
                pfam = PF_INET6;
118
        else {
119 21
                VSL(SLT_ProxyGarbage, req->sp->vxid,
120
                    "PROXY1: Wrong TCP[46] field");
121 21
                return (-1);
122
        }
123
124 589
        if (! SES_Reserve_client_addr(req->sp, &sa, &sz))
125 0
                return (vpx_ws_err(req));
126 589
        assert (sz == vsa_suckaddr_len);
127
128 1767
        if (VSS_ResolveOne(sa, fld[1], fld[3],
129 1178
            pfam, SOCK_STREAM, AI_NUMERICHOST | AI_NUMERICSERV) == NULL) {
130 147
                VSL(SLT_ProxyGarbage, req->sp->vxid,
131
                    "PROXY1: Cannot resolve source address");
132 147
                return (-1);
133
        }
134 442
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_IP, fld[1]))
135 0
                return (vpx_ws_err(req));
136 442
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, fld[3]))
137 0
                return (vpx_ws_err(req));
138
139 442
        if (! SES_Reserve_server_addr(req->sp, &sa, &sz))
140 0
                return (vpx_ws_err(req));
141 442
        assert (sz == vsa_suckaddr_len);
142
143 1326
        if (VSS_ResolveOne(sa, fld[2], fld[4],
144 884
            pfam, SOCK_STREAM, AI_NUMERICHOST | AI_NUMERICSERV) == NULL) {
145 63
                VSL(SLT_ProxyGarbage, req->sp->vxid,
146
                    "PROXY1: Cannot resolve destination address");
147 63
                return (-1);
148
        }
149
150 758
        VSL(SLT_Proxy, req->sp->vxid, "1 %s %s %s %s",
151 379
            fld[1], fld[3], fld[2], fld[4]);
152 379
        HTC_RxPipeline(req->htc, q);
153 379
        return (0);
154 715
}
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 105
static uint32_t crc32c(const uint8_t *buf, int len)
233
{
234 105
        uint32_t crc = 0xffffffff;
235 16380
        while (len-- > 0) {
236 16275
                crc = (crc >> 8) ^ crctable[(crc ^ (*buf++)) & 0xff];
237
        }
238 105
        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 1302
vpx_tlv_iter0(struct vpx_tlv_iter *vpi, void *p, unsigned l)
253
{
254
255 1302
        AN(p);
256 1302
        assert(l < 65536);
257 1302
        memset(vpi, 0, sizeof *vpi);
258 1302
        vpi->_p = p;
259 1302
        vpi->_l = l;
260 1302
}
261
262
static int
263 3528
vpx_tlv_itern(struct vpx_tlv_iter *vpi)
264
{
265 3528
        if (vpi->_l == 0 || vpi->e != NULL)
266 693
                return (0);
267 2835
        if (vpi->_l < 3) {
268 21
                vpi->e = "Dribble bytes";
269 21
                return (0);
270
        }
271 2814
        vpi->t = *vpi->_p;
272 2814
        vpi->l = vbe16dec(vpi->_p + 1);
273 2814
        if (vpi->l + 3 > vpi->_l) {
274 42
                vpi->e = "Length Error";
275 42
                return (0);
276
        }
277 2772
        vpi->p = vpi->_p + 3;
278 2772
        vpi->_p += 3 + vpi->l;
279 2772
        vpi->_l -= 3 + vpi->l;
280 2772
        return (1);
281 3528
}
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 546
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 546
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
295 546
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
296 546
        AN(dst);
297 546
        AN(len);
298 546
        *dst = NULL;
299 546
        *len = 0;
300
301 546
        if (SES_Get_proxy_tlv(req->sp, &up) != 0 || *up == 0)
302 105
                return (-1);
303 441
        CAST_OBJ_NOTNULL(tlv, (void*)(*up), VPX_TLV_MAGIC);
304
305 1092
        VPX_TLV_FOREACH(tlv->tlv, tlv->len, vpi) {
306 1050
                if (vpi->t == typ) {
307 315
                        *dst = vpi->p;
308 315
                        *len = vpi->l;
309 315
                        return (0);
310
                }
311 735
                if (vpi->t != PP2_TYPE_SSL)
312 630
                        continue;
313 315
                VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
314 294
                        if (vpi2->t == typ) {
315 84
                                *dst = vpi2->p;
316 84
                                *len = vpi2->l;
317 84
                                return (0);
318
                        }
319
                }
320
        }
321 42
        return (-1);
322 546
}
323
324
static int
325 1058
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 1058
        sa_family_t pfam = 0xff;
332 1058
        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 1058
        unsigned const plen = 2, aoff = 16;
343
344 1058
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
345 1058
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
346 1058
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
347
348 1058
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= 16L);
349 1058
        l = vbe16dec(req->htc->rxbuf_b + 14);
350 1058
        assert(l <= VPX_MAX_LEN); // vpx_complete()
351 1058
        hdr_len = l + 16L;
352 1058
        assert(req->htc->rxbuf_e >= req->htc->rxbuf_b + hdr_len);
353 1058
        HTC_RxPipeline(req->htc, req->htc->rxbuf_b + hdr_len);
354 1058
        p = (const void *)req->htc->rxbuf_b;
355 1058
        d = req->htc->rxbuf_b + 16L;
356
357
        /* Version @12 top half */
358 1058
        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 1058
        switch (p[12] & 0x0f) {
366
        case 0x0:
367 239
                VSL(SLT_Proxy, req->sp->vxid, "2 local local local local");
368 239
                return (0);
369
        case 0x1:
370
                /* Proxied connection */
371 777
                break;
372
        default:
373 84
                VSL(SLT_ProxyGarbage, req->sp->vxid,
374 42
                    "PROXY2: bad command (%d)", p[12] & 0x0f);
375 42
                return (-1);
376
        }
377
378
        /* Address family & protocol @13 */
379 777
        switch (p[13]) {
380
        case 0x00:
381
                /* UNSPEC|UNSPEC, ignore proxy header */
382 63
                VSL(SLT_ProxyGarbage, req->sp->vxid,
383
                    "PROXY2: Ignoring UNSPEC|UNSPEC addresses");
384 63
                return (0);
385
        case 0x11:
386
                /* IPv4|TCP */
387 504
                pfam = AF_INET;
388 504
                alen = 4;
389 504
                break;
390
        case 0x21:
391
                /* IPv6|TCP */
392 168
                pfam = AF_INET6;
393 168
                alen = 16;
394 168
                break;
395
        default:
396
                /* Ignore proxy header */
397 84
                VSL(SLT_ProxyGarbage, req->sp->vxid,
398 42
                    "PROXY2: Ignoring unsupported protocol (0x%02x)", p[13]);
399 42
                return (0);
400
        }
401
402 672
        flen = 2 * alen + 2 * plen;
403
404 672
        if (l < flen) {
405 168
                VSL(SLT_ProxyGarbage, req->sp->vxid,
406
                    "PROXY2: Ignoring short %s addresses (%u)",
407 84
                    pfam == AF_INET ? "IPv4" : "IPv6", l);
408 84
                return (0);
409
        }
410
411 588
        l -= flen;
412 588
        d += flen;
413
414 588
        ap = p + aoff;
415 588
        pp = ap + 2 * alen;
416
417
        /* src/client */
418 588
        if (! SES_Reserve_client_addr(req->sp, &sa, &sz))
419 0
                return (vpx_ws_err(req));
420 588
        assert(sz == vsa_suckaddr_len);
421 588
        AN(VSA_BuildFAP(sa, pfam, ap, alen, pp, plen));
422 588
        VTCP_name(sa, hb, sizeof hb, pb, sizeof pb);
423
424 588
        ap += alen;
425 588
        pp += plen;
426
427
        /* dst/server */
428 588
        if (! SES_Reserve_server_addr(req->sp, &sa, &sz))
429 0
                return (vpx_ws_err(req));
430 588
        assert(sz == vsa_suckaddr_len);
431 588
        AN(VSA_BuildFAP(sa, pfam, ap, alen, pp, plen));
432 588
        VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
433
434 588
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_IP, hb))
435 0
                return (vpx_ws_err(req));
436 588
        if (! SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, pb))
437 0
                return (vpx_ws_err(req));
438
439 588
        VSL(SLT_Proxy, req->sp->vxid, "2 %s %s %s %s", hb, pb, ha, pa);
440
441 588
        tlv_start = d;
442 588
        tlv_len = l;
443
444 1407
        VPX_TLV_FOREACH(d, l, vpi) {
445 861
                if (vpi->t == PP2_TYPE_SSL) {
446 189
                        if (vpi->l < 5) {
447 21
                                vpi->e = "Length Error";
448 21
                                break;
449
                        }
450 735
                        VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
451
                        }
452 168
                        vpi->e = vpi2->e;
453 840
                } else if (vpi->t == PP2_TYPE_CRC32C) {
454
                        uint32_t n_crc32c;
455 105
                        if (vpi->l != 4) {
456 0
                                vpi->e = "Length Error";
457 0
                                break;
458
                        }
459 105
                        n_crc32c = vbe32dec(vpi->p);
460 105
                        vbe32enc(vpi->p, 0);
461 105
                        if (crc32c(p, hdr_len) != n_crc32c) {
462 21
                                VSL(SLT_ProxyGarbage, req->sp->vxid,
463
                                    "PROXY2: CRC error");
464 21
                                return (-1);
465
                        }
466 84
                }
467
        }
468 567
        if (vpi->e != NULL) {
469 84
                VSL(SLT_ProxyGarbage, req->sp->vxid, "PROXY2: TLV %s", vpi->e);
470 84
                return (-1);
471
        }
472 483
        tlv = WS_Alloc(req->sp->ws, sizeof *tlv + tlv_len);
473 483
        if (tlv == NULL)
474 42
                return (vpx_ws_err(req));
475 441
        INIT_OBJ(tlv, VPX_TLV_MAGIC);
476 441
        tlv->len = tlv_len;
477 441
        vmemcpy(tlv->tlv, tlv_start, tlv_len);
478 441
        if (! SES_Reserve_proxy_tlv(req->sp, &up, &sz))
479 0
                return (vpx_ws_err(req));
480 441
        assert(sz == sizeof up);
481 441
        *up = (uintptr_t)tlv;
482 441
        return (0);
483 1058
}
484
485
/**********************************************************************
486
 * HTC_Rx completion detector
487
 */
488
489
static enum htc_status_e v_matchproto_(htc_complete_f)
490 3779
vpx_complete(struct http_conn *htc)
491
{
492
        size_t z, l;
493
        uint16_t j;
494
        char *p, *q;
495
496 3779
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
497 3779
        AN(WS_Reservation(htc->ws));
498 3779
        assert(pdiff(htc->rxbuf_b, htc->rxbuf_e) <= WS_ReservationSize(htc->ws));
499
500 3779
        l = htc->rxbuf_e - htc->rxbuf_b;
501 3779
        p = htc->rxbuf_b;
502 3779
        j = 0x3;
503 21029
        for (z = 0; z < l; z++) {
504 19149
                if (z < sizeof vpx1_sig && p[z] != vpx1_sig[z])
505 5636
                        j &= ~1;
506 19149
                if (z < sizeof vpx2_sig && p[z] != vpx2_sig[z])
507 4563
                        j &= ~2;
508 19149
                if (j == 0)
509 21
                        return (HTC_S_JUNK);
510 19128
                if (j == 1 && z == sizeof vpx1_sig) {
511 757
                        q = vmemchr(p + z, '\n', htc->rxbuf_e - (p + z));
512 757
                        if (q != NULL && (q - htc->rxbuf_b) > 107)
513 21
                                return (HTC_S_OVERFLOW);
514 736
                        if (q == NULL)
515 21
                                return (HTC_S_MORE);
516 715
                        return (HTC_S_COMPLETE);
517
                }
518 18371
                if (j == 2 && z == sizeof vpx2_sig) {
519 1121
                        if (l < 16)
520 0
                                return (HTC_S_MORE);
521 1121
                        j = vbe16dec(p + 14);
522 1121
                        if (j > VPX_MAX_LEN)
523 42
                                return (HTC_S_OVERFLOW);
524 1079
                        if (l < 16L + j)
525 21
                                return (HTC_S_MORE);
526 1058
                        return (HTC_S_COMPLETE);
527
                }
528 17250
        }
529 1880
        return (HTC_S_MORE);
530 3779
}
531
532
static void v_matchproto_(task_func_t)
533 1878
vpx_new_session(struct worker *wrk, void *arg)
534
{
535
        struct req *req;
536
        struct sess *sp;
537
        enum htc_status_e hs;
538
        char *p;
539
        int i;
540
541 1878
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
542 1878
        CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC);
543 1878
        sp = req->sp;
544 1878
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
545
546
        /* Per specification */
547 1878
        assert(sizeof vpx1_sig == 5);
548 1878
        assert(sizeof vpx2_sig == 12);
549
550 1878
        HTC_RxInit(req->htc, req->ws);
551 3756
        hs = HTC_RxStuff(req->htc, vpx_complete, NULL, NULL, NAN,
552 1878
            sp->t_idle + cache_param->timeout_idle, NAN, VPX_MAX_LEN);
553 1878
        if (hs != HTC_S_COMPLETE) {
554 105
                Req_Release(req);
555 105
                SES_DeleteHS(sp, hs, NAN);
556 105
                return;
557
        }
558 1773
        p = req->htc->rxbuf_b;
559 1773
        if (p[0] == vpx1_sig[0])
560 715
                i = vpx_proto1(wrk, req);
561 1058
        else if (p[0] == vpx2_sig[0])
562 1058
                i = vpx_proto2(wrk, req);
563
        else
564 0
                WRONG("proxy sig mismatch");
565
566 1773
        if (i) {
567 525
                Req_Release(req);
568 525
                SES_Delete(sp, SC_RX_JUNK, NAN);
569 525
                return;
570
        }
571
572 1248
        SES_SetTransport(wrk, sp, req, &HTTP1_transport);
573 1878
}
574
575
struct transport PROXY_transport = {
576
        .name =                 "PROXY",
577
        .proto_ident =          "PROXY",
578
        .magic =                TRANSPORT_MAGIC,
579
        .new_session =          vpx_new_session,
580
};
581
582
static void
583 546
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
584
{
585
        const struct sockaddr_in *sin4;
586
        const struct sockaddr_in6 *sin6;
587
        socklen_t sl;
588
589 546
        if (proto == PF_INET6) {
590 84
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
591 84
                AN(sin6);
592 84
                assert(sl >= sizeof *sin6);
593 84
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
594 84
        } else {
595 462
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
596 462
                AN(sin4);
597 462
                assert(sl >= sizeof *sin4);
598 462
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
599
        }
600 546
}
601
602
static void
603 546
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
604
{
605
        uint8_t b[2];
606
607 546
        vbe16enc(b, (uint16_t)VSA_Port(s));
608 546
        VSB_bcat(vsb, b, sizeof(b));
609 546
}
610
611
static void
612 273
vpx_enc_authority(struct vsb *vsb, const char *authority, size_t l_authority)
613
{
614
        uint16_t l;
615
616 273
        AN(vsb);
617
618 273
        if (l_authority == 0)
619 105
                return;
620 168
        AN(authority);
621 168
        AN(*authority);
622
623 168
        VSB_putc(vsb, PP2_TYPE_AUTHORITY);
624 168
        vbe16enc(&l, l_authority);
625 168
        VSB_bcat(vsb, &l, sizeof(l));
626 168
        VSB_cat(vsb, authority);
627 273
}
628
629
/* short path for stringified addresses from session attributes */
630
static void
631 63
vpx_format_proxy_v1(struct vsb *vsb, int proto,
632
    const char *cip,  const char *cport,
633
    const char *sip,  const char *sport)
634
{
635 63
        AN(vsb);
636 63
        AN(cip);
637 63
        AN(cport);
638 63
        AN(sip);
639 63
        AN(sport);
640
641 63
        VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
642
643 63
        if (proto == PF_INET6)
644 21
                VSB_cat(vsb, " TCP6 ");
645 42
        else if (proto == PF_INET)
646 42
                VSB_cat(vsb, " TCP4 ");
647
        else
648 0
                WRONG("Wrong proxy v1 proto");
649
650 63
        VSB_printf(vsb, "%s %s %s %s\r\n", cip, sip, cport, sport);
651
652 63
        AZ(VSB_finish(vsb));
653 63
}
654
655
static void
656 273
vpx_format_proxy_v2(struct vsb *vsb, int proto,
657
    const struct suckaddr *sac, const struct suckaddr *sas,
658
    const char *authority)
659
{
660 273
        size_t l_authority = 0;
661 273
        uint16_t l_tlv = 0, l;
662
663 273
        AN(vsb);
664 273
        AN(sac);
665 273
        AN(sas);
666
667 273
        if (authority != NULL && *authority != '\0') {
668 168
                l_authority = vstrlen(authority);
669
                /* 3 bytes in the TLV before the authority string */
670 168
                assert(3 + l_authority <= UINT16_MAX);
671 168
                l_tlv = 3 + l_authority;
672 168
        }
673
674 273
        VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
675 273
        VSB_putc(vsb, 0x21);
676 273
        if (proto == PF_INET6) {
677 42
                VSB_putc(vsb, 0x21);
678 42
                vbe16enc(&l, 0x24 + l_tlv);
679 42
                VSB_bcat(vsb, &l, sizeof(l));
680 273
        } else if (proto == PF_INET) {
681 231
                VSB_putc(vsb, 0x11);
682 231
                vbe16enc(&l, 0x0c + l_tlv);
683 231
                VSB_bcat(vsb, &l, sizeof(l));
684 231
        } else {
685 0
                WRONG("Wrong proxy v2 proto");
686
        }
687 273
        vpx_enc_addr(vsb, proto, sac);
688 273
        vpx_enc_addr(vsb, proto, sas);
689 273
        vpx_enc_port(vsb, sac);
690 273
        vpx_enc_port(vsb, sas);
691 273
        vpx_enc_authority(vsb, authority, l_authority);
692 273
        AZ(VSB_finish(vsb));
693 273
}
694
695
void
696 210
VPX_Format_Proxy(struct vsb *vsb, int version,
697
    const struct suckaddr *sac, const struct suckaddr *sas,
698
    const char *authority)
699
{
700
        int proto;
701
        char hac[VTCP_ADDRBUFSIZE];
702
        char pac[VTCP_PORTBUFSIZE];
703
        char has[VTCP_ADDRBUFSIZE];
704
        char pas[VTCP_PORTBUFSIZE];
705
706 210
        AN(vsb);
707 210
        AN(sac);
708 210
        AN(sas);
709
710 210
        assert(version == 1 || version == 2);
711
712 210
        proto = VSA_Get_Proto(sas);
713 210
        assert(proto == VSA_Get_Proto(sac));
714
715 210
        if (version == 1) {
716 21
                VTCP_name(sac, hac, sizeof hac, pac, sizeof pac);
717 21
                VTCP_name(sas, has, sizeof has, pas, sizeof pas);
718 21
                vpx_format_proxy_v1(vsb, proto, hac, pac, has, pas);
719 210
        } else if (version == 2) {
720 189
                vpx_format_proxy_v2(vsb, proto, sac, sas, authority);
721 189
        } else
722 0
                WRONG("Wrong proxy version");
723 210
}
724
725
#define PXY_BUFSZ                                               \
726
        (sizeof(vpx1_sig) + 4 /* TCPx */ +                      \
727
        2 * VTCP_ADDRBUFSIZE + 2 * VTCP_PORTBUFSIZE +           \
728
        6 /* spaces, CRLF */ + 16 /* safety */ )
729
730
int
731 126
VPX_Send_Proxy(int fd, int version, const struct sess *sp)
732
{
733
        struct vsb vsb[1], *vsb2;
734
        struct suckaddr *sac, *sas;
735
        char ha[VTCP_ADDRBUFSIZE];
736
        char pa[VTCP_PORTBUFSIZE];
737
        char buf[PXY_BUFSZ];
738
        int proto, r;
739
740 126
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
741 126
        assert(version == 1 || version == 2);
742 126
        AN(VSB_init(vsb, buf, sizeof buf));
743
744 126
        AZ(SES_Get_server_addr(sp, &sas));
745 126
        AN(sas);
746 126
        proto = VSA_Get_Proto(sas);
747
748 126
        if (version == 1) {
749 42
                VTCP_name(sas, ha, sizeof ha, pa, sizeof pa);
750 84
                vpx_format_proxy_v1(vsb, proto,
751 42
                    SES_Get_String_Attr(sp, SA_CLIENT_IP),
752 42
                    SES_Get_String_Attr(sp, SA_CLIENT_PORT),
753 42
                    ha, pa);
754 126
        } else if (version == 2) {
755 84
                AZ(SES_Get_client_addr(sp, &sac));
756 84
                AN(sac);
757 84
                vpx_format_proxy_v2(vsb, proto, sac, sas, NULL);
758 84
        } else
759 0
                WRONG("Wrong proxy version");
760
761 126
        r = write(fd, VSB_data(vsb), VSB_len(vsb));
762 126
        VTCP_Assert(r);
763
764 126
        if (DO_DEBUG(DBG_PROXY_ERROR)) {
765 21
                errno = EINTR;
766 21
                return (-1);
767
        }
768
769 105
        if (!DO_DEBUG(DBG_PROTOCOL))
770 105
                return (r);
771
772 0
        vsb2 = VSB_new_auto();
773 0
        AN(vsb2);
774 0
        VSB_quote(vsb2, VSB_data(vsb), VSB_len(vsb),
775 0
            version == 2 ? VSB_QUOTE_HEX : 0);
776 0
        AZ(VSB_finish(vsb2));
777 0
        VSL(SLT_Debug, NO_VXID, "PROXY_HDR %s", VSB_data(vsb2));
778 0
        VSB_destroy(&vsb2);
779 0
        VSB_fini(vsb);
780 0
        return (r);
781 126
}
782
783
#undef PXY_BUFSZ