1 /*
2 * Copyright 2023-2025 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 <openssl/bio.h>
11 #include "../ssl_local.h"
12 #include "internal/quic_trace.h"
13 #include "internal/quic_ssl.h"
14 #include "internal/quic_channel.h"
15 #include "internal/quic_wire_pkt.h"
16 #include "internal/quic_wire.h"
17 #include "internal/ssl_unwrap.h"
18
packet_type(int type)19 static const char *packet_type(int type)
20 {
21 switch (type) {
22 case QUIC_PKT_TYPE_INITIAL:
23 return "Initial";
24
25 case QUIC_PKT_TYPE_0RTT:
26 return "0RTT";
27
28 case QUIC_PKT_TYPE_HANDSHAKE:
29 return "Handshake";
30
31 case QUIC_PKT_TYPE_RETRY:
32 return "Retry";
33
34 case QUIC_PKT_TYPE_1RTT:
35 return "1RTT";
36
37 case QUIC_PKT_TYPE_VERSION_NEG:
38 return "VersionNeg";
39
40 default:
41 return "Unknown";
42 }
43 }
44
45 /* Print a non-NUL terminated string to BIO */
put_str(BIO * bio,char * str,size_t slen)46 static void put_str(BIO *bio, char *str, size_t slen)
47 {
48 size_t i;
49
50 for (i = 0; i < slen; i++)
51 BIO_printf(bio, "%c", str[i]);
52 }
53
put_data(BIO * bio,const uint8_t * data,size_t datalen)54 static void put_data(BIO *bio, const uint8_t *data, size_t datalen)
55 {
56 size_t i;
57
58 for (i = 0; i < datalen; i++)
59 BIO_printf(bio, "%02x", data[i]);
60 }
61
put_conn_id(BIO * bio,QUIC_CONN_ID * id)62 static void put_conn_id(BIO *bio, QUIC_CONN_ID *id)
63 {
64 if (id->id_len == 0) {
65 BIO_puts(bio, "<zero length id>");
66 return;
67 }
68
69 BIO_puts(bio, "0x");
70 put_data(bio, id->id, id->id_len);
71 }
72
put_token(BIO * bio,const uint8_t * token,size_t token_len)73 static void put_token(BIO *bio, const uint8_t *token, size_t token_len)
74 {
75 if (token_len == 0)
76 BIO_puts(bio, "<zero length token>");
77 else
78 put_data(bio, token, token_len);
79 }
80
frame_ack(BIO * bio,PACKET * pkt)81 static int frame_ack(BIO *bio, PACKET *pkt)
82 {
83 OSSL_QUIC_FRAME_ACK ack;
84 OSSL_QUIC_ACK_RANGE *ack_ranges = NULL;
85 uint64_t total_ranges = 0;
86 uint64_t i;
87 int ret = 0;
88
89 if (!ossl_quic_wire_peek_frame_ack_num_ranges(pkt, &total_ranges)
90 /* In case sizeof(uint64_t) > sizeof(size_t) */
91 || total_ranges > SIZE_MAX / sizeof(ack_ranges[0])
92 || (ack_ranges = OPENSSL_zalloc(sizeof(ack_ranges[0])
93 * (size_t)total_ranges))
94 == NULL)
95 return ret;
96
97 ack.ack_ranges = ack_ranges;
98 ack.num_ack_ranges = (size_t)total_ranges;
99
100 /* Ack delay exponent is 0, so we can get the raw delay time below */
101 if (!ossl_quic_wire_decode_frame_ack(pkt, 0, &ack, NULL))
102 goto end;
103
104 BIO_printf(bio, " Largest acked: %llu\n",
105 (unsigned long long)ack.ack_ranges[0].end);
106 BIO_printf(bio, " Ack delay (raw) %llu\n",
107 (unsigned long long)ossl_time2ticks(ack.delay_time));
108 BIO_printf(bio, " Ack range count: %llu\n",
109 (unsigned long long)total_ranges - 1);
110 BIO_printf(bio, " First ack range: %llu\n",
111 (unsigned long long)(ack.ack_ranges[0].end
112 - ack.ack_ranges[0].start));
113 for (i = 1; i < total_ranges; i++) {
114 BIO_printf(bio, " Gap: %llu\n",
115 (unsigned long long)(ack.ack_ranges[i - 1].start
116 - ack.ack_ranges[i].end - 2));
117 BIO_printf(bio, " Ack range len: %llu\n",
118 (unsigned long long)(ack.ack_ranges[i].end
119 - ack.ack_ranges[i].start));
120 }
121
122 ret = 1;
123 end:
124 OPENSSL_free(ack_ranges);
125 return ret;
126 }
127
frame_reset_stream(BIO * bio,PACKET * pkt)128 static int frame_reset_stream(BIO *bio, PACKET *pkt)
129 {
130 OSSL_QUIC_FRAME_RESET_STREAM frame_data;
131
132 if (!ossl_quic_wire_decode_frame_reset_stream(pkt, &frame_data))
133 return 0;
134
135 BIO_printf(bio, " Stream id: %llu\n",
136 (unsigned long long)frame_data.stream_id);
137 BIO_printf(bio, " App Protocol Error Code: %llu\n",
138 (unsigned long long)frame_data.app_error_code);
139 BIO_printf(bio, " Final size: %llu\n",
140 (unsigned long long)frame_data.final_size);
141
142 return 1;
143 }
144
frame_stop_sending(BIO * bio,PACKET * pkt)145 static int frame_stop_sending(BIO *bio, PACKET *pkt)
146 {
147 OSSL_QUIC_FRAME_STOP_SENDING frame_data;
148
149 if (!ossl_quic_wire_decode_frame_stop_sending(pkt, &frame_data))
150 return 0;
151
152 BIO_printf(bio, " Stream id: %llu\n",
153 (unsigned long long)frame_data.stream_id);
154 BIO_printf(bio, " App Protocol Error Code: %llu\n",
155 (unsigned long long)frame_data.app_error_code);
156
157 return 1;
158 }
159
frame_crypto(BIO * bio,PACKET * pkt)160 static int frame_crypto(BIO *bio, PACKET *pkt)
161 {
162 OSSL_QUIC_FRAME_CRYPTO frame_data;
163
164 if (!ossl_quic_wire_decode_frame_crypto(pkt, 1, &frame_data))
165 return 0;
166
167 BIO_printf(bio, " Offset: %llu\n", (unsigned long long)frame_data.offset);
168 BIO_printf(bio, " Len: %llu\n", (unsigned long long)frame_data.len);
169
170 return 1;
171 }
172
frame_new_token(BIO * bio,PACKET * pkt)173 static int frame_new_token(BIO *bio, PACKET *pkt)
174 {
175 const uint8_t *token;
176 size_t token_len;
177
178 if (!ossl_quic_wire_decode_frame_new_token(pkt, &token, &token_len))
179 return 0;
180
181 BIO_puts(bio, " Token: ");
182 put_token(bio, token, token_len);
183 BIO_puts(bio, "\n");
184
185 return 1;
186 }
187
frame_stream(BIO * bio,PACKET * pkt,uint64_t frame_type)188 static int frame_stream(BIO *bio, PACKET *pkt, uint64_t frame_type)
189 {
190
191 OSSL_QUIC_FRAME_STREAM frame_data;
192
193 BIO_puts(bio, "Stream");
194 switch (frame_type) {
195 case OSSL_QUIC_FRAME_TYPE_STREAM:
196 BIO_puts(bio, "\n");
197 break;
198
199 case OSSL_QUIC_FRAME_TYPE_STREAM_FIN:
200 BIO_puts(bio, " (Fin)\n");
201 break;
202
203 case OSSL_QUIC_FRAME_TYPE_STREAM_LEN:
204 BIO_puts(bio, " (Len)\n");
205 break;
206
207 case OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN:
208 BIO_puts(bio, " (Len, Fin)\n");
209 break;
210
211 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF:
212 BIO_puts(bio, " (Off)\n");
213 break;
214
215 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN:
216 BIO_puts(bio, " (Off, Fin)\n");
217 break;
218
219 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN:
220 BIO_puts(bio, " (Off, Len)\n");
221 break;
222
223 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN:
224 BIO_puts(bio, " (Off, Len, Fin)\n");
225 break;
226
227 default:
228 return 0;
229 }
230
231 if (!ossl_quic_wire_decode_frame_stream(pkt, 1, &frame_data))
232 return 0;
233
234 BIO_printf(bio, " Stream id: %llu\n",
235 (unsigned long long)frame_data.stream_id);
236 BIO_printf(bio, " Offset: %llu\n",
237 (unsigned long long)frame_data.offset);
238 /*
239 * It would be nice to find a way of passing the implicit length through
240 * to the msg_callback. But this is not currently possible.
241 */
242 if (frame_data.has_explicit_len)
243 BIO_printf(bio, " Len: %llu\n", (unsigned long long)frame_data.len);
244 else
245 BIO_puts(bio, " Len: <implicit length>\n");
246
247 return 1;
248 }
249
frame_max_data(BIO * bio,PACKET * pkt)250 static int frame_max_data(BIO *bio, PACKET *pkt)
251 {
252 uint64_t max_data = 0;
253
254 if (!ossl_quic_wire_decode_frame_max_data(pkt, &max_data))
255 return 0;
256
257 BIO_printf(bio, " Max Data: %llu\n", (unsigned long long)max_data);
258
259 return 1;
260 }
261
frame_max_stream_data(BIO * bio,PACKET * pkt)262 static int frame_max_stream_data(BIO *bio, PACKET *pkt)
263 {
264 uint64_t stream_id = 0;
265 uint64_t max_stream_data = 0;
266
267 if (!ossl_quic_wire_decode_frame_max_stream_data(pkt, &stream_id,
268 &max_stream_data))
269 return 0;
270
271 BIO_printf(bio, " Max Stream Data: %llu\n",
272 (unsigned long long)max_stream_data);
273
274 return 1;
275 }
276
frame_max_streams(BIO * bio,PACKET * pkt)277 static int frame_max_streams(BIO *bio, PACKET *pkt)
278 {
279 uint64_t max_streams = 0;
280
281 if (!ossl_quic_wire_decode_frame_max_streams(pkt, &max_streams))
282 return 0;
283
284 BIO_printf(bio, " Max Streams: %llu\n", (unsigned long long)max_streams);
285
286 return 1;
287 }
288
frame_data_blocked(BIO * bio,PACKET * pkt)289 static int frame_data_blocked(BIO *bio, PACKET *pkt)
290 {
291 uint64_t max_data = 0;
292
293 if (!ossl_quic_wire_decode_frame_data_blocked(pkt, &max_data))
294 return 0;
295
296 BIO_printf(bio, " Max Data: %llu\n", (unsigned long long)max_data);
297
298 return 1;
299 }
300
frame_stream_data_blocked(BIO * bio,PACKET * pkt)301 static int frame_stream_data_blocked(BIO *bio, PACKET *pkt)
302 {
303 uint64_t stream_id = 0;
304 uint64_t max_data = 0;
305
306 if (!ossl_quic_wire_decode_frame_stream_data_blocked(pkt, &stream_id,
307 &max_data))
308 return 0;
309
310 BIO_printf(bio, " Stream id: %llu\n", (unsigned long long)stream_id);
311 BIO_printf(bio, " Max Data: %llu\n", (unsigned long long)max_data);
312
313 return 1;
314 }
315
frame_streams_blocked(BIO * bio,PACKET * pkt)316 static int frame_streams_blocked(BIO *bio, PACKET *pkt)
317 {
318 uint64_t max_data = 0;
319
320 if (!ossl_quic_wire_decode_frame_streams_blocked(pkt, &max_data))
321 return 0;
322
323 BIO_printf(bio, " Max Data: %llu\n", (unsigned long long)max_data);
324
325 return 1;
326 }
327
frame_new_conn_id(BIO * bio,PACKET * pkt)328 static int frame_new_conn_id(BIO *bio, PACKET *pkt)
329 {
330 OSSL_QUIC_FRAME_NEW_CONN_ID frame_data;
331
332 if (!ossl_quic_wire_decode_frame_new_conn_id(pkt, &frame_data))
333 return 0;
334
335 BIO_printf(bio, " Sequence Number: %llu\n",
336 (unsigned long long)frame_data.seq_num);
337 BIO_printf(bio, " Retire prior to: %llu\n",
338 (unsigned long long)frame_data.retire_prior_to);
339 BIO_puts(bio, " Connection id: ");
340 put_conn_id(bio, &frame_data.conn_id);
341 BIO_puts(bio, "\n Stateless Reset Token: ");
342 put_data(bio, frame_data.stateless_reset.token,
343 sizeof(frame_data.stateless_reset.token));
344 BIO_puts(bio, "\n");
345
346 return 1;
347 }
348
frame_retire_conn_id(BIO * bio,PACKET * pkt)349 static int frame_retire_conn_id(BIO *bio, PACKET *pkt)
350 {
351 uint64_t seq_num;
352
353 if (!ossl_quic_wire_decode_frame_retire_conn_id(pkt, &seq_num))
354 return 0;
355
356 BIO_printf(bio, " Sequence Number: %llu\n", (unsigned long long)seq_num);
357
358 return 1;
359 }
360
frame_path_challenge(BIO * bio,PACKET * pkt)361 static int frame_path_challenge(BIO *bio, PACKET *pkt)
362 {
363 uint64_t data = 0;
364
365 if (!ossl_quic_wire_decode_frame_path_challenge(pkt, &data))
366 return 0;
367
368 BIO_printf(bio, " Data: %016llx\n", (unsigned long long)data);
369
370 return 1;
371 }
372
frame_path_response(BIO * bio,PACKET * pkt)373 static int frame_path_response(BIO *bio, PACKET *pkt)
374 {
375 uint64_t data = 0;
376
377 if (!ossl_quic_wire_decode_frame_path_response(pkt, &data))
378 return 0;
379
380 BIO_printf(bio, " Data: %016llx\n", (unsigned long long)data);
381
382 return 1;
383 }
384
frame_conn_closed(BIO * bio,PACKET * pkt)385 static int frame_conn_closed(BIO *bio, PACKET *pkt)
386 {
387 OSSL_QUIC_FRAME_CONN_CLOSE frame_data;
388
389 if (!ossl_quic_wire_decode_frame_conn_close(pkt, &frame_data))
390 return 0;
391
392 BIO_printf(bio, " Error Code: %llu\n",
393 (unsigned long long)frame_data.error_code);
394 BIO_puts(bio, " Reason: ");
395 put_str(bio, frame_data.reason, frame_data.reason_len);
396 BIO_puts(bio, "\n");
397
398 return 1;
399 }
400
trace_frame_data(BIO * bio,PACKET * pkt)401 static int trace_frame_data(BIO *bio, PACKET *pkt)
402 {
403 uint64_t frame_type;
404
405 if (!ossl_quic_wire_peek_frame_header(pkt, &frame_type, NULL))
406 return 0;
407
408 switch (frame_type) {
409 case OSSL_QUIC_FRAME_TYPE_PING:
410 BIO_puts(bio, "Ping\n");
411 if (!ossl_quic_wire_decode_frame_ping(pkt))
412 return 0;
413 break;
414
415 case OSSL_QUIC_FRAME_TYPE_PADDING:
416 BIO_puts(bio, "Padding\n");
417 ossl_quic_wire_decode_padding(pkt);
418 break;
419
420 case OSSL_QUIC_FRAME_TYPE_ACK_WITHOUT_ECN:
421 case OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN:
422 BIO_puts(bio, "Ack ");
423 if (frame_type == OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN)
424 BIO_puts(bio, " (with ECN)\n");
425 else
426 BIO_puts(bio, " (without ECN)\n");
427 if (!frame_ack(bio, pkt))
428 return 0;
429 break;
430
431 case OSSL_QUIC_FRAME_TYPE_RESET_STREAM:
432 BIO_puts(bio, "Reset stream\n");
433 if (!frame_reset_stream(bio, pkt))
434 return 0;
435 break;
436
437 case OSSL_QUIC_FRAME_TYPE_STOP_SENDING:
438 BIO_puts(bio, "Stop sending\n");
439 if (!frame_stop_sending(bio, pkt))
440 return 0;
441 break;
442
443 case OSSL_QUIC_FRAME_TYPE_CRYPTO:
444 BIO_puts(bio, "Crypto\n");
445 if (!frame_crypto(bio, pkt))
446 return 0;
447 break;
448
449 case OSSL_QUIC_FRAME_TYPE_NEW_TOKEN:
450 BIO_puts(bio, "New token\n");
451 if (!frame_new_token(bio, pkt))
452 return 0;
453 break;
454
455 case OSSL_QUIC_FRAME_TYPE_STREAM:
456 case OSSL_QUIC_FRAME_TYPE_STREAM_FIN:
457 case OSSL_QUIC_FRAME_TYPE_STREAM_LEN:
458 case OSSL_QUIC_FRAME_TYPE_STREAM_LEN_FIN:
459 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF:
460 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_FIN:
461 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN:
462 case OSSL_QUIC_FRAME_TYPE_STREAM_OFF_LEN_FIN:
463 /* frame_stream() prints the frame type string */
464 if (!frame_stream(bio, pkt, frame_type))
465 return 0;
466 break;
467
468 case OSSL_QUIC_FRAME_TYPE_MAX_DATA:
469 BIO_puts(bio, "Max data\n");
470 if (!frame_max_data(bio, pkt))
471 return 0;
472 break;
473
474 case OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA:
475 BIO_puts(bio, "Max stream data\n");
476 if (!frame_max_stream_data(bio, pkt))
477 return 0;
478 break;
479
480 case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI:
481 case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
482 BIO_puts(bio, "Max streams ");
483 if (frame_type == OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI)
484 BIO_puts(bio, " (Bidi)\n");
485 else
486 BIO_puts(bio, " (Uni)\n");
487 if (!frame_max_streams(bio, pkt))
488 return 0;
489 break;
490
491 case OSSL_QUIC_FRAME_TYPE_DATA_BLOCKED:
492 BIO_puts(bio, "Data blocked\n");
493 if (!frame_data_blocked(bio, pkt))
494 return 0;
495 break;
496
497 case OSSL_QUIC_FRAME_TYPE_STREAM_DATA_BLOCKED:
498 BIO_puts(bio, "Stream data blocked\n");
499 if (!frame_stream_data_blocked(bio, pkt))
500 return 0;
501 break;
502
503 case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI:
504 case OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_UNI:
505 BIO_puts(bio, "Streams blocked");
506 if (frame_type == OSSL_QUIC_FRAME_TYPE_STREAMS_BLOCKED_BIDI)
507 BIO_puts(bio, " (Bidi)\n");
508 else
509 BIO_puts(bio, " (Uni)\n");
510 if (!frame_streams_blocked(bio, pkt))
511 return 0;
512 break;
513
514 case OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID:
515 BIO_puts(bio, "New conn id\n");
516 if (!frame_new_conn_id(bio, pkt))
517 return 0;
518 break;
519
520 case OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID:
521 BIO_puts(bio, "Retire conn id\n");
522 if (!frame_retire_conn_id(bio, pkt))
523 return 0;
524 break;
525
526 case OSSL_QUIC_FRAME_TYPE_PATH_CHALLENGE:
527 BIO_puts(bio, "Path challenge\n");
528 if (!frame_path_challenge(bio, pkt))
529 return 0;
530 break;
531
532 case OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE:
533 BIO_puts(bio, "Path response\n");
534 if (!frame_path_response(bio, pkt))
535 return 0;
536 break;
537
538 case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP:
539 case OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_TRANSPORT:
540 BIO_puts(bio, "Connection close");
541 if (frame_type == OSSL_QUIC_FRAME_TYPE_CONN_CLOSE_APP)
542 BIO_puts(bio, " (app)\n");
543 else
544 BIO_puts(bio, " (transport)\n");
545 if (!frame_conn_closed(bio, pkt))
546 return 0;
547 break;
548
549 case OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE:
550 BIO_puts(bio, "Handshake done\n");
551 if (!ossl_quic_wire_decode_frame_handshake_done(pkt))
552 return 0;
553 break;
554
555 default:
556 return 0;
557 }
558
559 if (PACKET_remaining(pkt) != 0)
560 BIO_puts(bio, " <unexpected trailing frame data skipped>\n");
561
562 return 1;
563 }
564
ossl_quic_trace(int write_p,int version,int content_type,const void * buf,size_t msglen,SSL * ssl,void * arg)565 int ossl_quic_trace(int write_p, int version, int content_type,
566 const void *buf, size_t msglen, SSL *ssl, void *arg)
567 {
568 BIO *bio = arg;
569 PACKET pkt;
570 size_t id_len = 0;
571 QUIC_CHANNEL *ch;
572
573 switch (content_type) {
574 case SSL3_RT_QUIC_DATAGRAM:
575 BIO_puts(bio, write_p ? "Sent" : "Received");
576 /*
577 * Unfortunately there is no way of receiving auxiliary information
578 * about the datagram through the msg_callback API such as the peer
579 * address
580 */
581 BIO_printf(bio, " Datagram\n Length: %zu\n", msglen);
582 break;
583
584 case SSL3_RT_QUIC_PACKET: {
585 QUIC_PKT_HDR hdr;
586 size_t i;
587
588 if (!PACKET_buf_init(&pkt, buf, msglen))
589 return 0;
590 /* Decode the packet header */
591 ch = ossl_quic_conn_get_channel(ssl);
592 id_len = ossl_quic_channel_get_short_header_conn_id_len(ch);
593 if (ossl_quic_wire_decode_pkt_hdr(&pkt, id_len, 0, 1, &hdr, NULL,
594 NULL)
595 != 1)
596 return 0;
597
598 BIO_puts(bio, write_p ? "Sent" : "Received");
599 BIO_puts(bio, " Packet\n");
600 BIO_printf(bio, " Packet Type: %s\n", packet_type(hdr.type));
601 if (hdr.type != QUIC_PKT_TYPE_1RTT)
602 BIO_printf(bio, " Version: 0x%08lx\n",
603 (unsigned long)hdr.version);
604 BIO_puts(bio, " Destination Conn Id: ");
605 put_conn_id(bio, &hdr.dst_conn_id);
606 BIO_puts(bio, "\n");
607 if (hdr.type != QUIC_PKT_TYPE_1RTT) {
608 BIO_puts(bio, " Source Conn Id: ");
609 put_conn_id(bio, &hdr.src_conn_id);
610 BIO_puts(bio, "\n");
611 }
612 BIO_printf(bio, " Payload length: %zu\n", hdr.len);
613 if (hdr.type == QUIC_PKT_TYPE_INITIAL) {
614 BIO_puts(bio, " Token: ");
615 put_token(bio, hdr.token, hdr.token_len);
616 BIO_puts(bio, "\n");
617 }
618 if (hdr.type != QUIC_PKT_TYPE_VERSION_NEG
619 && hdr.type != QUIC_PKT_TYPE_RETRY) {
620 BIO_puts(bio, " Packet Number: 0x");
621 /* Will always be at least 1 byte */
622 for (i = 0; i < hdr.pn_len; i++)
623 BIO_printf(bio, "%02x", hdr.pn[i]);
624 BIO_puts(bio, "\n");
625 }
626 break;
627 }
628
629 case SSL3_RT_QUIC_FRAME_PADDING:
630 case SSL3_RT_QUIC_FRAME_FULL:
631 case SSL3_RT_QUIC_FRAME_HEADER: {
632 BIO_puts(bio, write_p ? "Sent" : "Received");
633 BIO_puts(bio, " Frame: ");
634
635 if (!PACKET_buf_init(&pkt, buf, msglen))
636 return 0;
637 if (!trace_frame_data(bio, &pkt)) {
638 BIO_puts(bio, " <error processing frame data>\n");
639 return 0;
640 }
641 } break;
642
643 default:
644 /* Unrecognised content_type. We defer to SSL_trace */
645 return 0;
646 }
647
648 return 1;
649 }
650