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