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