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