Coverage Report

Created: 2026-08-13 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2o/lib/handler/connect.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2021 Fastly Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include <limits.h>
23
#include "h2o/hostinfo.h"
24
#include "h2o/memory.h"
25
#include "h2o/socket.h"
26
#include "h2o.h"
27
#include "../probes_.h"
28
29
0
#define MODULE_NAME "lib/handler/connect.c"
30
31
struct st_connect_handler_t {
32
    h2o_handler_t super;
33
    h2o_proxy_config_vars_t config;
34
    struct {
35
        size_t count;
36
        h2o_connect_acl_entry_t entries[0];
37
    } acl;
38
};
39
40
0
#define MAX_ADDRESSES_PER_FAMILY 4
41
0
#define UDP_CHUNK_OVERHEAD 10 /* sufficient space to hold DATAGRAM capsule header (RFC 9297) and context ID of zero (RFC 9298) */
42
43
struct st_server_address_t {
44
    struct sockaddr *sa;
45
    socklen_t salen;
46
};
47
48
struct st_connect_generator_t {
49
    h2o_generator_t super;
50
    struct st_connect_handler_t *handler;
51
    h2o_req_t *src_req;
52
53
    struct {
54
        h2o_hostinfo_getaddr_req_t *v4, *v6;
55
    } getaddr_req;
56
    struct {
57
        struct st_server_address_t list[MAX_ADDRESSES_PER_FAMILY * 2];
58
        size_t size;
59
        size_t used;
60
    } server_addresses;
61
62
    h2o_socket_t *sock;
63
    /**
64
     * Most significant and latest error that occurred, if any. Significance is represented as `class`, in descending order.
65
     */
66
    struct {
67
        enum error_class { ERROR_CLASS_NAME_RESOLUTION, ERROR_CLASS_ACCESS_PROHIBITED, ERROR_CLASS_CONNECT } class;
68
        const char *str;
69
    } last_error;
70
71
    /**
72
     * timer used to handle user-visible timeouts (i.e., connect- and io-timeout)
73
     */
74
    h2o_timer_t timeout;
75
    /**
76
     * timer used to for RFC 8305-style happy eyeballs (resolution delay and connection attempt delay)
77
     */
78
    h2o_timer_t eyeball_delay;
79
80
    /**
81
     * Pick v4 (or v6) address in the next connection attempt. RFC 8305 recommends trying the other family one by one.
82
     */
83
    unsigned pick_v4 : 1;
84
    /**
85
     * `h2o_process_request` was called without request streaming; all data that have to be sent is inside `h2o_req_t::entity`
86
     */
87
    unsigned no_req_streaming : 1;
88
    /**
89
     * set when the send-side is closed by the user
90
     */
91
    unsigned write_closed : 1;
92
    /**
93
     * set when h2o_send has been called to notify that the socket has been closed
94
     */
95
    unsigned read_closed : 1;
96
    /**
97
     * if socket has been closed
98
     */
99
    unsigned socket_closed : 1;
100
    /**
101
     * if connecting using TCP (or UDP)
102
     */
103
    unsigned is_tcp : 1;
104
    /**
105
     * TCP- and UDP-specific data
106
     */
107
    union {
108
        struct {
109
            h2o_buffer_t *sendbuf;
110
            h2o_buffer_t *recvbuf_detached;
111
        } tcp;
112
        struct {
113
            struct {
114
                h2o_buffer_t *buf; /* for datagram fragments */
115
                h2o_timer_t delayed;
116
            } egress;
117
            struct {
118
                char buf[UDP_CHUNK_OVERHEAD + 1500];
119
            } ingress;
120
            /**
121
             * if using draft-03 style encoding rather than RFC 9298
122
             */
123
            unsigned is_draft03 : 1;
124
        } udp;
125
    };
126
};
127
128
static h2o_iovec_t get_proxy_status_identity(h2o_req_t *req)
129
0
{
130
0
    h2o_iovec_t identity = req->conn->ctx->globalconf->proxy_status_identity;
131
0
    if (identity.base == NULL)
132
0
        identity = h2o_iovec_init(H2O_STRLIT("h2o"));
133
0
    return identity;
134
0
}
135
136
static const struct st_server_address_t *get_dest_addr(struct st_connect_generator_t *self)
137
0
{
138
0
    if (self->server_addresses.used > 0) {
139
0
        return &self->server_addresses.list[self->server_addresses.used - 1];
140
0
    } else {
141
0
        return NULL;
142
0
    }
143
0
}
144
145
static void add_proxy_status_header(struct st_connect_handler_t *handler, h2o_req_t *req, const char *error_type,
146
                                    const char *details, const char *rcode, h2o_iovec_t dest_addr_str)
147
0
{
148
0
    if (!handler->config.connect_proxy_status_enabled)
149
0
        return;
150
151
0
    h2o_mem_pool_t *pool = &req->pool;
152
0
    h2o_iovec_t parts[10] = {
153
0
        get_proxy_status_identity(req),
154
0
    };
155
0
    size_t nparts = 1;
156
0
    if (error_type != NULL) {
157
0
        parts[nparts++] = h2o_iovec_init(H2O_STRLIT("; error="));
158
0
        parts[nparts++] = h2o_iovec_init(error_type, strlen(error_type));
159
0
    }
160
0
    if (rcode != NULL) {
161
0
        parts[nparts++] = h2o_iovec_init(H2O_STRLIT("; rcode="));
162
0
        parts[nparts++] = h2o_encode_sf_string(pool, rcode, SIZE_MAX);
163
0
    }
164
0
    if (details != NULL) {
165
0
        parts[nparts++] = h2o_iovec_init(H2O_STRLIT("; details="));
166
0
        parts[nparts++] = h2o_encode_sf_string(pool, details, SIZE_MAX);
167
0
    }
168
0
    if (dest_addr_str.base != NULL) {
169
0
        parts[nparts++] = h2o_iovec_init(H2O_STRLIT("; next-hop=\""));
170
0
        parts[nparts++] = dest_addr_str;
171
0
        parts[nparts++] = h2o_iovec_init(H2O_STRLIT("\""));
172
0
    }
173
0
    assert(nparts <= sizeof(parts) / sizeof(parts[0]));
174
0
    h2o_iovec_t hval = h2o_concat_list(pool, parts, nparts);
175
0
    h2o_add_header_by_str(pool, &req->res.headers, H2O_STRLIT("proxy-status"), 0, NULL, hval.base, hval.len);
176
0
}
177
178
0
#define TO_BITMASK(type, len) ((type) ~(((type)1 << (sizeof(type) * 8 - (len))) - 1))
179
180
static void record_error(struct st_connect_handler_t *handler, h2o_req_t *req, const struct st_server_address_t *addr,
181
                         const char *error_type, const char *details, const char *rcode)
182
0
{
183
0
    H2O_PROBE_REQUEST(CONNECT_ERROR, req, error_type, details, rcode);
184
185
0
    char dest_addr_strbuf[NI_MAXHOST];
186
0
    h2o_iovec_t dest_addr_str = h2o_iovec_init(NULL, 0);
187
0
    if (addr != NULL) {
188
0
        size_t len = h2o_socket_getnumerichost(addr->sa, addr->salen, dest_addr_strbuf);
189
0
        if (len != SIZE_MAX) {
190
0
            dest_addr_str = h2o_iovec_init(dest_addr_strbuf, len);
191
0
        }
192
0
    }
193
194
0
    h2o_req_log_error(req, MODULE_NAME, "%s; rcode=%s; details=%s; next-hop=%s", error_type, rcode != NULL ? rcode : "(null)",
195
0
                      details != NULL ? details : "(null)", dest_addr_str.base != NULL ? dest_addr_str.base : "(null)");
196
197
0
    add_proxy_status_header(handler, req, error_type, details, rcode, dest_addr_str);
198
0
}
199
200
static void record_connect_success(struct st_connect_generator_t *self)
201
0
{
202
0
    const struct st_server_address_t *addr = get_dest_addr(self);
203
0
    if (addr == NULL)
204
0
        return;
205
206
0
    H2O_PROBE_REQUEST(CONNECT_SUCCESS, self->src_req, addr->sa);
207
208
0
    char dest_addr_strbuf[NI_MAXHOST];
209
0
    size_t len = h2o_socket_getnumerichost(addr->sa, addr->salen, dest_addr_strbuf);
210
0
    if (len != SIZE_MAX) {
211
0
        add_proxy_status_header(self->handler, self->src_req, NULL, NULL, NULL, h2o_iovec_init(dest_addr_strbuf, len));
212
0
    }
213
0
}
214
215
static void record_socket_error(struct st_connect_generator_t *self, const char *err)
216
0
{
217
0
    const char *error_type;
218
0
    const char *details = NULL;
219
0
    if (err == h2o_socket_error_conn_refused)
220
0
        error_type = "connection_refused";
221
0
    else if (err == h2o_socket_error_conn_timed_out)
222
0
        error_type = "connection_timeout";
223
0
    else if (err == h2o_socket_error_network_unreachable || err == h2o_socket_error_host_unreachable)
224
0
        error_type = "destination_ip_unroutable";
225
0
    else {
226
0
        error_type = "proxy_internal_error";
227
0
        details = err;
228
0
    }
229
0
    record_error(self->handler, self->src_req, get_dest_addr(self), error_type, details, NULL);
230
0
}
231
232
static void try_connect(struct st_connect_generator_t *self);
233
static int tcp_start_connect(struct st_connect_generator_t *self, struct st_server_address_t *server_address);
234
static int udp_connect(struct st_connect_generator_t *self, struct st_server_address_t *server_address);
235
236
static h2o_loop_t *get_loop(struct st_connect_generator_t *self)
237
0
{
238
0
    return self->src_req->conn->ctx->loop;
239
0
}
240
241
static void stop_eyeballs(struct st_connect_generator_t *self)
242
0
{
243
0
    if (self->getaddr_req.v4 != NULL) {
244
0
        h2o_hostinfo_getaddr_cancel(self->getaddr_req.v4);
245
0
        self->getaddr_req.v4 = NULL;
246
0
    }
247
0
    if (self->getaddr_req.v6 != NULL) {
248
0
        h2o_hostinfo_getaddr_cancel(self->getaddr_req.v6);
249
0
        self->getaddr_req.v6 = NULL;
250
0
    }
251
0
    if (self->eyeball_delay.cb != NULL) {
252
0
        h2o_timer_unlink(&self->eyeball_delay);
253
0
        self->eyeball_delay.cb = NULL;
254
0
    }
255
0
}
256
257
static void dispose_generator(struct st_connect_generator_t *self)
258
0
{
259
0
    stop_eyeballs(self);
260
0
    if (self->sock != NULL) {
261
0
        h2o_socket_close(self->sock);
262
0
        self->sock = NULL;
263
0
        self->socket_closed = 1;
264
0
    }
265
0
    if (self->is_tcp) {
266
0
        if (self->tcp.sendbuf != NULL)
267
0
            h2o_buffer_dispose(&self->tcp.sendbuf);
268
0
        if (self->tcp.recvbuf_detached != NULL)
269
0
            h2o_buffer_dispose(&self->tcp.recvbuf_detached);
270
0
    } else {
271
0
        if (self->udp.egress.buf != NULL)
272
0
            h2o_buffer_dispose(&self->udp.egress.buf);
273
0
        h2o_timer_unlink(&self->udp.egress.delayed);
274
0
    }
275
0
    h2o_timer_unlink(&self->timeout);
276
0
}
277
278
static int close_socket(struct st_connect_generator_t *self)
279
0
{
280
0
    int send_inflight;
281
282
0
    if (self->is_tcp) {
283
0
        self->tcp.recvbuf_detached = self->sock->input;
284
0
        send_inflight = self->tcp.recvbuf_detached->size != 0;
285
0
    } else {
286
0
        send_inflight = !h2o_socket_is_reading(self->sock);
287
0
    }
288
0
    h2o_buffer_init(&self->sock->input, &h2o_socket_buffer_prototype);
289
0
    h2o_socket_close(self->sock);
290
0
    self->sock = NULL;
291
0
    self->socket_closed = 1;
292
293
0
    return send_inflight;
294
0
}
295
296
static void close_readwrite(struct st_connect_generator_t *self)
297
0
{
298
0
    int send_inflight = 0;
299
300
0
    if (self->sock != NULL)
301
0
        send_inflight = close_socket(self);
302
0
    else if (self->is_tcp)
303
0
        send_inflight = self->tcp.recvbuf_detached->size != 0;
304
305
0
    if (h2o_timer_is_linked(&self->timeout))
306
0
        h2o_timer_unlink(&self->timeout);
307
308
    /* immediately notify read-close if necessary, setting up delayed task to for destroying other items; the timer is reset if
309
     * `h2o_send` indirectly invokes `dispose_generator`. */
310
0
    if (!self->read_closed && !send_inflight) {
311
0
        h2o_timer_link(get_loop(self), 0, &self->timeout);
312
0
        self->read_closed = 1;
313
0
        h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_FINAL);
314
0
        return;
315
0
    }
316
317
    /* notify write-close if necessary; see the comment above regarding the use of the timer */
318
0
    if (!self->write_closed && self->is_tcp && self->tcp.sendbuf->size != 0) {
319
0
        self->write_closed = 1;
320
0
        h2o_timer_link(get_loop(self), 0, &self->timeout);
321
0
        self->src_req->proceed_req(self->src_req, h2o_httpclient_error_io /* TODO notify as cancel? */);
322
0
        return;
323
0
    }
324
0
}
325
326
static void on_io_timeout(h2o_timer_t *timer)
327
0
{
328
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, timeout, timer);
329
0
    H2O_PROBE_REQUEST0(CONNECT_IO_TIMEOUT, self->src_req);
330
0
    close_readwrite(self);
331
0
}
332
333
static void reset_io_timeout(struct st_connect_generator_t *self)
334
0
{
335
0
    if (self->sock != NULL) {
336
0
        h2o_timer_unlink(&self->timeout);
337
0
        h2o_timer_link(get_loop(self), self->handler->config.io_timeout, &self->timeout);
338
0
    }
339
0
}
340
341
static void send_connect_error(struct st_connect_generator_t *self, int code, const char *msg, const char *errstr)
342
0
{
343
0
    stop_eyeballs(self);
344
0
    h2o_timer_unlink(&self->timeout);
345
346
0
    if (self->sock != NULL) {
347
0
        h2o_socket_close(self->sock);
348
0
        self->sock = NULL;
349
0
    }
350
351
0
    h2o_send_error_generic(self->src_req, code, msg, errstr, H2O_SEND_ERROR_KEEP_HEADERS);
352
0
}
353
354
static void on_connect_error(struct st_connect_generator_t *self, const char *errstr)
355
0
{
356
0
    send_connect_error(self, 502, "Gateway Error", errstr);
357
0
}
358
359
static void on_connect_timeout(h2o_timer_t *entry)
360
0
{
361
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, timeout, entry);
362
0
    if (self->server_addresses.size > 0) {
363
0
        record_error(self->handler, self->src_req, get_dest_addr(self), "connection_timeout", NULL, NULL);
364
0
    } else {
365
0
        record_error(self->handler, self->src_req, NULL, "dns_timeout", NULL, NULL);
366
0
    }
367
0
    on_connect_error(self, h2o_httpclient_error_io_timeout);
368
0
}
369
370
static void set_last_error(struct st_connect_generator_t *self, enum error_class class, const char *str)
371
0
{
372
0
    if (self->last_error.class <= class) {
373
0
        self->last_error.class = class;
374
0
        self->last_error.str = str;
375
0
    }
376
0
}
377
378
static void on_resolution_delay_timeout(h2o_timer_t *entry)
379
0
{
380
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, eyeball_delay, entry);
381
382
0
    assert(self->server_addresses.used == 0);
383
384
0
    try_connect(self);
385
0
}
386
387
static void on_connection_attempt_delay_timeout(h2o_timer_t *entry)
388
0
{
389
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, eyeball_delay, entry);
390
391
    /* If no more addresses are available, continue trying the current attempt until the connect_timeout expires. */
392
0
    if (self->server_addresses.used == self->server_addresses.size)
393
0
        return;
394
395
    /* close current connection attempt and try next. */
396
0
    h2o_socket_close(self->sock);
397
0
    self->sock = NULL;
398
0
    try_connect(self);
399
0
}
400
401
static int store_server_addresses(struct st_connect_generator_t *self, struct addrinfo *res)
402
0
{
403
0
    size_t num_added = 0;
404
405
    /* copy first entries in the response; ordering of addresses being returned by `getaddrinfo` is respected, as ordinary clients
406
     * (incl. forward proxy) are not expected to distribute the load among the addresses being returned. */
407
0
    do {
408
0
        assert(self->server_addresses.size < PTLS_ELEMENTSOF(self->server_addresses.list));
409
0
        if (h2o_connect_lookup_acl(self->handler->acl.entries, self->handler->acl.count, res->ai_addr)) {
410
0
            struct st_server_address_t *dst = self->server_addresses.list + self->server_addresses.size++;
411
0
            dst->sa = h2o_mem_alloc_pool_aligned(&self->src_req->pool, H2O_ALIGNOF(struct sockaddr_storage), res->ai_addrlen);
412
0
            memcpy(dst->sa, res->ai_addr, res->ai_addrlen);
413
0
            dst->salen = res->ai_addrlen;
414
0
            ++num_added;
415
0
        }
416
0
    } while ((res = res->ai_next) != NULL && num_added < MAX_ADDRESSES_PER_FAMILY);
417
418
0
    return num_added != 0;
419
0
}
420
421
static void on_getaddr(h2o_hostinfo_getaddr_req_t *getaddr_req, const char *errstr, struct addrinfo *res, void *_self)
422
0
{
423
0
    struct st_connect_generator_t *self = _self;
424
0
    if (getaddr_req == self->getaddr_req.v4) {
425
0
        self->getaddr_req.v4 = NULL;
426
0
    } else if (getaddr_req == self->getaddr_req.v6) {
427
0
        self->getaddr_req.v6 = NULL;
428
0
    } else {
429
0
        h2o_fatal("unexpected getaddr_req");
430
0
    }
431
432
    /* Store addresses, or convert error to ACL denial. */
433
0
    if (errstr == NULL) {
434
0
        if (self->is_tcp) {
435
0
            assert(res->ai_socktype == SOCK_STREAM);
436
0
        } else {
437
0
            assert(res->ai_socktype == SOCK_DGRAM);
438
0
        }
439
0
        assert(res != NULL && "upon successful return, getaddrinfo shall return at least one address (RFC 3493 Section 6.1)");
440
0
        if (!store_server_addresses(self, res))
441
0
            set_last_error(self, ERROR_CLASS_ACCESS_PROHIBITED, "destination_ip_prohibited");
442
0
    } else {
443
0
        set_last_error(self, ERROR_CLASS_NAME_RESOLUTION, errstr);
444
0
    }
445
446
0
    if (self->getaddr_req.v4 == NULL) {
447
        /* If v6 lookup is still running, that means that v4 lookup has *just* completed. Set the resolution delay timer if v4
448
         * addresses are available. */
449
0
        if (self->getaddr_req.v6 != NULL) {
450
0
            assert(self->server_addresses.used == 0);
451
0
            if (self->server_addresses.size != 0) {
452
0
                self->eyeball_delay.cb = on_resolution_delay_timeout;
453
0
                h2o_timer_link(get_loop(self), self->handler->config.happy_eyeballs.name_resolution_delay, &self->eyeball_delay);
454
0
            }
455
0
            return;
456
0
        }
457
458
        /* Both v4 and v6 lookups are complete. If the resolution delay timer is running. Reset it. */
459
0
        if (h2o_timer_is_linked(&self->eyeball_delay) && self->eyeball_delay.cb == on_resolution_delay_timeout) {
460
0
            assert(self->server_addresses.used == 0);
461
0
            h2o_timer_unlink(&self->eyeball_delay);
462
0
        }
463
        /* In case no addresses are available, send HTTP error. */
464
0
        if (self->server_addresses.size == 0) {
465
0
            if (self->last_error.class == ERROR_CLASS_ACCESS_PROHIBITED) {
466
0
                record_error(self->handler, self->src_req, NULL, self->last_error.str, NULL, NULL);
467
0
                send_connect_error(self, 403, "Destination IP Prohibited", "Destination IP Prohibited");
468
0
            } else {
469
0
                const char *rcode;
470
0
                if (self->last_error.str == h2o_hostinfo_error_nxdomain) {
471
0
                    rcode = "NXDOMAIN";
472
0
                } else if (self->last_error.str == h2o_hostinfo_error_nodata) {
473
0
                    rcode = "NODATA";
474
0
                } else if (self->last_error.str == h2o_hostinfo_error_refused) {
475
0
                    rcode = "REFUSED";
476
0
                } else if (self->last_error.str == h2o_hostinfo_error_servfail) {
477
0
                    rcode = "SERVFAIL";
478
0
                } else {
479
0
                    rcode = NULL;
480
0
                }
481
0
                record_error(self->handler, self->src_req, NULL, "dns_error", self->last_error.str, rcode);
482
0
                on_connect_error(self, self->last_error.str);
483
0
            }
484
0
            return;
485
0
        }
486
0
    }
487
488
    /* If the connection attempt has been under way for more than CONNECTION_ATTEMPT_DELAY_MS and the lookup that just completed
489
     * gave us a new address to try, then stop that connection attempt and start a new connection attempt using the new address.
490
     *
491
     * If the connection attempt has been under way for less than that, then do nothing for now.  Eventually, either the timeout
492
     * will expire or the connection attempt will complete.
493
     *
494
     * If the connection attempt is under way but the lookup has not provided us any new address to try, then do nothing for now,
495
     * and wait for the connection attempt to complete. */
496
0
    if (self->sock != NULL) {
497
0
        if (h2o_timer_is_linked(&self->eyeball_delay))
498
0
            return;
499
0
        if (self->server_addresses.used == self->server_addresses.size)
500
0
            return;
501
0
        h2o_socket_close(self->sock);
502
0
        self->sock = NULL;
503
0
    }
504
0
    try_connect(self);
505
0
}
506
507
static struct st_server_address_t *pick_and_swap(struct st_connect_generator_t *self, size_t idx)
508
0
{
509
0
    struct st_server_address_t *server_address = NULL;
510
511
0
    if (idx != self->server_addresses.used) {
512
0
        struct st_server_address_t swap = self->server_addresses.list[idx];
513
0
        self->server_addresses.list[idx] = self->server_addresses.list[self->server_addresses.used];
514
0
        self->server_addresses.list[self->server_addresses.used] = swap;
515
0
    }
516
0
    server_address = &self->server_addresses.list[self->server_addresses.used];
517
0
    self->server_addresses.used++;
518
0
    self->pick_v4 = !self->pick_v4;
519
0
    return server_address;
520
0
}
521
522
static struct st_server_address_t *get_next_server_address_for_connect(struct st_connect_generator_t *self)
523
0
{
524
0
    struct st_server_address_t *server_address = NULL;
525
526
    /* Fetch the next address from the list of resolved addresses. */
527
0
    for (size_t i = self->server_addresses.used; i < self->server_addresses.size; i++) {
528
0
        if (self->pick_v4 && self->server_addresses.list[i].sa->sa_family == AF_INET) {
529
0
            server_address = pick_and_swap(self, i);
530
0
            break;
531
0
        } else if (!self->pick_v4 && self->server_addresses.list[i].sa->sa_family == AF_INET6) {
532
0
            server_address = pick_and_swap(self, i);
533
0
            break;
534
0
        }
535
0
    }
536
537
    /* If address of the preferred address family is not available, select one of the other family, if available. Otherwise,
538
     * send an HTTP error response or wait for address resolution. */
539
0
    if (server_address == NULL && self->server_addresses.used < self->server_addresses.size) {
540
0
        server_address = &self->server_addresses.list[self->server_addresses.used];
541
0
        self->server_addresses.used++;
542
0
    }
543
544
0
    return server_address;
545
0
}
546
547
static void try_connect(struct st_connect_generator_t *self)
548
0
{
549
0
    struct st_server_address_t *server_address;
550
551
0
    do {
552
0
        server_address = get_next_server_address_for_connect(self);
553
0
        if (server_address == NULL) {
554
            /* If address an is not available, send an HTTP error response or wait for address resolution. */
555
0
            if (self->getaddr_req.v4 == NULL && self->getaddr_req.v6 == NULL) {
556
                /* No pending address resolution, send error response. */
557
0
                assert(self->last_error.class == ERROR_CLASS_CONNECT);
558
0
                record_socket_error(self, self->last_error.str);
559
0
                on_connect_error(self, self->last_error.str);
560
0
            }
561
0
            return;
562
0
        }
563
564
        /* Connect. Retry if the connect function returns error immediately. */
565
0
    } while (!(self->is_tcp ? tcp_start_connect : udp_connect)(self, server_address));
566
0
}
567
568
static void tcp_on_write_complete(h2o_socket_t *_sock, const char *err)
569
0
{
570
0
    struct st_connect_generator_t *self = _sock->data;
571
572
0
    if (err != NULL) {
573
0
        H2O_PROBE_REQUEST(CONNECT_TCP_WRITE_ERROR, self->src_req, err);
574
0
    }
575
576
    /* until h2o_socket_t implements shutdown(SHUT_WR), do a bidirectional close when we close the write-side */
577
0
    if (err != NULL || self->write_closed) {
578
0
        close_readwrite(self);
579
0
        return;
580
0
    }
581
582
0
    reset_io_timeout(self);
583
584
0
    h2o_buffer_consume(&self->tcp.sendbuf, self->tcp.sendbuf->size);
585
0
    self->src_req->proceed_req(self->src_req, NULL);
586
0
}
587
588
static void tcp_do_write(struct st_connect_generator_t *self)
589
0
{
590
0
    reset_io_timeout(self);
591
592
0
    h2o_iovec_t vec = h2o_iovec_init(self->tcp.sendbuf->bytes, self->tcp.sendbuf->size);
593
0
    H2O_PROBE_REQUEST(CONNECT_TCP_WRITE, self->src_req, vec.len);
594
0
    h2o_socket_write(self->sock, &vec, 1, tcp_on_write_complete);
595
0
}
596
597
static int tcp_write(void *_self, int is_end_stream)
598
0
{
599
0
    struct st_connect_generator_t *self = _self;
600
0
    h2o_iovec_t chunk = self->src_req->entity;
601
602
0
    assert(!self->write_closed);
603
0
    assert(self->tcp.sendbuf->size == 0);
604
605
    /* the socket might have been closed due to a read error */
606
0
    if (self->socket_closed)
607
0
        return 1;
608
609
0
    assert(self->sock != NULL && "write_req called before proceed_req is called?");
610
611
    /* buffer input */
612
0
    h2o_buffer_append(&self->tcp.sendbuf, chunk.base, chunk.len);
613
0
    if (is_end_stream)
614
0
        self->write_closed = 1;
615
616
    /* write if the socket has been opened */
617
0
    if (self->sock != NULL && !h2o_socket_is_writing(self->sock))
618
0
        tcp_do_write(self);
619
620
0
    return 0;
621
0
}
622
623
static void tcp_on_read(h2o_socket_t *_sock, const char *err)
624
0
{
625
0
    struct st_connect_generator_t *self = _sock->data;
626
627
0
    h2o_socket_read_stop(self->sock);
628
0
    h2o_timer_unlink(&self->timeout);
629
630
0
    if (err == NULL) {
631
0
        h2o_iovec_t vec = h2o_iovec_init(self->sock->input->bytes, self->sock->input->size);
632
0
        H2O_PROBE_REQUEST(CONNECT_TCP_READ, self->src_req, vec.len);
633
0
        h2o_send(self->src_req, &vec, 1, H2O_SEND_STATE_IN_PROGRESS);
634
0
    } else {
635
0
        H2O_PROBE_REQUEST(CONNECT_TCP_READ_ERROR, self->src_req, err);
636
        /* unidirectional close is signalled using H2O_SEND_STATE_FINAL, but the write side remains open */
637
0
        self->read_closed = 1;
638
0
        h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_FINAL);
639
0
    }
640
0
}
641
642
static void tcp_on_proceed(h2o_generator_t *_self, h2o_req_t *req)
643
0
{
644
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, super, _self);
645
646
0
    assert(!self->read_closed);
647
648
0
    if (self->sock != NULL) {
649
0
        h2o_buffer_consume(&self->sock->input, self->sock->input->size);
650
0
        reset_io_timeout(self);
651
0
        h2o_socket_read_start(self->sock, tcp_on_read);
652
0
    } else {
653
0
        self->read_closed = 1;
654
0
        h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_FINAL);
655
0
    }
656
0
}
657
658
static void tcp_on_connect(h2o_socket_t *_sock, const char *err)
659
0
{
660
0
    struct st_connect_generator_t *self = _sock->data;
661
662
0
    assert(self->sock == _sock);
663
664
0
    if (err != NULL) {
665
0
        set_last_error(self, ERROR_CLASS_CONNECT, err);
666
0
        h2o_socket_close(self->sock);
667
0
        self->sock = NULL;
668
0
        try_connect(self);
669
0
        return;
670
0
    }
671
672
0
    stop_eyeballs(self);
673
0
    self->timeout.cb = on_io_timeout;
674
0
    reset_io_timeout(self);
675
676
    /* Start write. Once write is complete (or if there is nothing to write), `proceed_req` will be called or the socket would be
677
     * closed if `write_closed` is set. */
678
0
    self->src_req->write_req.cb(self, self->no_req_streaming);
679
680
0
    record_connect_success(self);
681
682
    /* build and submit 200 response */
683
0
    self->src_req->res.status = 200;
684
0
    h2o_start_response(self->src_req, &self->super);
685
0
    h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_IN_PROGRESS);
686
0
}
687
688
static int tcp_start_connect(struct st_connect_generator_t *self, struct st_server_address_t *server_address)
689
0
{
690
0
    H2O_PROBE_REQUEST(CONNECT_TCP_START, self->src_req, server_address->sa);
691
692
0
    const char *errstr;
693
0
    if ((self->sock = h2o_socket_connect(get_loop(self), server_address->sa, server_address->salen, tcp_on_connect, &errstr)) ==
694
0
        NULL) {
695
0
        set_last_error(self, ERROR_CLASS_CONNECT, errstr);
696
0
        return 0;
697
0
    }
698
699
0
    self->sock->data = self;
700
0
#if !H2O_USE_LIBUV
701
    /* This is the maximum amount of data that will be buffered within userspace. It is hard-coded to 64KB to balance throughput
702
     * and latency, and because we do not expect the need to change the value. */
703
0
    h2o_evloop_socket_set_max_read_size(self->sock, 64 * 1024);
704
0
#endif
705
0
    self->eyeball_delay.cb = on_connection_attempt_delay_timeout;
706
0
    h2o_timer_link(get_loop(self), self->handler->config.happy_eyeballs.connection_attempt_delay, &self->eyeball_delay);
707
708
0
    return 1;
709
0
}
710
711
static h2o_iovec_t udp_get_next_chunk(const char *start, size_t len, size_t *to_consume, int *skip)
712
0
{
713
0
    const uint8_t *bytes = (const uint8_t *)start;
714
0
    const uint8_t *end = bytes + len;
715
0
    uint64_t chunk_type, chunk_length;
716
717
0
    chunk_type = ptls_decode_quicint(&bytes, end);
718
0
    if (chunk_type == UINT64_MAX)
719
0
        return h2o_iovec_init(NULL, 0);
720
0
    chunk_length = ptls_decode_quicint(&bytes, end);
721
0
    if (chunk_length == UINT64_MAX)
722
0
        return h2o_iovec_init(NULL, 0);
723
724
    /* chunk is incomplete */
725
0
    if (end - bytes < chunk_length)
726
0
        return h2o_iovec_init(NULL, 0);
727
728
    /*
729
     * https://tools.ietf.org/html/draft-ietf-masque-connect-udp-03#section-6
730
     * CONNECT-UDP Stream Chunks can be used to convey UDP payloads, by
731
     * using a CONNECT-UDP Stream Chunk Type of UDP_PACKET (value 0x00).
732
     */
733
0
    *skip = chunk_type != 0;
734
0
    *to_consume = (bytes + chunk_length) - (const uint8_t *)start;
735
736
0
    return h2o_iovec_init(bytes, chunk_length);
737
0
}
738
739
static void udp_write_core(struct st_connect_generator_t *self, h2o_iovec_t datagram)
740
0
{
741
0
    const uint8_t *src = (const uint8_t *)datagram.base, *end = src + datagram.len;
742
743
    /* When using RFC 9298, the payload starts with a Context ID; drop anything other than UDP packets.
744
     * TODO: propagate error when decoding fails? */
745
0
    if (!self->udp.is_draft03 && (ptls_decode_quicint(&src, end)) != 0)
746
0
        return;
747
748
0
    H2O_PROBE_REQUEST(CONNECT_UDP_WRITE, self->src_req, end - src);
749
0
    while (send(h2o_socket_get_fd(self->sock), src, end - src, 0) == -1 && errno == EINTR)
750
0
        ;
751
0
}
752
753
static void udp_write_stream_complete_delayed(h2o_timer_t *_timer)
754
0
{
755
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, udp.egress.delayed, _timer);
756
757
0
    if (self->write_closed) {
758
0
        close_readwrite(self);
759
0
        return;
760
0
    }
761
762
0
    self->src_req->proceed_req(self->src_req, NULL);
763
0
}
764
765
static void udp_do_write_stream(struct st_connect_generator_t *self, h2o_iovec_t chunk)
766
0
{
767
0
    int from_buf = 0;
768
0
    size_t off = 0;
769
770
0
    reset_io_timeout(self);
771
772
0
    if (self->udp.egress.buf->size != 0) {
773
0
        from_buf = 1;
774
0
        if (chunk.len != 0)
775
0
            h2o_buffer_append(&self->udp.egress.buf, chunk.base, chunk.len);
776
0
        chunk.base = self->udp.egress.buf->bytes;
777
0
        chunk.len = self->udp.egress.buf->size;
778
0
    }
779
0
    do {
780
0
        int skip = 0;
781
0
        size_t to_consume;
782
0
        h2o_iovec_t datagram = udp_get_next_chunk(chunk.base + off, chunk.len - off, &to_consume, &skip);
783
0
        if (datagram.base == NULL)
784
0
            break;
785
0
        if (!skip)
786
0
            udp_write_core(self, datagram);
787
0
        off += to_consume;
788
0
    } while (1);
789
790
0
    if (from_buf) {
791
0
        h2o_buffer_consume(&self->udp.egress.buf, off);
792
0
    } else if (chunk.len != off) {
793
0
        h2o_buffer_append(&self->udp.egress.buf, chunk.base + off, chunk.len - off);
794
0
    }
795
796
0
    h2o_timer_link(get_loop(self), 0, &self->udp.egress.delayed);
797
0
}
798
799
static int udp_write_stream(void *_self, int is_end_stream)
800
0
{
801
0
    struct st_connect_generator_t *self = _self;
802
0
    h2o_iovec_t chunk = self->src_req->entity;
803
804
0
    assert(!self->write_closed);
805
806
    /* the socket might have been closed tue to a read error */
807
0
    if (self->socket_closed)
808
0
        return 1;
809
810
0
    assert(self->sock != NULL && "write_req called before proceed_req is called?");
811
812
0
    if (is_end_stream)
813
0
        self->write_closed = 1;
814
815
    /* if the socket is not yet open, buffer input and return */
816
0
    if (self->sock == NULL) {
817
0
        h2o_buffer_append(&self->udp.egress.buf, chunk.base, chunk.len);
818
0
        return 0;
819
0
    }
820
821
0
    udp_do_write_stream(self, chunk);
822
0
    return 0;
823
0
}
824
825
static void udp_write_datagrams(h2o_req_t *_req, h2o_iovec_t *datagrams, size_t num_datagrams)
826
0
{
827
0
    struct st_connect_generator_t *self = _req->write_req.ctx;
828
829
0
    reset_io_timeout(self);
830
831
0
    for (size_t i = 0; i != num_datagrams; ++i)
832
0
        udp_write_core(self, datagrams[i]);
833
0
}
834
835
static void udp_on_read(h2o_socket_t *_sock, const char *err)
836
0
{
837
0
    struct st_connect_generator_t *self = _sock->data;
838
0
    h2o_iovec_t payload =
839
0
        h2o_iovec_init(self->udp.ingress.buf + UDP_CHUNK_OVERHEAD, sizeof(self->udp.ingress.buf) - UDP_CHUNK_OVERHEAD);
840
841
0
    if (err != NULL) {
842
0
        close_readwrite(self);
843
0
        return;
844
0
    }
845
846
0
    { /* read UDP packet, or return */
847
0
        ssize_t rret;
848
0
        while ((rret = recv(h2o_socket_get_fd(self->sock), payload.base, payload.len, 0)) == -1 && errno == EINTR)
849
0
            ;
850
0
        if (rret == -1)
851
0
            return;
852
0
        payload.len = rret;
853
0
    }
854
0
    H2O_PROBE_REQUEST(CONNECT_UDP_READ, self->src_req, payload.len);
855
856
    /* prepend Context ID (of zero, indicating UDP packet) if RFC 9298 */
857
0
    if (!self->udp.is_draft03) {
858
0
        *--payload.base = 0;
859
0
        payload.len += 1;
860
0
    }
861
862
    /* forward UDP datagram as is; note that it might be zero-sized */
863
0
    if (self->src_req->forward_datagram.read_ != NULL) {
864
0
        self->src_req->forward_datagram.read_(self->src_req, &payload, 1);
865
0
    } else {
866
0
        h2o_socket_read_stop(self->sock);
867
0
        h2o_timer_unlink(&self->timeout);
868
0
        { /* prepend Datagram Capsule length */
869
0
            uint8_t length_buf[8];
870
0
            size_t length_len = quicly_encodev(length_buf, payload.len) - length_buf;
871
0
            memcpy(payload.base - length_len, length_buf, length_len);
872
0
            payload.base -= length_len;
873
0
            payload.len += length_len;
874
0
        }
875
        /* prepend Datagram Capsule Type */
876
0
        *--payload.base = 0;
877
0
        payload.len += 1;
878
0
        assert(payload.base >= self->udp.ingress.buf);
879
0
        h2o_send(self->src_req, &payload, 1, H2O_SEND_STATE_IN_PROGRESS);
880
0
    }
881
0
}
882
883
static void udp_on_proceed(h2o_generator_t *_self, h2o_req_t *req)
884
0
{
885
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, super, _self);
886
887
0
    if (self->sock != NULL) {
888
0
        h2o_buffer_consume(&self->sock->input, self->sock->input->size);
889
0
        reset_io_timeout(self);
890
0
        h2o_socket_read_start(self->sock, udp_on_read);
891
0
    } else {
892
0
        self->read_closed = 1;
893
0
        h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_FINAL);
894
0
    }
895
0
}
896
897
static int udp_connect(struct st_connect_generator_t *self, struct st_server_address_t *server_address)
898
0
{
899
0
    int fd;
900
901
0
    assert(self->udp.egress.buf->size == 0); /* the handler does not call `proceed_req` until the connection becomes ready */
902
903
0
    H2O_PROBE_REQUEST(CONNECT_UDP_START, self->src_req, server_address->sa);
904
    /* connect */
905
0
    if ((fd = socket(server_address->sa->sa_family, SOCK_DGRAM, 0)) == -1 ||
906
0
        connect(fd, server_address->sa, server_address->salen) != 0) {
907
0
        const char *err = h2o_socket_error_conn_fail;
908
0
        if (fd != -1) {
909
0
            err = h2o_socket_get_error_string(errno, err);
910
0
            close(fd);
911
0
        }
912
0
        set_last_error(self, ERROR_CLASS_CONNECT, err);
913
0
        return 0;
914
0
    }
915
916
0
    stop_eyeballs(self);
917
0
    self->timeout.cb = on_io_timeout;
918
0
    reset_io_timeout(self);
919
920
    /* setup, initiating transfer of early data */
921
#if H2O_USE_LIBUV
922
    self->sock = h2o_uv__poll_create(get_loop(self), fd, (uv_close_cb)free);
923
#else
924
0
    self->sock = h2o_evloop_socket_create(get_loop(self), fd, H2O_SOCKET_FLAG_DONT_READ);
925
0
#endif
926
0
    assert(self->sock != NULL);
927
0
    self->sock->data = self;
928
0
    self->src_req->write_req.cb = udp_write_stream;
929
0
    self->src_req->forward_datagram.write_ = udp_write_datagrams;
930
0
    self->src_req->write_req.ctx = self;
931
932
0
    record_connect_success(self);
933
934
    /* build and submit success */
935
0
    if (self->src_req->version < 0x200 && !self->udp.is_draft03) {
936
0
        assert(self->src_req->upgrade.base != NULL);
937
0
        self->src_req->res.status = 101;
938
0
        self->src_req->res.reason = "Switching Protocols";
939
0
        h2o_add_header(&self->src_req->pool, &self->src_req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("connect-udp"));
940
0
    } else {
941
0
        self->src_req->res.status = 200;
942
0
    }
943
0
    if (!self->udp.is_draft03)
944
0
        h2o_add_header_by_str(&self->src_req->pool, &self->src_req->res.headers, H2O_STRLIT("capsule-protocol"), 0, NULL,
945
0
                              H2O_STRLIT("?1"));
946
0
    h2o_start_response(self->src_req, &self->super);
947
0
    h2o_send(self->src_req, NULL, 0, H2O_SEND_STATE_IN_PROGRESS);
948
949
    /* write any data if provided, or just call the proceed_req callback */
950
0
    self->src_req->write_req.cb(self, self->no_req_streaming);
951
952
0
    return 1;
953
0
}
954
955
static void on_stop(h2o_generator_t *_self, h2o_req_t *req)
956
0
{
957
0
    struct st_connect_generator_t *self = H2O_STRUCT_FROM_MEMBER(struct st_connect_generator_t, super, _self);
958
0
    dispose_generator(self);
959
0
}
960
961
static void on_generator_dispose(void *_self)
962
0
{
963
0
    struct st_connect_generator_t *self = _self;
964
0
    H2O_PROBE_REQUEST0(CONNECT_DISPOSE, self->src_req);
965
0
    dispose_generator(self);
966
0
}
967
968
/**
969
 * expects "/host/port/" as input, where the preceding slash is optional
970
 */
971
static int masque_decode_hostport(h2o_mem_pool_t *pool, const char *_src, size_t _len, h2o_iovec_t *host, uint16_t *port)
972
0
{
973
0
    char *src = (char *)_src; /* h2o_strtosizefwd takes non-const arg, so ... */
974
0
    const char *end = src + _len;
975
976
0
    if (src < end && src[0] == '/')
977
0
        ++src;
978
979
0
    { /* extract host */
980
0
        size_t host_len;
981
0
        if ((host_len = h2o_strstr(src, end - src, H2O_STRLIT("/"))) == SIZE_MAX || host_len == 0)
982
0
            return 0;
983
0
        if ((*host = h2o_uri_unescape(pool, src, host_len)).base == NULL)
984
0
            return 0;
985
0
        src += host_len + 1;
986
0
    }
987
988
0
    { /* parse port */
989
0
        size_t v;
990
0
        if ((v = h2o_strtosizefwd(&src, end - src)) >= 65535)
991
0
            return 0;
992
0
        if (src == end || *src != '/')
993
0
            return 0;
994
0
        *port = (uint16_t)v;
995
0
    }
996
997
0
    return 1;
998
0
}
999
1000
static int on_req_core(struct st_connect_handler_t *handler, h2o_req_t *req, h2o_iovec_t host, uint16_t port, int is_tcp,
1001
                       int is_masque_draft03)
1002
0
{
1003
0
    struct st_connect_generator_t *self;
1004
0
    size_t sizeof_self = offsetof(struct st_connect_generator_t, tcp) + (is_tcp ? sizeof(self->tcp) : sizeof(self->udp));
1005
0
    self = h2o_mem_alloc_shared(&req->pool, sizeof_self, on_generator_dispose);
1006
0
    memset(self, 0, sizeof_self);
1007
0
    self->super.stop = on_stop;
1008
0
    self->handler = handler;
1009
0
    self->src_req = req;
1010
0
    self->timeout.cb = on_connect_timeout;
1011
0
    if (is_tcp) {
1012
0
        self->is_tcp = 1;
1013
0
        self->super.proceed = tcp_on_proceed;
1014
0
        h2o_buffer_init(&self->tcp.sendbuf, &h2o_socket_buffer_prototype);
1015
0
    } else {
1016
0
        self->super.proceed = udp_on_proceed;
1017
0
        h2o_buffer_init(&self->udp.egress.buf, &h2o_socket_buffer_prototype);
1018
0
        self->udp.egress.delayed = (h2o_timer_t){.cb = udp_write_stream_complete_delayed};
1019
0
        self->udp.is_draft03 = is_masque_draft03;
1020
0
    }
1021
0
    h2o_timer_link(get_loop(self), handler->config.connect_timeout, &self->timeout);
1022
1023
    /* setup write_req now, so that the protocol handler would not provide additional data until we call `proceed_req` */
1024
0
    assert(req->entity.base != NULL && "CONNECT must indicate existence of payload");
1025
0
    self->src_req->write_req.cb = is_tcp ? tcp_write : udp_write_stream;
1026
0
    self->src_req->write_req.ctx = self;
1027
0
    if (self->src_req->proceed_req == NULL)
1028
0
        self->no_req_streaming = 1;
1029
1030
0
    char port_str[sizeof(H2O_UINT16_LONGEST_STR)];
1031
0
    int port_strlen = sprintf(port_str, "%" PRIu16, port);
1032
1033
0
    self->getaddr_req.v6 = h2o_hostinfo_getaddr(
1034
0
        &self->src_req->conn->ctx->receivers.hostinfo_getaddr, host, h2o_iovec_init(port_str, port_strlen), AF_INET6,
1035
0
        is_tcp ? SOCK_STREAM : SOCK_DGRAM, is_tcp ? IPPROTO_TCP : IPPROTO_UDP, AI_ADDRCONFIG | AI_NUMERICSERV, on_getaddr, self);
1036
0
    self->getaddr_req.v4 = h2o_hostinfo_getaddr(
1037
0
        &self->src_req->conn->ctx->receivers.hostinfo_getaddr, host, h2o_iovec_init(port_str, port_strlen), AF_INET,
1038
0
        is_tcp ? SOCK_STREAM : SOCK_DGRAM, is_tcp ? IPPROTO_TCP : IPPROTO_UDP, AI_ADDRCONFIG | AI_NUMERICSERV, on_getaddr, self);
1039
1040
0
    return 0;
1041
0
}
1042
1043
static int on_req_classic_connect(h2o_handler_t *_handler, h2o_req_t *req)
1044
0
{
1045
0
    struct st_connect_handler_t *handler = (void *)_handler;
1046
0
    h2o_iovec_t host;
1047
0
    uint16_t port;
1048
0
    int is_tcp;
1049
1050
0
    if (req->upgrade.base != NULL) {
1051
0
        return -1;
1052
0
    } else if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("CONNECT"))) {
1053
        /* old-style CONNECT */
1054
0
        is_tcp = 1;
1055
0
    } else if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("CONNECT-UDP"))) {
1056
        /* masque (draft 03); host and port are stored the same way as ordinary CONNECT
1057
         * TODO remove code once we drop support for draft-03 */
1058
0
        if (!handler->config.support_masque_draft_03) {
1059
0
            h2o_send_error_405(req, "Method Not Allowed", "Method Not Allowed", H2O_SEND_ERROR_KEEP_HEADERS);
1060
0
            return 0;
1061
0
        }
1062
0
        is_tcp = 0;
1063
0
    } else {
1064
        /* it is not the task of this handler to handle non-CONNECT requests */
1065
0
        return -1;
1066
0
    }
1067
1068
    /* parse host and port from authority, unless it is handled above in the case of extended connect */
1069
0
    if (h2o_url_parse_hostport(req->authority.base, req->authority.len, &host, &port) == NULL || port == 0 || port == 65535) {
1070
0
        record_error(handler, req, NULL, "http_request_error", "invalid host:port", NULL);
1071
0
        h2o_send_error_400(req, "Bad Request", "Bad Request", H2O_SEND_ERROR_KEEP_HEADERS);
1072
0
        return 0;
1073
0
    }
1074
1075
0
    return on_req_core((void *)handler, req, host, port, is_tcp, 1);
1076
0
}
1077
1078
/**
1079
 * handles RFC9298 requests
1080
 */
1081
static int on_req_connect_udp(h2o_handler_t *_handler, h2o_req_t *req)
1082
0
{
1083
0
    struct st_connect_handler_t *handler = (void *)_handler;
1084
0
    h2o_iovec_t host;
1085
0
    uint16_t port;
1086
1087
    /* reject requests wo. upgrade: connect-udp */
1088
0
    if (!(req->upgrade.base != NULL && h2o_lcstris(req->upgrade.base, req->upgrade.len, H2O_STRLIT("connect-udp"))))
1089
0
        return -1;
1090
1091
    /* check method */
1092
0
    if (!(req->version < 0x200 ? h2o_memis(req->method.base, req->method.len, H2O_STRLIT("GET"))
1093
0
                               : h2o_memis(req->method.base, req->method.len, H2O_STRLIT("CONNECT"))))
1094
0
        return -1;
1095
1096
    /* masque (RFC 9298); parse host/port */
1097
0
    if (!masque_decode_hostport(&req->pool, req->path_normalized.base + req->pathconf->path.len,
1098
0
                                req->path_normalized.len - req->pathconf->path.len, &host, &port)) {
1099
0
        record_error(handler, req, NULL, "http_request_error", "invalid URI", NULL);
1100
0
        h2o_send_error_400(req, "Bad Request", "Bad Request", H2O_SEND_ERROR_KEEP_HEADERS);
1101
0
        return 0;
1102
0
    }
1103
1104
0
    return on_req_core((void *)handler, req, host, port, 0, 0);
1105
0
}
1106
1107
static void do_register(h2o_pathconf_t *pathconf, h2o_proxy_config_vars_t *config, h2o_connect_acl_entry_t *acl_entries,
1108
                        size_t num_acl_entries, int (*on_req)(struct st_h2o_handler_t *self, h2o_req_t *req))
1109
0
{
1110
0
    assert(config->max_buffer_size != 0);
1111
1112
0
    struct st_connect_handler_t *self = (void *)h2o_create_handler(pathconf, offsetof(struct st_connect_handler_t, acl.entries) +
1113
0
                                                                                 sizeof(*self->acl.entries) * num_acl_entries);
1114
1115
0
    self->super.on_req = on_req;
1116
0
    self->super.supports_request_streaming = 1;
1117
0
    self->config = *config;
1118
0
    self->acl.count = num_acl_entries;
1119
0
    memcpy(self->acl.entries, acl_entries, sizeof(self->acl.entries[0]) * num_acl_entries);
1120
0
}
1121
1122
void h2o_connect_register(h2o_pathconf_t *pathconf, h2o_proxy_config_vars_t *config, h2o_connect_acl_entry_t *acl_entries,
1123
                          size_t num_acl_entries)
1124
0
{
1125
0
    do_register(pathconf, config, acl_entries, num_acl_entries, on_req_classic_connect);
1126
0
}
1127
1128
void h2o_connect_udp_register(h2o_pathconf_t *pathconf, h2o_proxy_config_vars_t *config, h2o_connect_acl_entry_t *acl_entries,
1129
                              size_t num_acl_entries)
1130
0
{
1131
0
    do_register(pathconf, config, acl_entries, num_acl_entries, on_req_connect_udp);
1132
0
}
1133
1134
/**
1135
 * Parses a decimal number at the beginning of [*s, end), advancing *s past the digits consumed. Returns the parsed value, or -1 if
1136
 * no digit is found or the value would not fit in a non-negative int. The caller is responsible for range-checking the result.
1137
 */
1138
static int parse_decimal(const char **s, const char *end)
1139
0
{
1140
0
    const char *start = *s;
1141
0
    int v = 0;
1142
1143
0
    for (; *s != end && '0' <= **s && **s <= '9'; ++*s) {
1144
0
        int digit = **s - '0';
1145
        /* reject if `v * 10 + digit` would overflow INT_MAX, checked before the multiply to avoid relying on a wider type */
1146
0
        if (v > (INT_MAX - digit) / 10)
1147
0
            return -1;
1148
0
        v = v * 10 + digit;
1149
0
    }
1150
0
    if (*s == start)
1151
0
        return -1;
1152
0
    return v;
1153
0
}
1154
1155
/**
1156
 * Parse an ACL host/mask:port specification.
1157
 * Accepted format: host[/mask][:port[-port]] (the netmask may also appear after the port, e.g. host:port/mask, for backward
1158
 * compatibility). A port of `*` means any port, same as omitting it.
1159
 * Examples: 10.0.0.0/8:80-443, [::1]:443, *:25, 127.0.0.1/32, 127.0.0.1:25/24, 127.0.0.1:*, local
1160
 * Returns pointer to first unparsed character on success, NULL on error.
1161
 */
1162
static const char *parse_acl_hostport(const char *s, size_t len, h2o_iovec_t *host, size_t *addr_mask, uint16_t *port_min,
1163
                                      uint16_t *port_max)
1164
0
{
1165
0
    const char *token_start = s, *token_end, *end = s + len;
1166
1167
    /* default to matching any port; overridden below if a port or range is given */
1168
0
    *port_min = 0;
1169
0
    *port_max = 65535;
1170
0
    *addr_mask = 0;
1171
1172
0
    if (token_start == end)
1173
0
        return NULL;
1174
1175
    /* parse host */
1176
0
    if (*token_start == '[') {
1177
        /* IPv6 address in brackets */
1178
0
        ++token_start;
1179
0
        if ((token_end = memchr(token_start, ']', end - token_start)) == NULL)
1180
0
            return NULL;
1181
0
        *host = h2o_iovec_init(token_start, token_end - token_start);
1182
0
        token_start = token_end + 1;
1183
0
    } else {
1184
0
        for (token_end = token_start; !(token_end == end || *token_end == '/' || *token_end == ':'); ++token_end)
1185
0
            ;
1186
0
        *host = h2o_iovec_init(token_start, token_end - token_start);
1187
0
        token_start = token_end;
1188
0
    }
1189
1190
    /* disallow zero-length host */
1191
0
    if (host->len == 0)
1192
0
        return NULL;
1193
1194
    /* parse optional /mask appearing before the port (e.g. 10.0.0.0/8:80) */
1195
0
    if (token_start != end && *token_start == '/') {
1196
0
        int mask;
1197
0
        ++token_start;
1198
0
        if ((mask = parse_decimal(&token_start, end)) <= 0)
1199
0
            return NULL;
1200
0
        *addr_mask = mask;
1201
0
    }
1202
1203
    /* parse optional :port, :port-port, or :* (any port) */
1204
0
    if (token_start != end && *token_start == ':') {
1205
0
        ++token_start;
1206
0
        if (token_start != end && *token_start == '*') {
1207
            /* `:*` means any port; leave the default full range in place */
1208
0
            ++token_start;
1209
0
        } else {
1210
0
            int p;
1211
0
            if ((p = parse_decimal(&token_start, end)) < 0 || p > 65535)
1212
0
                return NULL;
1213
0
            *port_min = (uint16_t)p;
1214
0
            if (token_start != end && *token_start == '-') {
1215
0
                ++token_start;
1216
0
                if ((p = parse_decimal(&token_start, end)) < 0 || p > 65535)
1217
0
                    return NULL;
1218
0
            }
1219
0
            *port_max = (uint16_t)p;
1220
0
        }
1221
0
    }
1222
1223
    /* parse optional /mask appearing after the port (legacy order, e.g. 10.0.0.0:80/8) */
1224
0
    if (token_start != end && *token_start == '/') {
1225
0
        int mask;
1226
0
        if (*addr_mask != 0) /* mask already given before the port */
1227
0
            return NULL;
1228
0
        ++token_start;
1229
0
        if ((mask = parse_decimal(&token_start, end)) <= 0)
1230
0
            return NULL;
1231
0
        *addr_mask = mask;
1232
0
    }
1233
1234
0
    return token_start;
1235
0
}
1236
1237
const char *h2o_connect_parse_acl(h2o_connect_acl_entry_t *output, const char *input)
1238
0
{
1239
    /* type */
1240
0
    switch (input[0]) {
1241
0
    case '+':
1242
0
        output->allow_ = 1;
1243
0
        break;
1244
0
    case '-':
1245
0
        output->allow_ = 0;
1246
0
        break;
1247
0
    default:
1248
0
        return "ACL entry must begin with + or -";
1249
0
    }
1250
1251
    /* extract address, optional netmask, optional port or port range. Port ranges are INCLUSIVE on both min and max */
1252
0
    h2o_iovec_t host_vec;
1253
0
    uint16_t port_min, port_max;
1254
0
    const char *rest;
1255
0
    if ((rest = parse_acl_hostport(input + 1, strlen(input + 1), &host_vec, &output->addr_mask, &port_min, &port_max)) == NULL)
1256
0
        goto GenericParseError;
1257
0
    if (*rest != '\0')
1258
0
        goto GenericParseError;
1259
0
    char *host = alloca(host_vec.len + 1);
1260
0
    memcpy(host, host_vec.base, host_vec.len);
1261
0
    host[host_vec.len] = '\0';
1262
1263
    /* parse address */
1264
0
    struct in_addr v4addr;
1265
0
    struct in6_addr v6addr;
1266
0
    if (strcmp(host, "*") == 0) {
1267
0
        output->addr_family = H2O_CONNECT_ACL_ADDRESS_ANY;
1268
0
        if (output->addr_mask != 0)
1269
0
            return "wildcard address (*) cannot have a netmask";
1270
0
    } else if (inet_pton(AF_INET, host, &v4addr) == 1) {
1271
0
        output->addr_family = H2O_CONNECT_ACL_ADDRESS_V4;
1272
0
        if (output->addr_mask == 0) {
1273
0
            output->addr_mask = 32;
1274
0
        } else if (output->addr_mask > 32) {
1275
0
            return "invalid address mask";
1276
0
        }
1277
0
        output->addr.v4 = ntohl(v4addr.s_addr) & TO_BITMASK(uint32_t, output->addr_mask);
1278
0
    } else if (inet_pton(AF_INET6, host, &v6addr) == 1) {
1279
0
        output->addr_family = H2O_CONNECT_ACL_ADDRESS_V6;
1280
0
        if (output->addr_mask == 0) {
1281
0
            output->addr_mask = 128;
1282
0
        } else if (output->addr_mask > 128) {
1283
0
            return "invalid address mask";
1284
0
        }
1285
0
        size_t i;
1286
0
        for (i = 0; i < output->addr_mask / 8; ++i)
1287
0
            output->addr.v6[i] = v6addr.s6_addr[i];
1288
0
        if (output->addr_mask % 8 != 0)
1289
0
            output->addr.v6[i] = v6addr.s6_addr[i] & TO_BITMASK(uint8_t, output->addr_mask % 8);
1290
0
        for (++i; i < PTLS_ELEMENTSOF(output->addr.v6); ++i)
1291
0
            output->addr.v6[i] = 0;
1292
0
    } else {
1293
0
        return "failed to parse address";
1294
0
    }
1295
1296
0
    if (port_max < port_min)
1297
0
        return "port range end must be >= start";
1298
1299
0
    output->port_min = port_min;
1300
0
    output->port_max = port_max;
1301
1302
0
    return NULL;
1303
1304
0
GenericParseError:
1305
0
    return "failed to parse input, expected format is: [+-]address[/netmask][:port[-port]]";
1306
0
}
1307
1308
int h2o_connect_lookup_acl(h2o_connect_acl_entry_t *acl_entries, size_t num_acl_entries, struct sockaddr *target)
1309
0
{
1310
0
    uint32_t target_v4addr = 0;
1311
0
    uint16_t target_port;
1312
1313
    /* reject anything other than v4/v6, as well as converting the values to native format */
1314
0
    switch (target->sa_family) {
1315
0
    case AF_INET: {
1316
0
        struct sockaddr_in *sin = (void *)target;
1317
0
        target_v4addr = ntohl(sin->sin_addr.s_addr);
1318
0
        target_port = ntohs(sin->sin_port);
1319
0
    } break;
1320
0
    case AF_INET6:
1321
0
        target_port = htons(((struct sockaddr_in6 *)target)->sin6_port);
1322
0
        break;
1323
0
    default:
1324
0
        return 0;
1325
0
    }
1326
1327
    /* check each ACL entry */
1328
0
    for (size_t i = 0; i != num_acl_entries; ++i) {
1329
0
        h2o_connect_acl_entry_t *entry = acl_entries + i;
1330
        /* check port */
1331
0
        if (target_port < entry->port_min || target_port > entry->port_max)
1332
0
            goto Next;
1333
        /* check address */
1334
0
        switch (entry->addr_family) {
1335
0
        case H2O_CONNECT_ACL_ADDRESS_ANY:
1336
0
            break;
1337
0
        case H2O_CONNECT_ACL_ADDRESS_V4: {
1338
0
            if (target->sa_family != AF_INET)
1339
0
                goto Next;
1340
0
            if (entry->addr.v4 != (target_v4addr & TO_BITMASK(uint32_t, entry->addr_mask)))
1341
0
                goto Next;
1342
0
        } break;
1343
0
        case H2O_CONNECT_ACL_ADDRESS_V6: {
1344
0
            if (target->sa_family != AF_INET6)
1345
0
                continue;
1346
0
            uint8_t *target_v6addr = ((struct sockaddr_in6 *)target)->sin6_addr.s6_addr;
1347
0
            size_t i;
1348
0
            for (i = 0; i < entry->addr_mask / 8; ++i)
1349
0
                if (entry->addr.v6[i] != target_v6addr[i])
1350
0
                    goto Next;
1351
0
            if (entry->addr_mask % 8 != 0 && entry->addr.v6[i] != (target_v6addr[i] & TO_BITMASK(uint8_t, entry->addr_mask % 8)))
1352
0
                goto Next;
1353
0
        } break;
1354
0
        }
1355
        /* match */
1356
0
        return entry->allow_;
1357
0
    Next:;
1358
0
    }
1359
1360
    /* default rule is deny */
1361
0
    return 0;
1362
0
}