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