/src/openssl34/ssl/quic/quic_port.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include "internal/quic_port.h" |
11 | | #include "internal/quic_channel.h" |
12 | | #include "internal/quic_lcidm.h" |
13 | | #include "internal/quic_srtm.h" |
14 | | #include "quic_port_local.h" |
15 | | #include "quic_channel_local.h" |
16 | | #include "quic_engine_local.h" |
17 | | #include "../ssl_local.h" |
18 | | |
19 | | /* |
20 | | * QUIC Port Structure |
21 | | * =================== |
22 | | */ |
23 | 20.9k | #define INIT_DCID_LEN 8 |
24 | | |
25 | | static int port_init(QUIC_PORT *port); |
26 | | static void port_cleanup(QUIC_PORT *port); |
27 | | static OSSL_TIME get_time(void *arg); |
28 | | static void port_default_packet_handler(QUIC_URXE *e, void *arg, |
29 | | const QUIC_CONN_ID *dcid); |
30 | | static void port_rx_pre(QUIC_PORT *port); |
31 | | |
32 | 141M | DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); quic_port.c:ossl_list_ch_head Line | Count | Source | 32 | | DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); |
quic_port.c:ossl_list_ch_next Line | Count | Source | 32 | | DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); |
|
33 | 101k | DEFINE_LIST_OF_IMPL(port, QUIC_PORT); quic_port.c:ossl_list_port_insert_tail Line | Count | Source | 33 | | DEFINE_LIST_OF_IMPL(port, QUIC_PORT); |
quic_port.c:ossl_list_port_remove Line | Count | Source | 33 | | DEFINE_LIST_OF_IMPL(port, QUIC_PORT); |
|
34 | | |
35 | | QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) |
36 | 50.6k | { |
37 | 50.6k | QUIC_PORT *port; |
38 | | |
39 | 50.6k | if ((port = OPENSSL_zalloc(sizeof(QUIC_PORT))) == NULL) |
40 | 0 | return NULL; |
41 | | |
42 | 50.6k | port->engine = args->engine; |
43 | 50.6k | port->channel_ctx = args->channel_ctx; |
44 | 50.6k | port->is_multi_conn = args->is_multi_conn; |
45 | | |
46 | 50.6k | if (!port_init(port)) { |
47 | 0 | OPENSSL_free(port); |
48 | 0 | return NULL; |
49 | 0 | } |
50 | | |
51 | 50.6k | return port; |
52 | 50.6k | } |
53 | | |
54 | | void ossl_quic_port_free(QUIC_PORT *port) |
55 | 50.6k | { |
56 | 50.6k | if (port == NULL) |
57 | 0 | return; |
58 | | |
59 | 50.6k | port_cleanup(port); |
60 | 50.6k | OPENSSL_free(port); |
61 | 50.6k | } |
62 | | |
63 | | static int port_init(QUIC_PORT *port) |
64 | 20.9k | { |
65 | 20.9k | size_t rx_short_dcid_len = (port->is_multi_conn ? INIT_DCID_LEN : 0); |
66 | | |
67 | 20.9k | if (port->engine == NULL || port->channel_ctx == NULL) |
68 | 0 | goto err; |
69 | | |
70 | 20.9k | if ((port->err_state = OSSL_ERR_STATE_new()) == NULL) |
71 | 0 | goto err; |
72 | | |
73 | 20.9k | if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL, |
74 | 20.9k | /*Short CID Len=*/rx_short_dcid_len, |
75 | 20.9k | get_time, port)) |
76 | 20.9k | == NULL) |
77 | 0 | goto err; |
78 | | |
79 | 20.9k | ossl_quic_demux_set_default_handler(port->demux, |
80 | 20.9k | port_default_packet_handler, |
81 | 20.9k | port); |
82 | | |
83 | 20.9k | if ((port->srtm = ossl_quic_srtm_new(port->engine->libctx, |
84 | 20.9k | port->engine->propq)) |
85 | 20.9k | == NULL) |
86 | 0 | goto err; |
87 | | |
88 | 20.9k | if ((port->lcidm = ossl_quic_lcidm_new(port->engine->libctx, |
89 | 20.9k | rx_short_dcid_len)) |
90 | 20.9k | == NULL) |
91 | 0 | goto err; |
92 | | |
93 | 20.9k | port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; |
94 | 20.9k | port->tx_init_dcid_len = INIT_DCID_LEN; |
95 | 20.9k | port->state = QUIC_PORT_STATE_RUNNING; |
96 | | |
97 | 20.9k | ossl_list_port_insert_tail(&port->engine->port_list, port); |
98 | 20.9k | port->on_engine_list = 1; |
99 | 20.9k | return 1; |
100 | | |
101 | 0 | err: |
102 | 0 | port_cleanup(port); |
103 | 0 | return 0; |
104 | 20.9k | } |
105 | | |
106 | | static void port_cleanup(QUIC_PORT *port) |
107 | 50.6k | { |
108 | 50.6k | assert(ossl_list_ch_num(&port->channel_list) == 0); |
109 | | |
110 | 50.6k | ossl_quic_demux_free(port->demux); |
111 | 50.6k | port->demux = NULL; |
112 | | |
113 | 50.6k | ossl_quic_srtm_free(port->srtm); |
114 | 50.6k | port->srtm = NULL; |
115 | | |
116 | 50.6k | ossl_quic_lcidm_free(port->lcidm); |
117 | 50.6k | port->lcidm = NULL; |
118 | | |
119 | 50.6k | OSSL_ERR_STATE_free(port->err_state); |
120 | 50.6k | port->err_state = NULL; |
121 | | |
122 | 50.6k | if (port->on_engine_list) { |
123 | 50.6k | ossl_list_port_remove(&port->engine->port_list, port); |
124 | 50.6k | port->on_engine_list = 0; |
125 | 50.6k | } |
126 | 50.6k | } |
127 | | |
128 | | static void port_transition_failed(QUIC_PORT *port) |
129 | 0 | { |
130 | 0 | if (port->state == QUIC_PORT_STATE_FAILED) |
131 | 0 | return; |
132 | | |
133 | 0 | port->state = QUIC_PORT_STATE_FAILED; |
134 | 0 | } |
135 | | |
136 | | int ossl_quic_port_is_running(const QUIC_PORT *port) |
137 | 121M | { |
138 | 121M | return port->state == QUIC_PORT_STATE_RUNNING; |
139 | 121M | } |
140 | | |
141 | | QUIC_ENGINE *ossl_quic_port_get0_engine(QUIC_PORT *port) |
142 | 0 | { |
143 | 0 | return port->engine; |
144 | 0 | } |
145 | | |
146 | | QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) |
147 | 88.5M | { |
148 | 88.5M | return ossl_quic_engine_get0_reactor(port->engine); |
149 | 88.5M | } |
150 | | |
151 | | QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port) |
152 | 0 | { |
153 | 0 | return port->demux; |
154 | 0 | } |
155 | | |
156 | | CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port) |
157 | 0 | { |
158 | 0 | return ossl_quic_engine_get0_mutex(port->engine); |
159 | 0 | } |
160 | | |
161 | | OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port) |
162 | 189M | { |
163 | 189M | return ossl_quic_engine_get_time(port->engine); |
164 | 189M | } |
165 | | |
166 | | static OSSL_TIME get_time(void *port) |
167 | 9.04M | { |
168 | 9.04M | return ossl_quic_port_get_time((QUIC_PORT *)port); |
169 | 9.04M | } |
170 | | |
171 | | int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port) |
172 | 50.4k | { |
173 | 50.4k | return port->rx_short_dcid_len; |
174 | 50.4k | } |
175 | | |
176 | | int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port) |
177 | 50.4k | { |
178 | 50.4k | return port->tx_init_dcid_len; |
179 | 50.4k | } |
180 | | |
181 | | /* |
182 | | * QUIC Port: Network BIO Configuration |
183 | | * ==================================== |
184 | | */ |
185 | | |
186 | | /* Determines whether we can support a given poll descriptor. */ |
187 | | static int validate_poll_descriptor(const BIO_POLL_DESCRIPTOR *d) |
188 | 96.1M | { |
189 | 96.1M | if (d->type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD && d->value.fd < 0) { |
190 | 0 | ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); |
191 | 0 | return 0; |
192 | 0 | } |
193 | | |
194 | 96.1M | return 1; |
195 | 96.1M | } |
196 | | |
197 | | BIO *ossl_quic_port_get_net_rbio(QUIC_PORT *port) |
198 | 26.3M | { |
199 | 26.3M | return port->net_rbio; |
200 | 26.3M | } |
201 | | |
202 | | BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port) |
203 | 26.3M | { |
204 | 26.3M | return port->net_wbio; |
205 | 26.3M | } |
206 | | |
207 | | static int port_update_poll_desc(QUIC_PORT *port, BIO *net_bio, int for_write) |
208 | 96.1M | { |
209 | 96.1M | BIO_POLL_DESCRIPTOR d = { 0 }; |
210 | | |
211 | 96.1M | if (net_bio == NULL |
212 | 96.1M | || (!for_write && !BIO_get_rpoll_descriptor(net_bio, &d)) |
213 | 48.0M | || (for_write && !BIO_get_wpoll_descriptor(net_bio, &d))) |
214 | | /* Non-pollable BIO */ |
215 | 96.1M | d.type = BIO_POLL_DESCRIPTOR_TYPE_NONE; |
216 | | |
217 | 96.1M | if (!validate_poll_descriptor(&d)) |
218 | 0 | return 0; |
219 | | |
220 | | /* |
221 | | * TODO(QUIC MULTIPORT): We currently only support one port per |
222 | | * engine/domain. This is necessitated because QUIC_REACTOR only supports a |
223 | | * single pollable currently. In the future, once complete polling |
224 | | * infrastructure has been implemented, this limitation can be removed. |
225 | | * |
226 | | * For now, just update the descriptor on the engine's reactor as we are |
227 | | * guaranteed to be the only port under it. |
228 | | */ |
229 | 96.1M | if (for_write) |
230 | 48.0M | ossl_quic_reactor_set_poll_w(&port->engine->rtor, &d); |
231 | 48.0M | else |
232 | 48.0M | ossl_quic_reactor_set_poll_r(&port->engine->rtor, &d); |
233 | | |
234 | 96.1M | return 1; |
235 | 96.1M | } |
236 | | |
237 | | int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port) |
238 | 21.7M | { |
239 | 21.7M | int ok = 1; |
240 | | |
241 | 21.7M | if (!port_update_poll_desc(port, port->net_rbio, /*for_write=*/0)) |
242 | 0 | ok = 0; |
243 | | |
244 | 21.7M | if (!port_update_poll_desc(port, port->net_wbio, /*for_write=*/1)) |
245 | 0 | ok = 0; |
246 | | |
247 | 21.7M | return ok; |
248 | 21.7M | } |
249 | | |
250 | | /* |
251 | | * QUIC_PORT does not ref any BIO it is provided with, nor is any ref |
252 | | * transferred to it. The caller (e.g., QUIC_CONNECTION) is responsible for |
253 | | * ensuring the BIO lasts until the channel is freed or the BIO is switched out |
254 | | * for another BIO by a subsequent successful call to this function. |
255 | | */ |
256 | | int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio) |
257 | 71.5k | { |
258 | 71.5k | if (port->net_rbio == net_rbio) |
259 | 20.9k | return 1; |
260 | | |
261 | 50.6k | if (!port_update_poll_desc(port, net_rbio, /*for_write=*/0)) |
262 | 0 | return 0; |
263 | | |
264 | 50.6k | ossl_quic_demux_set_bio(port->demux, net_rbio); |
265 | 50.6k | port->net_rbio = net_rbio; |
266 | 50.6k | return 1; |
267 | 50.6k | } |
268 | | |
269 | | int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio) |
270 | 71.5k | { |
271 | 71.5k | QUIC_CHANNEL *ch; |
272 | | |
273 | 71.5k | if (port->net_wbio == net_wbio) |
274 | 20.9k | return 1; |
275 | | |
276 | 50.6k | if (!port_update_poll_desc(port, net_wbio, /*for_write=*/1)) |
277 | 0 | return 0; |
278 | | |
279 | 50.6k | OSSL_LIST_FOREACH(ch, ch, &port->channel_list) |
280 | 50.4k | ossl_qtx_set_bio(ch->qtx, net_wbio); |
281 | | |
282 | 50.6k | port->net_wbio = net_wbio; |
283 | 50.6k | return 1; |
284 | 50.6k | } |
285 | | |
286 | | /* |
287 | | * QUIC Port: Channel Lifecycle |
288 | | * ============================ |
289 | | */ |
290 | | |
291 | | static SSL *port_new_handshake_layer(QUIC_PORT *port) |
292 | 0 | { |
293 | 0 | SSL *tls = NULL; |
294 | 0 | SSL_CONNECTION *tls_conn = NULL; |
295 | |
|
296 | 0 | tls = ossl_ssl_connection_new_int(port->channel_ctx, NULL, TLS_method()); |
297 | 0 | if (tls == NULL || (tls_conn = SSL_CONNECTION_FROM_SSL(tls)) == NULL) |
298 | 0 | return NULL; |
299 | | |
300 | | /* Override the user_ssl of the inner connection. */ |
301 | 0 | tls_conn->s3.flags |= TLS1_FLAGS_QUIC; |
302 | | |
303 | | /* Restrict options derived from the SSL_CTX. */ |
304 | 0 | tls_conn->options &= OSSL_QUIC_PERMITTED_OPTIONS_CONN; |
305 | 0 | tls_conn->pha_enabled = 0; |
306 | 0 | return tls; |
307 | 0 | } |
308 | | |
309 | | static QUIC_CHANNEL *port_make_channel(QUIC_PORT *port, SSL *tls, int is_server) |
310 | 20.9k | { |
311 | 20.9k | QUIC_CHANNEL_ARGS args = { 0 }; |
312 | 20.9k | QUIC_CHANNEL *ch; |
313 | | |
314 | 20.9k | args.port = port; |
315 | 20.9k | args.is_server = is_server; |
316 | 20.9k | args.tls = (tls != NULL ? tls : port_new_handshake_layer(port)); |
317 | 20.9k | args.lcidm = port->lcidm; |
318 | 20.9k | args.srtm = port->srtm; |
319 | 20.9k | if (args.tls == NULL) |
320 | 0 | return NULL; |
321 | | |
322 | 20.9k | #ifndef OPENSSL_NO_QLOG |
323 | 20.9k | args.use_qlog = 1; /* disabled if env not set */ |
324 | 20.9k | args.qlog_title = args.tls->ctx->qlog_title; |
325 | 20.9k | #endif |
326 | | |
327 | 20.9k | ch = ossl_quic_channel_new(&args); |
328 | 20.9k | if (ch == NULL) { |
329 | 0 | if (tls == NULL) |
330 | 0 | SSL_free(args.tls); |
331 | |
|
332 | 0 | return NULL; |
333 | 0 | } |
334 | | |
335 | 20.9k | return ch; |
336 | 20.9k | } |
337 | | |
338 | | QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls) |
339 | 50.4k | { |
340 | 50.4k | return port_make_channel(port, tls, /*is_server=*/0); |
341 | 50.4k | } |
342 | | |
343 | | QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) |
344 | 0 | { |
345 | 0 | QUIC_CHANNEL *ch; |
346 | |
|
347 | 0 | assert(port->tserver_ch == NULL); |
348 | |
|
349 | 0 | ch = port_make_channel(port, tls, /*is_server=*/1); |
350 | 0 | port->tserver_ch = ch; |
351 | 0 | port->is_server = 1; |
352 | 0 | return ch; |
353 | 0 | } |
354 | | |
355 | | /* |
356 | | * QUIC Port: Ticker-Mutator |
357 | | * ========================= |
358 | | */ |
359 | | |
360 | | /* |
361 | | * Tick function for this port. This does everything related to network I/O for |
362 | | * this port's network BIOs, and services child channels. |
363 | | */ |
364 | | void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *res, |
365 | | uint32_t flags) |
366 | 70.6M | { |
367 | 70.6M | QUIC_CHANNEL *ch; |
368 | | |
369 | 70.6M | res->net_read_desired = 0; |
370 | 70.6M | res->net_write_desired = 0; |
371 | 70.6M | res->tick_deadline = ossl_time_infinite(); |
372 | | |
373 | 70.6M | if (!port->engine->inhibit_tick) { |
374 | | /* Handle any incoming data from network. */ |
375 | 70.6M | if (ossl_quic_port_is_running(port)) |
376 | 70.6M | port_rx_pre(port); |
377 | | |
378 | | /* Iterate through all channels and service them. */ |
379 | 70.6M | OSSL_LIST_FOREACH(ch, ch, &port->channel_list) |
380 | 70.6M | { |
381 | 70.6M | QUIC_TICK_RESULT subr = { 0 }; |
382 | | |
383 | 70.6M | ossl_quic_channel_subtick(ch, &subr, flags); |
384 | 70.6M | ossl_quic_tick_result_merge_into(res, &subr); |
385 | 70.6M | } |
386 | 70.6M | } |
387 | 70.6M | } |
388 | | |
389 | | /* Process incoming datagrams, if any. */ |
390 | | static void port_rx_pre(QUIC_PORT *port) |
391 | 70.6M | { |
392 | 70.6M | int ret; |
393 | | |
394 | | /* |
395 | | * Originally, this check (don't RX before we have sent anything if we are |
396 | | * not a server, because there can't be anything) was just intended as a |
397 | | * minor optimisation. However, it is actually required on Windows, and |
398 | | * removing this check will cause Windows to break. |
399 | | * |
400 | | * The reason is that under Win32, recvfrom() does not work on a UDP socket |
401 | | * which has not had bind() called (???). However, calling sendto() will |
402 | | * automatically bind an unbound UDP socket. Therefore, if we call a Winsock |
403 | | * recv-type function before calling a Winsock send-type function, that call |
404 | | * will fail with WSAEINVAL, which we will regard as a permanent network |
405 | | * error. |
406 | | * |
407 | | * Therefore, this check is essential as we do not require our API users to |
408 | | * bind a socket first when using the API in client mode. |
409 | | */ |
410 | 70.6M | if (!port->is_server && !port->have_sent_any_pkt) |
411 | 50.4k | return; |
412 | | |
413 | | /* |
414 | | * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams |
415 | | * to the appropriate QRX instances. |
416 | | */ |
417 | 70.5M | ret = ossl_quic_demux_pump(port->demux); |
418 | 70.5M | if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) |
419 | | /* |
420 | | * We don't care about transient failure, but permanent failure means we |
421 | | * should tear down the port. All connections skip straight to the |
422 | | * Terminated state as there is no point trying to send CONNECTION_CLOSE |
423 | | * frames if the network BIO is not operating correctly. |
424 | | */ |
425 | 0 | ossl_quic_port_raise_net_error(port, NULL); |
426 | 70.5M | } |
427 | | |
428 | | /* |
429 | | * Handles an incoming connection request and potentially decides to make a |
430 | | * connection from it. If a new connection is made, the new channel is written |
431 | | * to *new_ch. |
432 | | */ |
433 | | static void port_on_new_conn(QUIC_PORT *port, const BIO_ADDR *peer, |
434 | | const QUIC_CONN_ID *scid, |
435 | | const QUIC_CONN_ID *dcid, |
436 | | QUIC_CHANNEL **new_ch) |
437 | 0 | { |
438 | 0 | if (port->tserver_ch != NULL) { |
439 | | /* Specially assign to existing channel */ |
440 | 0 | if (!ossl_quic_channel_on_new_conn(port->tserver_ch, peer, scid, dcid)) |
441 | 0 | return; |
442 | | |
443 | 0 | *new_ch = port->tserver_ch; |
444 | 0 | port->tserver_ch = NULL; |
445 | 0 | return; |
446 | 0 | } |
447 | 0 | } |
448 | | |
449 | | static int port_try_handle_stateless_reset(QUIC_PORT *port, const QUIC_URXE *e) |
450 | 11.7M | { |
451 | 11.7M | size_t i; |
452 | 11.7M | const unsigned char *data = ossl_quic_urxe_data(e); |
453 | 11.7M | void *opaque = NULL; |
454 | | |
455 | | /* |
456 | | * Perform some fast and cheap checks for a packet not being a stateless |
457 | | * reset token. RFC 9000 s. 10.3 specifies this layout for stateless |
458 | | * reset packets: |
459 | | * |
460 | | * Stateless Reset { |
461 | | * Fixed Bits (2) = 1, |
462 | | * Unpredictable Bits (38..), |
463 | | * Stateless Reset Token (128), |
464 | | * } |
465 | | * |
466 | | * It also specifies: |
467 | | * However, endpoints MUST treat any packet ending in a valid |
468 | | * stateless reset token as a Stateless Reset, as other QUIC |
469 | | * versions might allow the use of a long header. |
470 | | * |
471 | | * We can rapidly check for the minimum length and that the first pair |
472 | | * of bits in the first byte are 01 or 11. |
473 | | * |
474 | | * The function returns 1 if it is a stateless reset packet, 0 if it isn't |
475 | | * and -1 if an error was encountered. |
476 | | */ |
477 | 11.7M | if (e->data_len < QUIC_STATELESS_RESET_TOKEN_LEN + 5 |
478 | 4.98M | || (0100 & *data) != 0100) |
479 | 7.24M | return 0; |
480 | | |
481 | 4.50M | for (i = 0;; ++i) { |
482 | 4.50M | if (!ossl_quic_srtm_lookup(port->srtm, |
483 | 4.50M | (QUIC_STATELESS_RESET_TOKEN *)(data + e->data_len |
484 | 4.50M | - sizeof(QUIC_STATELESS_RESET_TOKEN)), |
485 | 4.50M | i, &opaque, NULL)) |
486 | 4.50M | break; |
487 | | |
488 | 4.50M | assert(opaque != NULL); |
489 | 22 | ossl_quic_channel_on_stateless_reset((QUIC_CHANNEL *)opaque); |
490 | 22 | } |
491 | | |
492 | 4.50M | return i > 0; |
493 | 4.50M | } |
494 | | |
495 | | /* |
496 | | * This is called by the demux when we get a packet not destined for any known |
497 | | * DCID. |
498 | | */ |
499 | | static void port_default_packet_handler(QUIC_URXE *e, void *arg, |
500 | | const QUIC_CONN_ID *dcid) |
501 | 4.75M | { |
502 | 4.75M | QUIC_PORT *port = arg; |
503 | 4.75M | PACKET pkt; |
504 | 4.75M | QUIC_PKT_HDR hdr; |
505 | 4.75M | QUIC_CHANNEL *ch = NULL, *new_ch = NULL; |
506 | | |
507 | | /* Don't handle anything if we are no longer running. */ |
508 | 4.75M | if (!ossl_quic_port_is_running(port)) |
509 | 0 | goto undesirable; |
510 | | |
511 | 4.75M | if (port_try_handle_stateless_reset(port, e)) |
512 | 4 | goto undesirable; |
513 | | |
514 | 4.75M | if (dcid != NULL |
515 | 1.86M | && ossl_quic_lcidm_lookup(port->lcidm, dcid, NULL, |
516 | 1.86M | (void **)&ch)) { |
517 | 1.86M | assert(ch != NULL); |
518 | 1.86M | ossl_quic_channel_inject(ch, e); |
519 | 1.86M | return; |
520 | 1.86M | } |
521 | | |
522 | | /* |
523 | | * If we have an incoming packet which doesn't match any existing connection |
524 | | * we assume this is an attempt to make a new connection. Currently we |
525 | | * require our caller to have precreated a latent 'incoming' channel via |
526 | | * TSERVER which then gets turned into the new connection. |
527 | | * |
528 | | * TODO(QUIC SERVER): In the future we will construct channels dynamically |
529 | | * in this case. |
530 | | */ |
531 | 2.89M | if (port->tserver_ch == NULL) |
532 | 2.89M | goto undesirable; |
533 | | |
534 | | /* |
535 | | * We have got a packet for an unknown DCID. This might be an attempt to |
536 | | * open a new connection. |
537 | | */ |
538 | 0 | if (e->data_len < QUIC_MIN_INITIAL_DGRAM_LEN) |
539 | 0 | goto undesirable; |
540 | | |
541 | 0 | if (!PACKET_buf_init(&pkt, ossl_quic_urxe_data(e), e->data_len)) |
542 | 0 | goto undesirable; |
543 | | |
544 | | /* |
545 | | * We set short_conn_id_len to SIZE_MAX here which will cause the decode |
546 | | * operation to fail if we get a 1-RTT packet. This is fine since we only |
547 | | * care about Initial packets. |
548 | | */ |
549 | 0 | if (!ossl_quic_wire_decode_pkt_hdr(&pkt, SIZE_MAX, 1, 0, &hdr, NULL)) |
550 | 0 | goto undesirable; |
551 | | |
552 | 0 | switch (hdr.version) { |
553 | 0 | case QUIC_VERSION_1: |
554 | 0 | break; |
555 | | |
556 | 0 | case QUIC_VERSION_NONE: |
557 | 0 | default: |
558 | | /* Unknown version or proactive version negotiation request, bail. */ |
559 | | /* TODO(QUIC SERVER): Handle version negotiation on server side */ |
560 | 0 | goto undesirable; |
561 | 0 | } |
562 | | |
563 | | /* |
564 | | * We only care about Initial packets which might be trying to establish a |
565 | | * connection. |
566 | | */ |
567 | 0 | if (hdr.type != QUIC_PKT_TYPE_INITIAL) |
568 | 0 | goto undesirable; |
569 | | |
570 | | /* |
571 | | * Try to process this as a valid attempt to initiate a connection. |
572 | | * |
573 | | * The channel will do all the LCID registration needed, but as an |
574 | | * optimization inject this packet directly into the channel's QRX for |
575 | | * processing without going through the DEMUX again. |
576 | | */ |
577 | 0 | port_on_new_conn(port, &e->peer, &hdr.src_conn_id, &hdr.dst_conn_id, |
578 | 0 | &new_ch); |
579 | 0 | if (new_ch != NULL) |
580 | 0 | ossl_qrx_inject_urxe(new_ch->qrx, e); |
581 | |
|
582 | 0 | return; |
583 | | |
584 | 2.89M | undesirable: |
585 | 2.89M | ossl_quic_demux_release_urxe(port->demux, e); |
586 | 2.89M | } |
587 | | |
588 | | void ossl_quic_port_raise_net_error(QUIC_PORT *port, |
589 | | QUIC_CHANNEL *triggering_ch) |
590 | 0 | { |
591 | 0 | QUIC_CHANNEL *ch; |
592 | |
|
593 | 0 | if (!ossl_quic_port_is_running(port)) |
594 | 0 | return; |
595 | | |
596 | | /* |
597 | | * Immediately capture any triggering error on the error stack, with a |
598 | | * cover error. |
599 | | */ |
600 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR, |
601 | 0 | "port failed due to network BIO I/O error"); |
602 | 0 | OSSL_ERR_STATE_save(port->err_state); |
603 | |
|
604 | 0 | port_transition_failed(port); |
605 | | |
606 | | /* Give the triggering channel (if any) the first notification. */ |
607 | 0 | if (triggering_ch != NULL) |
608 | 0 | ossl_quic_channel_raise_net_error(triggering_ch); |
609 | |
|
610 | 0 | OSSL_LIST_FOREACH(ch, ch, &port->channel_list) |
611 | 0 | if (ch != triggering_ch) |
612 | 0 | ossl_quic_channel_raise_net_error(ch); |
613 | 0 | } |
614 | | |
615 | | void ossl_quic_port_restore_err_state(const QUIC_PORT *port) |
616 | 0 | { |
617 | 0 | ERR_clear_error(); |
618 | 0 | OSSL_ERR_STATE_restore(port->err_state); |
619 | 0 | } |