varnish-cache/bin/varnishd/proxy/cache_proxy_proto.c
1
/*-
2
 * Copyright (c) 2015 Varnish Software AS
3
 * Copyright (c) 2018 GANDI SAS
4
 * All rights reserved.
5
 *
6
 * Authors: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *          Emmanuel Hocdet <manu@gandi.net>
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <netinet/in.h>
35
#include <netdb.h>
36
37
#include "cache/cache_varnishd.h"
38
#include "cache/cache_transport.h"
39
#include "proxy/cache_proxy.h"
40
41
#include "vend.h"
42
#include "vsa.h"
43
#include "vtcp.h"
44
45
struct vpx_tlv {
46
        unsigned                magic;
47
#define VPX_TLV_MAGIC           0xdeb9a4a5
48
        unsigned                len;
49
        char                    tlv[1];
50
};
51
52
/**********************************************************************
53
 * PROXY 1 protocol
54
 */
55
56
static const char vpx1_sig[] = {'P', 'R', 'O', 'X', 'Y'};
57
58
static int
59 68
vpx_proto1(const struct worker *wrk, const struct req *req)
60
{
61
        const char *fld[5];
62
        int i;
63
        char *p, *q;
64
        struct addrinfo hints, *res;
65
        struct suckaddr *sa;
66 68
        int pfam = -1;
67
68 68
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
69 68
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
70 68
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
71
72 68
        q = memchr(req->htc->rxbuf_b, '\r',
73 68
            req->htc->rxbuf_e - req->htc->rxbuf_b);
74 68
        if (q == NULL)
75 2
                return (-1);
76
77 66
        *q++ = '\0';
78
        /* Nuke the CRLF */
79 66
        if (q == req->htc->rxbuf_e || *q != '\n')
80 0
                return (-1);
81 66
        *q++ = '\0';
82
83
        /* Split the fields */
84 66
        p = req->htc->rxbuf_b;
85 394
        for (i = 0; i < 5; i++) {
86 330
                p = strchr(p, ' ');
87 330
                if (p == NULL) {
88 2
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
89
                            "PROXY1: Too few fields");
90 2
                        return (-1);
91
                }
92 328
                *p++ = '\0';
93 328
                fld[i] = p;
94
        }
95
96 64
        if (strchr(p, ' ')) {
97 6
                VSL(SLT_ProxyGarbage, req->sp->vxid,
98
                    "PROXY1: Too many fields");
99 6
                return (-1);
100
        }
101
102 58
        if (!strcmp(fld[0], "TCP4"))
103 34
                pfam = AF_INET;
104 24
        else if (!strcmp(fld[0], "TCP6"))
105 22
                pfam = AF_INET6;
106
        else {
107 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
108
                    "PROXY1: Wrong TCP[46] field");
109 2
                return (-1);
110
        }
111
112 56
        memset(&hints, 0, sizeof hints);
113 56
        hints.ai_socktype = SOCK_STREAM;
114 56
        hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
115
116 56
        i = getaddrinfo(fld[1], fld[3], &hints, &res);
117 56
        if (i != 0) {
118 10
                VSL(SLT_ProxyGarbage, req->sp->vxid,
119
                    "PROXY1: Cannot resolve source address (%s)",
120
                    gai_strerror(i));
121 10
                return (-1);
122
        }
123 46
        AZ(res->ai_next);
124 46
        if (res->ai_family != pfam) {
125 4
                VSL(SLT_ProxyGarbage, req->sp->vxid,
126
                    "PROXY1: %s got wrong protocol (%d)",
127 4
                    fld[0], res->ai_family);
128 4
                freeaddrinfo(res);
129 4
                return (-1);
130
        }
131 42
        SES_Reserve_client_addr(req->sp, &sa);
132 42
        AN(VSA_Build(sa, res->ai_addr, res->ai_addrlen));
133 42
        SES_Set_String_Attr(req->sp, SA_CLIENT_IP, fld[1]);
134 42
        SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, fld[3]);
135 42
        freeaddrinfo(res);
136
137 42
        i = getaddrinfo(fld[2], fld[4], &hints, &res);
138 42
        if (i != 0) {
139 6
                VSL(SLT_ProxyGarbage, req->sp->vxid,
140
                    "PROXY1: Cannot resolve destination address (%s)",
141
                    gai_strerror(i));
142 6
                return (-1);
143
        }
144 36
        AZ(res->ai_next);
145 36
        if (res->ai_family != pfam) {
146 0
                VSL(SLT_ProxyGarbage, req->sp->vxid,
147
                    "PROXY1: %s got wrong protocol (%d)",
148 0
                    fld[0], res->ai_family);
149 0
                freeaddrinfo(res);
150 0
                return (-1);
151
        }
152 36
        SES_Reserve_server_addr(req->sp, &sa);
153 36
        AN(VSA_Build(sa, res->ai_addr, res->ai_addrlen));
154 36
        freeaddrinfo(res);
155
156 36
        VSL(SLT_Proxy, req->sp->vxid, "1 %s %s %s %s",
157
            fld[1], fld[3], fld[2], fld[4]);
158 36
        HTC_RxPipeline(req->htc, q);
159 36
        WS_Reset(req->htc->ws, 0);
160 36
        return (0);
161
}
162
163
/**********************************************************************
164
 * PROXY 2 protocol
165
 */
166
167
static const char vpx2_sig[] = {
168
        '\r', '\n', '\r', '\n', '\0', '\r', '\n',
169
        'Q', 'U', 'I', 'T', '\n',
170
};
171
172
static const uint32_t crctable[256] = {
173
        0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
174
        0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
175
        0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
176
        0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
177
        0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
178
        0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
179
        0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
180
        0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
181
        0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
182
        0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
183
        0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
184
        0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
185
        0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
186
        0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
187
        0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
188
        0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
189
        0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
190
        0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
191
        0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
192
        0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
193
        0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
194
        0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
195
        0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
196
        0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
197
        0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
198
        0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
199
        0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
200
        0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
201
        0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
202
        0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
203
        0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
204
        0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
205
        0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
206
        0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
207
        0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
208
        0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
209
        0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
210
        0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
211
        0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
212
        0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
213
        0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
214
        0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
215
        0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
216
        0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
217
        0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
218
        0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
219
        0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
220
        0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
221
        0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
222
        0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
223
        0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
224
        0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
225
        0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
226
        0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
227
        0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
228
        0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
229
        0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
230
        0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
231
        0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
232
        0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
233
        0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
234
        0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
235
        0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
236
        0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
237
};
238
239 6
static uint32_t crc32c(const uint8_t *buf, int len)
240
{
241 6
        uint32_t crc = 0xffffffff;
242 1094
        while (len-- > 0) {
243 1082
                crc = (crc >> 8) ^ crctable[(crc ^ (*buf++)) & 0xff];
244
        }
245 6
        return (crc ^ 0xffffffff);
246
}
247
248
struct vpx_tlv_iter {
249
        uint8_t         t;
250
        void            *p;
251
        uint16_t        l;
252
        const char      *e;
253
254
        unsigned char   *_p;
255
        uint16_t        _l;
256
};
257
258
static void
259 64
vpx_tlv_iter0(struct vpx_tlv_iter *vpi, void *p, unsigned l)
260
{
261
262 64
        AN(p);
263 64
        assert(l < 65536);
264 64
        memset(vpi, 0, sizeof *vpi);
265 64
        vpi->_p = p;
266 64
        vpi->_l = l;
267 64
}
268
269
static int
270 214
vpx_tlv_itern(struct vpx_tlv_iter *vpi)
271
{
272 214
        if (vpi->_l == 0 || vpi->e != NULL)
273 28
                return (0);
274 186
        if (vpi->_l < 3) {
275 2
                vpi->e = "Dribble bytes";
276 2
                return (0);
277
        }
278 184
        vpi->t = *vpi->_p;
279 184
        vpi->l = vbe16dec(vpi->_p + 1);
280 184
        if (vpi->l + 3 > vpi->_l) {
281 4
                vpi->e = "Length Error";
282 4
                return (0);
283
        }
284 180
        vpi->p = vpi->_p + 3;
285 180
        vpi->_p += 3 + vpi->l;
286 180
        vpi->_l -= 3 + vpi->l;
287 180
        return (1);
288
}
289
290
#define VPX_TLV_FOREACH(ptr, len, itv) \
291
        for(vpx_tlv_iter0(itv, ptr, len); vpx_tlv_itern(itv);)
292
293
int
294 22
VPX_tlv(const struct req *req, int typ, void **dst, int *len)
295
{
296
        struct vpx_tlv *tlv;
297
        struct vpx_tlv_iter vpi[1], vpi2[1];
298
        uintptr_t *up;
299
300 22
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
301 22
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
302 22
        AN(dst);
303 22
        AN(len);
304 22
        *dst = NULL;
305 22
        *len = 0;
306
307 22
        if (SES_Get_proxy_tlv(req->sp, &up) != 0 || *up == 0)
308 0
                return (-1);
309 22
        CAST_OBJ_NOTNULL(tlv, (void*)(*up), VPX_TLV_MAGIC);
310
311 106
        VPX_TLV_FOREACH(tlv->tlv, tlv->len, vpi) {
312 82
                if (vpi->t == typ) {
313 12
                        *dst = vpi->p;
314 12
                        *len = vpi->l;
315 12
                        return (0);
316
                }
317 70
                if (vpi->t != PP2_TYPE_SSL)
318 60
                        continue;
319 40
                VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
320 28
                        if (vpi2->t == typ) {
321 8
                                *dst = vpi2->p;
322 8
                                *len = vpi2->l;
323 8
                                return (0);
324
                        }
325
                }
326
        }
327 2
        return (-1);
328
}
329
330
static int
331 62
vpx_proto2(const struct worker *wrk, struct req *req)
332
{
333
        int l, hdr_len;
334
        uintptr_t *up;
335
        uint16_t tlv_len;
336
        const uint8_t *p;
337
        char *d, *tlv_start;
338 62
        sa_family_t pfam = 0xff;
339
        struct sockaddr_in sin4;
340
        struct sockaddr_in6 sin6;
341 62
        struct suckaddr *sa = NULL;
342
        char ha[VTCP_ADDRBUFSIZE];
343
        char pa[VTCP_PORTBUFSIZE];
344
        char hb[VTCP_ADDRBUFSIZE];
345
        char pb[VTCP_PORTBUFSIZE];
346
        struct vpx_tlv_iter vpi[1], vpi2[1];
347
        struct vpx_tlv *tlv;
348
349 62
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
350 62
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
351 62
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
352
353 62
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= 16L);
354 62
        l = vbe16dec(req->htc->rxbuf_b + 14);
355 62
        hdr_len = l + 16L;
356 62
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= hdr_len);
357 62
        HTC_RxPipeline(req->htc, req->htc->rxbuf_b + hdr_len);
358 62
        WS_Reset(req->ws, 0);
359 62
        p = (const void *)req->htc->rxbuf_b;
360 62
        d = req->htc->rxbuf_b + 16L;
361
362
        /* Version @12 top half */
363 62
        if ((p[12] >> 4) != 2) {
364 0
                VSL(SLT_ProxyGarbage, req->sp->vxid,
365 0
                    "PROXY2: bad version (%d)", p[12] >> 4);
366 0
                return (-1);
367
        }
368
369
        /* Command @12 bottom half */
370 62
        switch (p[12] & 0x0f) {
371
        case 0x0:
372 26
                VSL(SLT_Proxy, req->sp->vxid, "2 local local local local");
373 26
                return (0);
374
        case 0x1:
375
                /* Proxied connection */
376 34
                break;
377
        default:
378 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
379 2
                    "PROXY2: bad command (%d)", p[12] & 0x0f);
380 2
                return (-1);
381
        }
382
383
        /* Address family & protocol @13 */
384 34
        switch (p[13]) {
385
        case 0x00:
386
                /* UNSPEC|UNSPEC, ignore proxy header */
387 4
                VSL(SLT_ProxyGarbage, req->sp->vxid,
388
                    "PROXY2: Ignoring UNSPEC|UNSPEC addresses");
389 4
                return (0);
390
        case 0x11:
391
                /* IPv4|TCP */
392 20
                pfam = AF_INET;
393 20
                if (l < 12) {
394 2
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
395
                            "PROXY2: Ignoring short IPv4 addresses (%d)", l);
396 2
                        return (0);
397
                }
398 18
                l -= 12;
399 18
                d += 12;
400 18
                memset(&sin4, 0, sizeof sin4);
401 18
                sin4.sin_family = pfam;
402
403
                /* dst/server */
404 18
                memcpy(&sin4.sin_addr, p + 20, 4);
405 18
                memcpy(&sin4.sin_port, p + 26, 2);
406 18
                SES_Reserve_server_addr(req->sp, &sa);
407 18
                AN(VSA_Build(sa, &sin4, sizeof sin4));
408 18
                VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
409
410
                /* src/client */
411 18
                memcpy(&sin4.sin_addr, p + 16, 4);
412 18
                memcpy(&sin4.sin_port, p + 24, 2);
413 18
                SES_Reserve_client_addr(req->sp, &sa);
414 18
                AN(VSA_Build(sa, &sin4, sizeof sin4));
415 18
                break;
416
        case 0x21:
417
                /* IPv6|TCP */
418 8
                pfam = AF_INET6;
419 8
                if (l < 36) {
420 2
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
421
                            "PROXY2: Ignoring short IPv6 addresses (%d)", l);
422 2
                        return (0);
423
                }
424 6
                l -= 36;
425 6
                d += 36;
426 6
                memset(&sin6, 0, sizeof sin6);
427 6
                sin6.sin6_family = pfam;
428
429
                /* dst/server */
430 6
                memcpy(&sin6.sin6_addr, p + 32, 16);
431 6
                memcpy(&sin6.sin6_port, p + 50, 2);
432 6
                SES_Reserve_server_addr(req->sp, &sa);
433 6
                AN(VSA_Build(sa, &sin6, sizeof sin6));
434 6
                VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
435
436
                /* src/client */
437 6
                memcpy(&sin6.sin6_addr, p + 16, 16);
438 6
                memcpy(&sin6.sin6_port, p + 48, 2);
439 6
                SES_Reserve_client_addr(req->sp, &sa);
440 6
                AN(VSA_Build(sa, &sin6, sizeof sin6));
441 6
                break;
442
        default:
443
                /* Ignore proxy header */
444 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
445 2
                    "PROXY2: Ignoring unsupported protocol (0x%02x)", p[13]);
446 2
                return (0);
447
        }
448
449 24
        AN(sa);
450 24
        VTCP_name(sa, hb, sizeof hb, pb, sizeof pb);
451 24
        SES_Set_String_Attr(req->sp, SA_CLIENT_IP, hb);
452 24
        SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, pb);
453
454 24
        VSL(SLT_Proxy, req->sp->vxid, "2 %s %s %s %s", hb, pb, ha, pa);
455
456 24
        tlv_start = d;
457 24
        tlv_len = l;
458
459 86
        VPX_TLV_FOREACH(d, l, vpi) {
460 40
                if (vpi->t == PP2_TYPE_SSL) {
461 8
                        VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
462
                        }
463 8
                        vpi->e = vpi2->e;
464 32
                } else if (vpi->t == PP2_TYPE_CRC32C) {
465 6
                        uint32_t n_crc32c = vbe32dec(vpi->p);
466 6
                        vbe32enc(vpi->p, 0);
467 6
                        if (crc32c(p, hdr_len) != n_crc32c) {
468 2
                                VSL(SLT_ProxyGarbage, req->sp->vxid,
469
                                    "PROXY2: CRC error");
470 2
                                return (-1);
471
                        }
472
                }
473
        }
474 22
        if (vpi->e != NULL) {
475 6
                VSL(SLT_ProxyGarbage, req->sp->vxid, "PROXY2: TLV %s", vpi->e);
476 6
                return (-1);
477
        }
478 16
        tlv = WS_Alloc(req->sp->ws, sizeof *tlv + tlv_len);
479 16
        if (tlv == NULL) {
480 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
481
                    "PROXY2: TLV overflows WS");
482 2
                return (-1);
483
        }
484 14
        INIT_OBJ(tlv, VPX_TLV_MAGIC);
485 14
        tlv->len = tlv_len;
486 14
        memcpy(tlv->tlv, tlv_start, tlv_len);
487 14
        SES_Reserve_proxy_tlv(req->sp, &up);
488 14
        *up = (uintptr_t)tlv;
489 14
        return (0);
490
}
491
492
/**********************************************************************
493
 * HTC_Rx completion detector
494
 */
495
496
static enum htc_status_e v_matchproto_(htc_complete_f)
497 284
vpx_complete(struct http_conn *htc)
498
{
499
        int i, l, j;
500
        char *p, *q;
501
502 284
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
503
504 284
        assert(htc->rxbuf_e >= htc->rxbuf_b);
505 284
        assert(htc->rxbuf_e <= htc->ws->r);
506
507 284
        l = htc->rxbuf_e - htc->rxbuf_b;
508 284
        p = htc->rxbuf_b;
509 284
        j = 0x3;
510 1518
        for (i = 0; i < l; i++) {
511 1379
                if (i < sizeof vpx1_sig && p[i] != vpx1_sig[i])
512 362
                        j &= ~1;
513 1379
                if (i < sizeof vpx2_sig && p[i] != vpx2_sig[i])
514 446
                        j &= ~2;
515 1379
                if (j == 0)
516 2
                        return (HTC_S_JUNK);
517 1377
                if (j == 1 && i == sizeof vpx1_sig) {
518 74
                        q = memchr(p + i, '\n', htc->rxbuf_e - (p + i));
519 74
                        if (q != NULL && (q - htc->rxbuf_b) > 107)
520 2
                                return (HTC_S_OVERFLOW);
521 72
                        if (q == NULL)
522 4
                                return (HTC_S_MORE);
523 68
                        return (HTC_S_COMPLETE);
524
                }
525 1303
                if (j == 2 && i == sizeof vpx2_sig) {
526 69
                        if (l < 16)
527 0
                                return (HTC_S_MORE);
528 69
                        j = vbe16dec(p + 14);
529 69
                        if (l < 16 + j)
530 7
                                return (HTC_S_MORE);
531 62
                        return (HTC_S_COMPLETE);
532
                }
533
        }
534 139
        return (HTC_S_MORE);
535
}
536
537
static void v_matchproto_(task_func_t)
538 136
vpx_new_session(struct worker *wrk, void *arg)
539
{
540
        struct req *req;
541
        struct sess *sp;
542
        enum htc_status_e hs;
543
        char *p;
544
        int i;
545
546 136
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
547 136
        CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC);
548 136
        sp = req->sp;
549 136
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
550
551
        /* Per specification */
552
        assert(sizeof vpx1_sig == 5);
553
        assert(sizeof vpx2_sig == 12);
554
555 136
        HTC_RxInit(req->htc, req->ws);
556 136
        hs = HTC_RxStuff(req->htc, vpx_complete,
557 136
            NULL, NULL, NAN, sp->t_idle + cache_param->timeout_idle,
558
            1024);                      // XXX ?
559 136
        if (hs != HTC_S_COMPLETE) {
560 6
                Req_Release(req);
561 6
                SES_Delete(sp, SC_RX_JUNK, NAN);
562 6
                return;
563
        }
564 130
        p = req->htc->rxbuf_b;
565 130
        if (p[0] == vpx1_sig[0])
566 68
                i = vpx_proto1(wrk, req);
567 62
        else if (p[0] == vpx2_sig[0])
568 62
                i = vpx_proto2(wrk, req);
569
        else
570 0
                WRONG("proxy sig mismatch");
571
572 130
        if (i) {
573 44
                Req_Release(req);
574 44
                SES_Delete(sp, SC_RX_JUNK, NAN);
575 44
                return;
576
        }
577
578 86
        SES_SetTransport(wrk, sp, req, &HTTP1_transport);
579
}
580
581
struct transport PROXY_transport = {
582
        .name =                 "PROXY",
583
        .proto_ident =          "PROXY",
584
        .magic =                TRANSPORT_MAGIC,
585
        .new_session =          vpx_new_session,
586
};
587
588
static void
589 12
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
590
{
591
        const struct sockaddr_in *sin4;
592
        const struct sockaddr_in6 *sin6;
593
        socklen_t sl;
594
595 12
        if (proto == PF_INET6) {
596 8
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
597 8
                AN(sin6);
598 8
                assert(sl >= sizeof *sin6);
599 8
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
600
        } else {
601 4
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
602 4
                AN(sin4);
603 4
                assert(sl >= sizeof *sin4);
604 4
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
605
        }
606 12
}
607
608
static void
609 12
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
610
{
611
        uint8_t b[2];
612
613 12
        vbe16enc(b, (uint16_t)VSA_Port(s));
614 12
        VSB_bcat(vsb, b, sizeof(b));
615 12
}
616
617
void
618 10
VPX_Send_Proxy(int fd, int version, const struct sess *sp)
619
{
620
        struct vsb *vsb, *vsb2;
621
        const char *p1, *p2;
622
        struct suckaddr *sac, *sas;
623
        char ha[VTCP_ADDRBUFSIZE];
624
        char pa[VTCP_PORTBUFSIZE];
625
        int proto;
626
627 10
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
628 10
        assert(version == 1 || version == 2);
629 10
        vsb = VSB_new_auto();
630 10
        AN(vsb);
631
632 10
        AZ(SES_Get_server_addr(sp, &sas));
633 10
        AN(sas);
634 10
        proto = VSA_Get_Proto(sas);
635 10
        assert(proto == PF_INET6 || proto == PF_INET);
636
637 10
        if (version == 1) {
638 4
                VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
639 4
                p1 = SES_Get_String_Attr(sp, SA_CLIENT_IP);
640 4
                AN(p1);
641 4
                p2 = SES_Get_String_Attr(sp, SA_CLIENT_PORT);
642 4
                AN(p2);
643 4
                VTCP_name(sas, ha, sizeof ha, pa, sizeof pa);
644 4
                if (proto == PF_INET6)
645 2
                        VSB_printf(vsb, " TCP6 ");
646 2
                else if (proto == PF_INET)
647 2
                        VSB_printf(vsb, " TCP4 ");
648 4
                VSB_printf(vsb, "%s %s %s %s\r\n", p1, ha, p2, pa);
649 6
        } else if (version == 2) {
650 6
                AZ(SES_Get_client_addr(sp, &sac));
651 6
                AN(sac);
652
653 6
                VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
654 6
                VSB_putc(vsb, 0x21);
655 6
                if (proto == PF_INET6) {
656 4
                        VSB_putc(vsb, 0x21);
657 4
                        VSB_putc(vsb, 0x00);
658 4
                        VSB_putc(vsb, 0x24);
659 2
                } else if (proto == PF_INET) {
660 2
                        VSB_putc(vsb, 0x11);
661 2
                        VSB_putc(vsb, 0x00);
662 2
                        VSB_putc(vsb, 0x0c);
663
                }
664 6
                vpx_enc_addr(vsb, proto, sac);
665 6
                vpx_enc_addr(vsb, proto, sas);
666 6
                vpx_enc_port(vsb, sac);
667 6
                vpx_enc_port(vsb, sas);
668
        } else
669 0
                WRONG("Wrong proxy version");
670
671 10
        AZ(VSB_finish(vsb));
672 10
        (void)write(fd, VSB_data(vsb), VSB_len(vsb));
673 10
        if (!DO_DEBUG(DBG_PROTOCOL)) {
674 10
                VSB_delete(vsb);
675 10
                return;
676
        }
677
678 0
        vsb2 = VSB_new_auto();
679 0
        AN(vsb2);
680 0
        VSB_quote(vsb2, VSB_data(vsb), VSB_len(vsb),
681
            version == 2 ? VSB_QUOTE_HEX : 0);
682 0
        AZ(VSB_finish(vsb2));
683 0
        VSL(SLT_Debug, 999, "PROXY_HDR %s", VSB_data(vsb2));
684 0
        VSB_delete(vsb);
685 0
        VSB_delete(vsb2);
686
}