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