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 34
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 34
        int pfam = -1;
67
68 34
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
69 34
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
70 34
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
71
72 34
        q = memchr(req->htc->rxbuf_b, '\r',
73 34
            req->htc->rxbuf_e - req->htc->rxbuf_b);
74 34
        if (q == NULL)
75 1
                return (-1);
76
77 33
        *q++ = '\0';
78
        /* Nuke the CRLF */
79 33
        if (q == req->htc->rxbuf_e || *q != '\n')
80 0
                return (-1);
81 33
        *q++ = '\0';
82
83
        /* Split the fields */
84 33
        p = req->htc->rxbuf_b;
85 197
        for (i = 0; i < 5; i++) {
86 165
                p = strchr(p, ' ');
87 165
                if (p == NULL) {
88 1
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
89
                            "PROXY1: Too few fields");
90 1
                        return (-1);
91
                }
92 164
                *p++ = '\0';
93 164
                fld[i] = p;
94
        }
95
96 32
        if (strchr(p, ' ')) {
97 3
                VSL(SLT_ProxyGarbage, req->sp->vxid,
98
                    "PROXY1: Too many fields");
99 3
                return (-1);
100
        }
101
102 29
        if (!strcmp(fld[0], "TCP4"))
103 17
                pfam = AF_INET;
104 12
        else if (!strcmp(fld[0], "TCP6"))
105 11
                pfam = AF_INET6;
106
        else {
107 1
                VSL(SLT_ProxyGarbage, req->sp->vxid,
108
                    "PROXY1: Wrong TCP[46] field");
109 1
                return (-1);
110
        }
111
112 28
        memset(&hints, 0, sizeof hints);
113 28
        hints.ai_socktype = SOCK_STREAM;
114 28
        hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
115
116 28
        i = getaddrinfo(fld[1], fld[3], &hints, &res);
117 28
        if (i != 0) {
118 5
                VSL(SLT_ProxyGarbage, req->sp->vxid,
119
                    "PROXY1: Cannot resolve source address (%s)",
120
                    gai_strerror(i));
121 5
                return (-1);
122
        }
123 23
        AZ(res->ai_next);
124 23
        if (res->ai_family != pfam) {
125 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
126
                    "PROXY1: %s got wrong protocol (%d)",
127 2
                    fld[0], res->ai_family);
128 2
                freeaddrinfo(res);
129 2
                return (-1);
130
        }
131 21
        SES_Reserve_client_addr(req->sp, &sa);
132 21
        AN(VSA_Build(sa, res->ai_addr, res->ai_addrlen));
133 21
        SES_Set_String_Attr(req->sp, SA_CLIENT_IP, fld[1]);
134 21
        SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, fld[3]);
135 21
        freeaddrinfo(res);
136
137 21
        i = getaddrinfo(fld[2], fld[4], &hints, &res);
138 21
        if (i != 0) {
139 3
                VSL(SLT_ProxyGarbage, req->sp->vxid,
140
                    "PROXY1: Cannot resolve destination address (%s)",
141
                    gai_strerror(i));
142 3
                return (-1);
143
        }
144 18
        AZ(res->ai_next);
145 18
        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 18
        SES_Reserve_server_addr(req->sp, &sa);
153 18
        AN(VSA_Build(sa, res->ai_addr, res->ai_addrlen));
154 18
        freeaddrinfo(res);
155
156 18
        VSL(SLT_Proxy, req->sp->vxid, "1 %s %s %s %s",
157
            fld[1], fld[3], fld[2], fld[4]);
158 18
        HTC_RxPipeline(req->htc, q);
159 18
        WS_Reset(req->htc->ws, 0);
160 18
        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 2
static uint32_t crc32c(const uint8_t *buf, int len)
240
{
241 2
        uint32_t crc = 0xffffffff;
242 238
        while (len-- > 0) {
243 234
                crc = (crc >> 8) ^ crctable[(crc ^ (*buf++)) & 0xff];
244
        }
245 2
        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 30
vpx_tlv_iter0(struct vpx_tlv_iter *vpi, void *p, unsigned l)
260
{
261
262 30
        AN(p);
263 30
        assert(l < 65536);
264 30
        memset(vpi, 0, sizeof *vpi);
265 30
        vpi->_p = p;
266 30
        vpi->_l = l;
267 30
}
268
269
static int
270 97
vpx_tlv_itern(struct vpx_tlv_iter *vpi)
271
{
272 97
        if (vpi->_l == 0 || vpi->e != NULL)
273 12
                return (0);
274 85
        if (vpi->_l < 3) {
275 1
                vpi->e = "Dribble bytes";
276 1
                return (0);
277
        }
278 84
        vpi->t = *vpi->_p;
279 84
        vpi->l = vbe16dec(vpi->_p + 1);
280 84
        if (vpi->l + 3 > vpi->_l) {
281 2
                vpi->e = "Length Error";
282 2
                return (0);
283
        }
284 82
        vpi->p = vpi->_p + 3;
285 82
        vpi->_p += 3 + vpi->l;
286 82
        vpi->_l -= 3 + vpi->l;
287 82
        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 11
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 11
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
301 11
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
302 11
        AN(dst);
303 11
        AN(len);
304 11
        *dst = NULL;
305 11
        *len = 0;
306
307 11
        if (SES_Get_proxy_tlv(req->sp, &up) != 0 || *up == 0)
308 0
                return (-1);
309 11
        CAST_OBJ_NOTNULL(tlv, (void*)(*up), VPX_TLV_MAGIC);
310
311 53
        VPX_TLV_FOREACH(tlv->tlv, tlv->len, vpi) {
312 41
                if (vpi->t == typ) {
313 6
                        *dst = vpi->p;
314 6
                        *len = vpi->l;
315 6
                        return (0);
316
                }
317 35
                if (vpi->t != PP2_TYPE_SSL)
318 30
                        continue;
319 20
                VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
320 14
                        if (vpi2->t == typ) {
321 4
                                *dst = vpi2->p;
322 4
                                *len = vpi2->l;
323 4
                                return (0);
324
                        }
325
                }
326
        }
327 1
        return (-1);
328
}
329
330
static int
331 30
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 30
        sa_family_t pfam = 0xff;
339
        struct sockaddr_in sin4;
340
        struct sockaddr_in6 sin6;
341 30
        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 30
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
350 30
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
351 30
        CHECK_OBJ_NOTNULL(req->sp, SESS_MAGIC);
352
353 30
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= 16L);
354 30
        l = vbe16dec(req->htc->rxbuf_b + 14);
355 30
        hdr_len = l + 16L;
356 30
        assert(req->htc->rxbuf_e - req->htc->rxbuf_b >= hdr_len);
357 30
        HTC_RxPipeline(req->htc, req->htc->rxbuf_b + hdr_len);
358 30
        WS_Reset(req->ws, 0);
359 30
        p = (const void *)req->htc->rxbuf_b;
360 30
        d = req->htc->rxbuf_b + 16L;
361
362
        /* Version @12 top half */
363 30
        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 30
        switch (p[12] & 0x0f) {
371
        case 0x0:
372 13
                VSL(SLT_Proxy, req->sp->vxid, "2 local local local local");
373 13
                return (0);
374
        case 0x1:
375
                /* Proxied connection */
376 16
                break;
377
        default:
378 1
                VSL(SLT_ProxyGarbage, req->sp->vxid,
379 1
                    "PROXY2: bad command (%d)", p[12] & 0x0f);
380 1
                return (-1);
381
        }
382
383
        /* Address family & protocol @13 */
384 16
        switch (p[13]) {
385
        case 0x00:
386
                /* UNSPEC|UNSPEC, ignore proxy header */
387 2
                VSL(SLT_ProxyGarbage, req->sp->vxid,
388
                    "PROXY2: Ignoring UNSPEC|UNSPEC addresses");
389 2
                return (0);
390
        case 0x11:
391
                /* IPv4|TCP */
392 9
                pfam = AF_INET;
393 9
                if (l < 12) {
394 1
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
395
                            "PROXY2: Ignoring short IPv4 addresses (%d)", l);
396 1
                        return (0);
397
                }
398 8
                l -= 12;
399 8
                d += 12;
400 8
                memset(&sin4, 0, sizeof sin4);
401 8
                sin4.sin_family = pfam;
402
403
                /* dst/server */
404 8
                memcpy(&sin4.sin_addr, p + 20, 4);
405 8
                memcpy(&sin4.sin_port, p + 26, 2);
406 8
                SES_Reserve_server_addr(req->sp, &sa);
407 8
                AN(VSA_Build(sa, &sin4, sizeof sin4));
408 8
                VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
409
410
                /* src/client */
411 8
                memcpy(&sin4.sin_addr, p + 16, 4);
412 8
                memcpy(&sin4.sin_port, p + 24, 2);
413 8
                SES_Reserve_client_addr(req->sp, &sa);
414 8
                AN(VSA_Build(sa, &sin4, sizeof sin4));
415 8
                break;
416
        case 0x21:
417
                /* IPv6|TCP */
418 4
                pfam = AF_INET6;
419 4
                if (l < 36) {
420 1
                        VSL(SLT_ProxyGarbage, req->sp->vxid,
421
                            "PROXY2: Ignoring short IPv6 addresses (%d)", l);
422 1
                        return (0);
423
                }
424 3
                l -= 36;
425 3
                d += 36;
426 3
                memset(&sin6, 0, sizeof sin6);
427 3
                sin6.sin6_family = pfam;
428
429
                /* dst/server */
430 3
                memcpy(&sin6.sin6_addr, p + 32, 16);
431 3
                memcpy(&sin6.sin6_port, p + 50, 2);
432 3
                SES_Reserve_server_addr(req->sp, &sa);
433 3
                AN(VSA_Build(sa, &sin6, sizeof sin6));
434 3
                VTCP_name(sa, ha, sizeof ha, pa, sizeof pa);
435
436
                /* src/client */
437 3
                memcpy(&sin6.sin6_addr, p + 16, 16);
438 3
                memcpy(&sin6.sin6_port, p + 48, 2);
439 3
                SES_Reserve_client_addr(req->sp, &sa);
440 3
                AN(VSA_Build(sa, &sin6, sizeof sin6));
441 3
                break;
442
        default:
443
                /* Ignore proxy header */
444 1
                VSL(SLT_ProxyGarbage, req->sp->vxid,
445 1
                    "PROXY2: Ignoring unsupported protocol (0x%02x)", p[13]);
446 1
                return (0);
447
        }
448
449 11
        AN(sa);
450 11
        VTCP_name(sa, hb, sizeof hb, pb, sizeof pb);
451 11
        SES_Set_String_Attr(req->sp, SA_CLIENT_IP, hb);
452 11
        SES_Set_String_Attr(req->sp, SA_CLIENT_PORT, pb);
453
454 11
        VSL(SLT_Proxy, req->sp->vxid, "2 %s %s %s %s", hb, pb, ha, pa);
455
456 11
        tlv_start = d;
457 11
        tlv_len = l;
458
459 37
        VPX_TLV_FOREACH(d, l, vpi) {
460 16
                if (vpi->t == PP2_TYPE_SSL) {
461 3
                        VPX_TLV_FOREACH((char*)vpi->p + 5, vpi->l - 5, vpi2) {
462
                        }
463 3
                        vpi->e = vpi2->e;
464 13
                } else if (vpi->t == PP2_TYPE_CRC32C) {
465 2
                        uint32_t n_crc32c = vbe32dec(vpi->p);
466 2
                        vbe32enc(vpi->p, 0);
467 2
                        if (crc32c(p, hdr_len) != n_crc32c) {
468 1
                                VSL(SLT_ProxyGarbage, req->sp->vxid,
469
                                    "PROXY2: CRC error");
470 1
                                return (-1);
471
                        }
472
                }
473
        }
474 10
        if (vpi->e != NULL) {
475 3
                VSL(SLT_ProxyGarbage, req->sp->vxid, "PROXY2: TLV %s", vpi->e);
476 3
                return (-1);
477
        }
478 7
        tlv = WS_Alloc(req->sp->ws, sizeof *tlv + tlv_len);
479 7
        if (tlv == NULL) {
480 0
                VSL(SLT_ProxyGarbage, req->sp->vxid,
481
                    "PROXY2: TLV overflows WS");
482 0
                return (-1);
483
        }
484 7
        INIT_OBJ(tlv, VPX_TLV_MAGIC);
485 7
        tlv->len = tlv_len;
486 7
        memcpy(tlv->tlv, tlv_start, tlv_len);
487 7
        SES_Reserve_proxy_tlv(req->sp, &up);
488 7
        *up = (uintptr_t)tlv;
489 7
        return (0);
490
}
491
492
/**********************************************************************
493
 * HTC_Rx completion detector
494
 */
495
496
static enum htc_status_e v_matchproto_(htc_complete_f)
497 139
vpx_complete(struct http_conn *htc)
498
{
499
        int i, l, j;
500
        char *p, *q;
501
502 139
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
503
504 139
        assert(htc->rxbuf_e >= htc->rxbuf_b);
505 139
        assert(htc->rxbuf_e <= htc->ws->r);
506
507 139
        l = htc->rxbuf_e - htc->rxbuf_b;
508 139
        p = htc->rxbuf_b;
509 139
        j = 0x3;
510 732
        for (i = 0; i < l; i++) {
511 665
                if (i < sizeof vpx1_sig && p[i] != vpx1_sig[i])
512 171
                        j &= ~1;
513 665
                if (i < sizeof vpx2_sig && p[i] != vpx2_sig[i])
514 223
                        j &= ~2;
515 665
                if (j == 0)
516 1
                        return (HTC_S_JUNK);
517 664
                if (j == 1 && i == sizeof vpx1_sig) {
518 37
                        q = memchr(p + i, '\n', htc->rxbuf_e - (p + i));
519 37
                        if (q != NULL && (q - htc->rxbuf_b) > 107)
520 1
                                return (HTC_S_OVERFLOW);
521 36
                        if (q == NULL)
522 2
                                return (HTC_S_MORE);
523 34
                        return (HTC_S_COMPLETE);
524
                }
525 627
                if (j == 2 && i == sizeof vpx2_sig) {
526 34
                        if (l < 16)
527 0
                                return (HTC_S_MORE);
528 34
                        j = vbe16dec(p + 14);
529 34
                        if (l < 16 + j)
530 4
                                return (HTC_S_MORE);
531 30
                        return (HTC_S_COMPLETE);
532
                }
533
        }
534 67
        return (HTC_S_MORE);
535
}
536
537
static void v_matchproto_(task_func_t)
538 67
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 67
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
547 67
        CAST_OBJ_NOTNULL(req, arg, REQ_MAGIC);
548 67
        sp = req->sp;
549 67
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
550
551
        /* Per specification */
552
        assert(sizeof vpx1_sig == 5);
553
        assert(sizeof vpx2_sig == 12);
554
555 67
        HTC_RxInit(req->htc, req->ws);
556 67
        hs = HTC_RxStuff(req->htc, vpx_complete,
557 67
            NULL, NULL, NAN, sp->t_idle + cache_param->timeout_idle,
558
            1024);                      // XXX ?
559 67
        if (hs != HTC_S_COMPLETE) {
560 3
                Req_Release(req);
561 3
                SES_Delete(sp, SC_RX_JUNK, NAN);
562 3
                return;
563
        }
564 64
        p = req->htc->rxbuf_b;
565 64
        if (p[0] == vpx1_sig[0])
566 34
                i = vpx_proto1(wrk, req);
567 30
        else if (p[0] == vpx2_sig[0])
568 30
                i = vpx_proto2(wrk, req);
569
        else
570 0
                WRONG("proxy sig mismatch");
571
572 64
        if (i) {
573 21
                Req_Release(req);
574 21
                SES_Delete(sp, SC_RX_JUNK, NAN);
575 21
                return;
576
        }
577
578 43
        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 6
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 6
        if (proto == PF_INET6) {
596 4
                sin6 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
597 4
                AN(sin6);
598 4
                assert(sl >= sizeof *sin6);
599 4
                VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
600
        } else {
601 2
                sin4 = VSA_Get_Sockaddr(s, &sl);        //lint !e826
602 2
                AN(sin4);
603 2
                assert(sl >= sizeof *sin4);
604 2
                VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
605
        }
606 6
}
607
608
static void
609 6
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
610
{
611
        uint8_t b[2];
612
613 6
        vbe16enc(b, (uint16_t)VSA_Port(s));
614 6
        VSB_bcat(vsb, b, sizeof(b));
615 6
}
616
617
void
618 5
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 5
        CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
628 5
        assert(version == 1 || version == 2);
629 5
        vsb = VSB_new_auto();
630 5
        AN(vsb);
631
632 5
        AZ(SES_Get_server_addr(sp, &sas));
633 5
        AN(sas);
634 5
        proto = VSA_Get_Proto(sas);
635 5
        assert(proto == PF_INET6 || proto == PF_INET);
636
637 5
        if (version == 1) {
638 2
                VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
639 2
                p1 = SES_Get_String_Attr(sp, SA_CLIENT_IP);
640 2
                AN(p1);
641 2
                p2 = SES_Get_String_Attr(sp, SA_CLIENT_PORT);
642 2
                AN(p2);
643 2
                VTCP_name(sas, ha, sizeof ha, pa, sizeof pa);
644 2
                if (proto == PF_INET6)
645 1
                        VSB_printf(vsb, " TCP6 ");
646 1
                else if (proto == PF_INET)
647 1
                        VSB_printf(vsb, " TCP4 ");
648 2
                VSB_printf(vsb, "%s %s %s %s\r\n", p1, ha, p2, pa);
649 3
        } else if (version == 2) {
650 3
                AZ(SES_Get_client_addr(sp, &sac));
651 3
                AN(sac);
652
653 3
                VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
654 3
                VSB_putc(vsb, 0x21);
655 3
                if (proto == PF_INET6) {
656 2
                        VSB_putc(vsb, 0x21);
657 2
                        VSB_putc(vsb, 0x00);
658 2
                        VSB_putc(vsb, 0x24);
659 1
                } else if (proto == PF_INET) {
660 1
                        VSB_putc(vsb, 0x11);
661 1
                        VSB_putc(vsb, 0x00);
662 1
                        VSB_putc(vsb, 0x0c);
663
                }
664 3
                vpx_enc_addr(vsb, proto, sac);
665 3
                vpx_enc_addr(vsb, proto, sas);
666 3
                vpx_enc_port(vsb, sac);
667 3
                vpx_enc_port(vsb, sas);
668
        } else
669 0
                WRONG("Wrong proxy version");
670
671 5
        AZ(VSB_finish(vsb));
672 5
        (void)write(fd, VSB_data(vsb), VSB_len(vsb));
673 5
        if (!DO_DEBUG(DBG_PROTOCOL)) {
674 5
                VSB_delete(vsb);
675 5
                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
}