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