Line data Source code
1 : /* fd_quic_trace_rx_tile.c does passive decryption of incoming QUIC
2 : packets.
3 :
4 : It mocks the setup procedure and run loop of a real fd_quic_tile. */
5 :
6 : #include "fd_quic_trace.h"
7 :
8 : #include "../../../../waltz/quic/fd_quic_private.h"
9 : #include "../../../../waltz/quic/templ/fd_quic_parse_util.h"
10 : #include "../../../../waltz/quic/fd_quic_proto.c"
11 : #include "../../../../util/net/fd_eth.h"
12 : #include "../../../../util/net/fd_ip4.h"
13 : #include "../../../../util/net/fd_udp.h"
14 :
15 : static int
16 : before_frag( fd_quic_trace_ctx_t * ctx FD_FN_UNUSED,
17 : ulong in_idx FD_FN_UNUSED,
18 : ulong seq FD_FN_UNUSED,
19 0 : ulong sig ) {
20 : /* Skip non-QUIC packets */
21 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
22 0 : return (proto!=DST_PROTO_OUTGOING) & (proto!=DST_PROTO_TPU_QUIC);
23 0 : }
24 :
25 : static void
26 : during_frag( fd_quic_trace_ctx_t * ctx,
27 : ulong in_idx FD_PARAM_UNUSED,
28 : ulong seq FD_PARAM_UNUSED,
29 : ulong sig,
30 : ulong chunk,
31 : ulong sz,
32 0 : ulong ctl ) {
33 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
34 0 : if( proto==DST_PROTO_TPU_QUIC ) {
35 0 : fd_memcpy( ctx->buffer, fd_net_rx_translate_frag( &ctx->net_in_bounds[0], chunk, ctl, sz ), sz );
36 0 : } else if( proto == DST_PROTO_OUTGOING ) {
37 0 : ulong p = ctx->net_out_base + (chunk<<FD_CHUNK_LG_SZ);
38 0 : fd_memcpy( ctx->buffer, (void*)p, sz );
39 0 : }
40 0 : }
41 :
42 : static int
43 : bounds_check_conn( fd_quic_t const * quic,
44 0 : fd_quic_conn_t const * conn ) {
45 0 : long conn_off = (long)((ulong)conn-(ulong)quic);
46 0 : return conn_off >= (long)quic->layout.conns_off && conn_off < (long)quic->layout.conn_map_off;
47 0 : }
48 :
49 : static ulong
50 : fd_quic_trace_initial( fd_quic_trace_ctx_t * ctx,
51 : uchar * data,
52 : ulong data_sz,
53 : uint ip4_saddr,
54 : ushort udp_sport,
55 : uint ip4_daddr,
56 : ushort udp_dport,
57 0 : uint key_idx ) {
58 0 : fd_quic_t * quic = ctx->quic;
59 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
60 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
61 :
62 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return FD_QUIC_PARSE_FAIL;
63 :
64 0 : fd_quic_initial_t initial[1] = {0};
65 0 : ulong rc = fd_quic_decode_initial( initial, data, data_sz );
66 0 : if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
67 0 : FD_LOG_DEBUG(( "fd_quic_decode_initial failed" ));
68 0 : return FD_QUIC_PARSE_FAIL;
69 0 : }
70 0 : ulong len = (ulong)( initial->pkt_num_pnoff + initial->len );
71 0 : if( FD_UNLIKELY( len > data_sz ) ) {
72 0 : FD_LOG_DEBUG(( "Bogus initial packet length" ));
73 0 : return FD_QUIC_PARSE_FAIL;
74 0 : }
75 0 : if( FD_UNLIKELY( initial->dst_conn_id_len > 20 ) ) {
76 0 : FD_LOG_DEBUG(( "Bogus destination connection id length: %u", (uint)initial->dst_conn_id_len ));
77 0 : }
78 :
79 0 : uint conn_idx = ~0u;
80 0 : fd_quic_crypto_keys_t _keys[1];
81 0 : fd_quic_crypto_keys_t const * keys = NULL;
82 0 : if( initial->dst_conn_id_len == FD_QUIC_CONN_ID_SZ ) {
83 0 : ulong conn_id = key_idx == 0 ? fd_ulong_load_8( initial->dst_conn_id )
84 0 : : fd_ulong_load_8( initial->src_conn_id );
85 0 : if( conn_id==0 ) return FD_QUIC_PARSE_FAIL;
86 :
87 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, conn_id, NULL );
88 0 : if( conn_entry && conn_entry->conn ) {
89 0 : fd_quic_conn_t * conn = translate_ptr( conn_entry->conn );
90 0 : if( FD_LIKELY( bounds_check_conn( quic, conn ) ) ) {
91 0 : conn_idx = conn->conn_idx;
92 0 : keys = &conn->keys[fd_quic_enc_level_initial_id][key_idx];
93 :
94 0 : # define EMPTY ((uchar[16]){0})
95 : /* assume this is a new connection, since this is an Initial packet */
96 0 : if( memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) != 0 ) {
97 : /* load the appropriate cid into peer_conn_id */
98 0 : ulong peer_conn_id = key_idx == 0 ? fd_ulong_load_8( initial->src_conn_id )
99 0 : : fd_ulong_load_8( initial->dst_conn_id );
100 :
101 : /* insert into peer_cid map */
102 0 : peer_conn_id_map_t * entry = peer_conn_id_map_insert( fd_quic_trace_peer_map, peer_conn_id );
103 :
104 : /* NULL entry either implies already exists, or full */
105 0 : if( entry ) {
106 0 : entry->conn_idx = conn->conn_idx;
107 0 : }
108 0 : }
109 0 : } else {
110 0 : FD_LOG_WARNING(( "conn out of bounds in fd_quic_trace_initial for conn id %lu with key idx %u", conn_id, key_idx ));
111 0 : }
112 0 : } else {
113 0 : FD_LOG_DEBUG(( "Failed to find conn for conn id %lu with key idx %u", conn_id, key_idx ));
114 0 : }
115 0 : }
116 :
117 0 : if( !keys || memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) == 0 ) {
118 0 : int is_client = 0;
119 0 : int is_egress = (int)key_idx;
120 :
121 : /* (server,egress) and (client,ingress) don't have the client's orig DCID avail */
122 0 : if( is_client==is_egress ) {
123 0 : fd_quic_crypto_secrets_t secrets[1];
124 0 : fd_quic_gen_initial_secrets(
125 0 : secrets,
126 0 : initial->dst_conn_id, initial->dst_conn_id_len,
127 0 : !is_client );
128 :
129 : /* Derive decryption key */
130 0 : fd_quic_gen_keys( _keys, secrets->secret[fd_quic_enc_level_initial_id][key_idx] );
131 0 : keys = _keys;
132 0 : }
133 0 : }
134 :
135 0 : if( !keys ) return FD_QUIC_PARSE_FAIL;
136 :
137 0 : ulong pktnum_off = initial->pkt_num_pnoff;
138 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
139 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
140 :
141 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
142 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+pktnum_off, pktnum_sz );
143 0 : ulong pktnum = pktnum_comp; /* don't bother decompressing since initial pktnum is usually low */
144 :
145 0 : ulong body_sz = initial->len; /* length of packet number, frames, and auth tag */
146 0 : ulong tot_sz = pktnum_off + body_sz;
147 :
148 0 : if( tot_sz > data_sz ) return FD_QUIC_PARSE_FAIL;
149 :
150 0 : int crypt_err = fd_quic_crypto_decrypt( data, tot_sz, pktnum_off, pktnum, keys );
151 0 : if( crypt_err!=FD_QUIC_SUCCESS ) {
152 0 : return FD_QUIC_PARSE_FAIL;
153 0 : }
154 :
155 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
156 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
157 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return FD_QUIC_PARSE_FAIL;
158 :
159 0 : if( ctx->dump ) {
160 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
161 0 : .ip4_saddr = ip4_saddr,
162 0 : .udp_sport = udp_sport,
163 0 : .ip4_daddr = ip4_daddr,
164 0 : .udp_dport = udp_dport,
165 0 : .flow = key_idx,
166 0 : .conn_idx = conn_idx };
167 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
168 0 : fd_quic_get_state( quic )->now,
169 0 : data,
170 0 : tot_sz );
171 0 : fflush( stdout );
172 0 : } else {
173 0 : uchar conn_id_truncated[24] = {0};
174 0 : fd_memcpy( conn_id_truncated, initial->dst_conn_id, initial->dst_conn_id_len );
175 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
176 0 : .conn_id = fd_ulong_load_8( conn_id_truncated ),
177 0 : .pkt_num = pktnum,
178 0 : .src_ip = ip4_saddr,
179 0 : .src_port = udp_sport,
180 0 : .pkt_type = FD_QUIC_PKT_TYPE_INITIAL
181 0 : };
182 :
183 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, tot_sz-wrap_sz );
184 0 : }
185 :
186 0 : return tot_sz;
187 0 : }
188 :
189 : static ulong
190 : fd_quic_trace_handshake( fd_quic_trace_ctx_t * ctx,
191 : uchar * data,
192 : ulong data_sz,
193 : uint ip4_saddr,
194 : ushort udp_sport,
195 : uint ip4_daddr,
196 : ushort udp_dport,
197 0 : uint key_idx ) {
198 0 : fd_quic_t * quic = ctx->quic;
199 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
200 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
201 :
202 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return FD_QUIC_PARSE_FAIL;
203 :
204 0 : fd_quic_handshake_t handshake[1] = {0};
205 0 : ulong rc = fd_quic_decode_handshake( handshake, data, data_sz );
206 0 : if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
207 0 : FD_LOG_DEBUG(( "fd_quic_decode_handshake failed" ));
208 0 : return FD_QUIC_PARSE_FAIL;
209 0 : }
210 0 : ulong len = (ulong)( handshake->pkt_num_pnoff + handshake->len );
211 0 : if( FD_UNLIKELY( len > data_sz ) ) {
212 0 : FD_LOG_DEBUG(( "Bogus handshake packet length" ));
213 0 : return FD_QUIC_PARSE_FAIL;
214 0 : }
215 :
216 : /* need conn_idx */
217 0 : uint conn_idx = ~0u;
218 :
219 : /* keeping this logic similar to the equivalent in fd_quic_trace_initial */
220 : /* for future merging */
221 0 : fd_quic_crypto_keys_t const * keys = NULL;
222 0 : if( handshake->dst_conn_id_len == FD_QUIC_CONN_ID_SZ ) {
223 0 : ulong conn_id = key_idx == 0 ? fd_ulong_load_8( handshake->dst_conn_id )
224 0 : : fd_ulong_load_8( handshake->src_conn_id );
225 0 : if( conn_id==0 ) return FD_QUIC_PARSE_FAIL;
226 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, conn_id, NULL );
227 0 : if( conn_entry && conn_entry->conn ) {
228 0 : fd_quic_conn_t * conn = translate_ptr( conn_entry->conn );
229 0 : if( FD_LIKELY( bounds_check_conn( quic, conn ) ) ) {
230 0 : keys = &conn->keys[fd_quic_enc_level_handshake_id][key_idx];
231 0 : conn_idx = conn->conn_idx;
232 0 : }
233 0 : }
234 0 : }
235 0 : if( !keys || memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) == 0 ) {
236 0 : return FD_QUIC_PARSE_FAIL;
237 0 : }
238 :
239 0 : ulong pktnum_off = handshake->pkt_num_pnoff;
240 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
241 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
242 :
243 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
244 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+pktnum_off, pktnum_sz );
245 0 : ulong pktnum = pktnum_comp; /* TODO decompress */
246 :
247 0 : ulong body_sz = handshake->len; /* length of packet number, frames, and auth tag */
248 0 : ulong tot_sz = pktnum_off + body_sz;
249 :
250 0 : if( tot_sz > data_sz ) return FD_QUIC_PARSE_FAIL;
251 :
252 0 : int crypt_err = fd_quic_crypto_decrypt( data, data_sz, pktnum_off, pktnum, keys );
253 0 : if( crypt_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
254 :
255 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
256 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
257 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return FD_QUIC_PARSE_FAIL;
258 :
259 0 : if( ctx->dump ) {
260 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
261 0 : .ip4_saddr = ip4_saddr,
262 0 : .udp_sport = udp_sport,
263 0 : .ip4_daddr = ip4_daddr,
264 0 : .udp_dport = udp_dport,
265 0 : .flow = key_idx,
266 0 : .conn_idx = conn_idx };
267 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
268 0 : fd_quic_get_state( quic )->now,
269 0 : data,
270 0 : data_sz );
271 0 : fflush( stdout );
272 0 : } else {
273 0 : uchar conn_id_truncated[8] = {0};
274 0 : fd_memcpy( conn_id_truncated, handshake->dst_conn_id, 8 );
275 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
276 0 : .conn_id = fd_ulong_load_8( conn_id_truncated ),
277 0 : .pkt_num = pktnum,
278 0 : .src_ip = ip4_saddr,
279 0 : .src_port = udp_sport,
280 0 : .pkt_type = FD_QUIC_PKT_TYPE_HANDSHAKE
281 0 : };
282 :
283 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
284 0 : }
285 :
286 0 : return FD_QUIC_PARSE_FAIL;
287 0 : }
288 :
289 : static void
290 : fd_quic_trace_1rtt( fd_quic_trace_ctx_t * ctx,
291 : uchar * data,
292 : ulong data_sz,
293 : uint ip4_saddr,
294 : ushort udp_sport,
295 : uint ip4_daddr,
296 : ushort udp_dport,
297 0 : uint key_idx ) {
298 0 : fd_quic_t * quic = ctx->quic;
299 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
300 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
301 :
302 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return;
303 :
304 0 : fd_quic_conn_t const * conn = NULL;
305 0 : ulong dst_conn_id = 0UL;
306 :
307 : /* key_idx 0 is ingress, key_idx 1 is egress */
308 0 : if( key_idx == 0 ) {
309 : /* Look up conn */
310 0 : dst_conn_id = fd_ulong_load_8( data+1 );
311 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, dst_conn_id, NULL );
312 :
313 0 : if( conn_entry && dst_conn_id && conn_entry->conn ) {
314 0 : conn = translate_ptr( conn_entry->conn );
315 0 : if( FD_UNLIKELY( !bounds_check_conn( quic, conn ) ) ) return;
316 0 : }
317 0 : } else {
318 :
319 : /* we use the first 8 bytes of the peer conn_id for the key
320 : since we don't actually know the length */
321 :
322 0 : ulong peer_conn_id = fd_ulong_load_8( data+1 );
323 :
324 : /* look up connection id in peer conn_id map */
325 0 : uint conn_idx = 0;
326 0 : peer_conn_id_map_t * peer_entry = peer_conn_id_map_query( fd_quic_trace_peer_map, peer_conn_id, NULL );
327 :
328 0 : if( FD_LIKELY( peer_entry ) ) {
329 0 : conn_idx = peer_entry->conn_idx;
330 0 : } else {
331 : /* report packet with unavailable connection */
332 0 : char time_str[FD_LOG_WALLCLOCK_CSTR_BUF_SZ];
333 0 : printf( "{ "
334 0 : "\"type\": \"packet\", "
335 0 : "\"flow\": \"%s\", "
336 0 : "\"trace_time\": \"%s\", "
337 0 : "\"src_ip_addr\": \"" FD_IP4_ADDR_FMT "\", "
338 0 : "\"src_udp_port\": \"%u\", "
339 0 : "\"dst_ip_addr\": \"" FD_IP4_ADDR_FMT "\", "
340 0 : "\"dst_udp_port\": \"%u\", "
341 0 : "\"hdr_type\": \"1-rtt\", "
342 0 : "\"err\": \"no-trace-connection\", "
343 0 : "\"dst_conn_id\": \"%lx\" "
344 0 : "}, ] }\n",
345 0 : key_idx == 0 ? "ingress" : "egress",
346 0 : fd_log_wallclock_cstr( fd_log_wallclock(), time_str ),
347 0 : FD_IP4_ADDR_FMT_ARGS( ip4_saddr ),
348 0 : (uint)udp_sport,
349 0 : FD_IP4_ADDR_FMT_ARGS( ip4_daddr ),
350 0 : (uint)udp_dport,
351 0 : peer_conn_id
352 0 : );
353 0 : return;
354 0 : }
355 :
356 0 : conn = fd_quic_trace_conn_at_idx( quic, conn_idx );
357 0 : }
358 :
359 0 : if( !conn ) return;
360 :
361 0 : fd_quic_crypto_keys_t const * keys = &conn->keys[ fd_quic_enc_level_appdata_id ][ key_idx ];
362 :
363 0 : ulong pktnum_off = 9UL;
364 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
365 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return;
366 :
367 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
368 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+9UL, pktnum_sz );
369 0 : ulong pktnum = fd_quic_reconstruct_pkt_num( pktnum_comp, pktnum_sz, conn->exp_pkt_number[2] );
370 0 : int crypt_err = fd_quic_crypto_decrypt( data, data_sz, pktnum_off, pktnum, keys );
371 0 : if( crypt_err!=FD_QUIC_SUCCESS ) return;
372 :
373 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
374 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
375 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return;
376 :
377 0 : if( ctx->dump ) {
378 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
379 0 : .ip4_saddr = ip4_saddr,
380 0 : .udp_sport = udp_sport,
381 0 : .ip4_daddr = ip4_daddr,
382 0 : .udp_dport = udp_dport,
383 0 : .flow = key_idx,
384 0 : .conn_idx = conn->conn_idx };
385 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
386 0 : fd_quic_get_state( quic )->now,
387 0 : data,
388 0 : data_sz );
389 0 : fflush( stdout );
390 0 : } else if( key_idx == 0 ) {
391 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
392 0 : .conn_id = dst_conn_id,
393 0 : .pkt_num = pktnum,
394 0 : .src_ip = ip4_saddr,
395 0 : .src_port = udp_sport,
396 0 : .pkt_type = FD_QUIC_PKT_TYPE_ONE_RTT
397 0 : };
398 :
399 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
400 0 : }
401 0 : }
402 :
403 : static int
404 0 : is_valid_quic_long_hdr( uchar* data ) {
405 0 : if( data[0]>>6 != 0x3 ) return 0;
406 0 : uint version = fd_uint_bswap( FD_LOAD( uint, data + 1 ) );
407 0 : if( version != 1 ) return 0;
408 :
409 0 : return 1;
410 0 : }
411 :
412 : static void
413 : fd_quic_trace_pkt( fd_quic_trace_ctx_t * ctx,
414 : uchar * data,
415 : ulong data_sz,
416 : uint ip4_saddr,
417 : ushort udp_sport,
418 : uint ip4_daddr,
419 : ushort udp_dport,
420 0 : uint key_idx ) {
421 :
422 0 : uchar * cur_ptr = data;
423 0 : uchar * end_ptr = data + data_sz;
424 0 : while( cur_ptr < end_ptr ) {
425 0 : int is_long = fd_quic_h0_hdr_form( cur_ptr[0] );
426 0 : ulong sz = 0;
427 0 : if( is_long ) {
428 0 : if( !is_valid_quic_long_hdr( cur_ptr ) ) {
429 0 : FD_LOG_NOTICE(( "Invalid quic long hdr with key_idx %u (maybe udp)", key_idx ));
430 0 : return;
431 0 : };
432 0 : switch( fd_quic_h0_long_packet_type( cur_ptr[0] ) ) {
433 0 : case FD_QUIC_PKT_TYPE_INITIAL:
434 0 : sz = fd_quic_trace_initial( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
435 0 : break;
436 0 : case FD_QUIC_PKT_TYPE_HANDSHAKE:
437 0 : sz = fd_quic_trace_handshake( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
438 0 : break;
439 0 : case FD_QUIC_PKT_TYPE_RETRY:
440 : /* TODO fd_quic_trace_retry */
441 0 : FD_LOG_NOTICE(( "%s retry packet of data_sz %lu, src: " FD_IP4_ADDR_FMT ":%u, dst: " FD_IP4_ADDR_FMT ":%u", key_idx==0 ? "Received" : "Sent", (ulong)( end_ptr - cur_ptr ), FD_IP4_ADDR_FMT_ARGS( ip4_saddr ), udp_sport, FD_IP4_ADDR_FMT_ARGS( ip4_daddr ), udp_dport ));
442 0 : return;
443 0 : default:
444 0 : FD_LOG_NOTICE(( "Unknown long packet type with key_idx %u, data_sz %lu, src: " FD_IP4_ADDR_FMT ":%u, dst: " FD_IP4_ADDR_FMT ":%u", key_idx, (ulong)( end_ptr - cur_ptr ), FD_IP4_ADDR_FMT_ARGS( ip4_saddr ), udp_sport, FD_IP4_ADDR_FMT_ARGS( ip4_daddr ), udp_dport ));
445 0 : return;
446 0 : }
447 :
448 : /* TODO TX should support FD_QUIC_PKT_TYPE_RETRY */
449 : /* FD_QUIC_PKT_TYPE_RETRY as the server, we shouldn't be receiving RETRY packets */
450 : /* FD_QUIC_PKT_TYPE_ZERO_RTT we don't support 0-RTT packets */
451 0 : } else {
452 0 : fd_quic_trace_1rtt( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
453 : /* one-rtt packets are last in the datagram */
454 0 : break;
455 0 : }
456 :
457 0 : if( sz == 0 || sz == FD_QUIC_PARSE_FAIL ) break;
458 :
459 0 : cur_ptr += sz;
460 0 : }
461 0 : }
462 :
463 : static void
464 : after_frag( fd_quic_trace_ctx_t * ctx,
465 : ulong in_idx FD_PARAM_UNUSED,
466 : ulong seq FD_PARAM_UNUSED,
467 : ulong sig,
468 : ulong sz,
469 : ulong tsorig FD_PARAM_UNUSED,
470 : ulong tspub FD_PARAM_UNUSED,
471 0 : fd_stem_context_t * stem FD_PARAM_UNUSED ) {
472 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
473 0 : uint key_idx = proto==DST_PROTO_OUTGOING ? 1 : 0;
474 :
475 0 : if( sz < FD_QUIC_SHORTEST_PKT ) return;
476 0 : if( sz > sizeof(ctx->buffer) ) return;
477 :
478 0 : uchar * cur = ctx->buffer;
479 0 : uchar * end = cur+sz;
480 :
481 0 : fd_eth_hdr_t const * eth_hdr = fd_type_pun_const( cur );
482 0 : cur += sizeof(fd_eth_hdr_t);
483 0 : if( FD_UNLIKELY( cur>end ) ) return;
484 0 : if( FD_UNLIKELY( fd_ushort_bswap( eth_hdr->net_type )!=FD_ETH_HDR_TYPE_IP ) ) return;
485 :
486 0 : fd_ip4_hdr_t const * ip4_hdr = fd_type_pun_const( cur );
487 0 : if( FD_UNLIKELY( cur+sizeof(fd_ip4_hdr_t) > end ) ) return;
488 0 : cur += FD_IP4_GET_LEN( *ip4_hdr );
489 0 : if( FD_UNLIKELY( cur>end ) ) return;
490 0 : if( FD_UNLIKELY( ip4_hdr->protocol!=FD_IP4_HDR_PROTOCOL_UDP ) ) return;
491 :
492 0 : fd_udp_hdr_t const * udp_hdr = fd_type_pun_const( cur );
493 0 : if( FD_UNLIKELY( cur+sizeof(fd_udp_hdr_t) > end ) ) return;
494 0 : cur += sizeof(fd_udp_hdr_t);
495 0 : if( FD_UNLIKELY( cur>end ) ) return;
496 :
497 0 : uint ip4_saddr = fd_uint_load_4( ip4_hdr->saddr_c );
498 0 : ushort udp_sport = fd_ushort_bswap( udp_hdr->net_sport );
499 0 : uint ip4_daddr = fd_uint_load_4( ip4_hdr->daddr_c );
500 0 : ushort udp_dport = fd_ushort_bswap( udp_hdr->net_dport );
501 0 : fd_quic_trace_pkt( ctx, cur, (ulong)( end-cur ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
502 0 : }
503 :
504 :
505 : #define STEM_BURST (1UL)
506 :
507 : #define STEM_CALLBACK_CONTEXT_TYPE fd_quic_trace_ctx_t
508 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_quic_trace_ctx_t)
509 :
510 0 : #define STEM_CALLBACK_BEFORE_FRAG before_frag
511 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
512 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
513 :
514 : #include "../../../../disco/stem/fd_stem.c"
515 :
516 : void
517 : fd_quic_trace_rx_tile( fd_quic_trace_ctx_t * trace_ctx,
518 : fd_frag_meta_t const * rx_mcache,
519 0 : fd_frag_meta_t const * tx_mcache ) {
520 :
521 0 : uchar fseq_mem[ FD_FSEQ_FOOTPRINT*2 ] __attribute__((aligned(FD_FSEQ_ALIGN)));
522 0 : ulong * fseq_tbl[2] = {0};
523 0 : for( uint j = 0; j < 2; ++j ){
524 0 : ulong * fseq = fd_fseq_join( fd_fseq_new( fseq_mem + j * FD_FSEQ_FOOTPRINT, 0UL ) );
525 0 : fseq_tbl[j] = fseq;
526 0 : }
527 :
528 0 : fd_rng_t rng[1];
529 0 : FD_TEST( fd_rng_join( fd_rng_new( rng, (uint)fd_tickcount(), 0UL ) ) );
530 :
531 0 : uchar scratch[ sizeof(fd_stem_tile_in_t)+128 ] __attribute__((aligned(FD_STEM_SCRATCH_ALIGN)));
532 :
533 0 : fd_frag_meta_t const * in_mcache_tbl[2] = { rx_mcache, tx_mcache };
534 :
535 0 : fd_stem_sleep_t sleep[ 1 ] = {{ .shmem = NULL }}; /* no sleep object: spin */
536 0 : stem_run1( /* in_cnt */ 2UL,
537 0 : /* in_mcache */ in_mcache_tbl,
538 0 : /* in_fseq */ fseq_tbl,
539 0 : /* out_cnt */ 0UL,
540 : /* out_mcache */ NULL,
541 0 : /* cons_cnt */ 0UL,
542 : /* cons_out */ NULL,
543 : /* cons_fseq */ NULL,
544 : /* cons_slow */ NULL,
545 0 : /* stem_burst */ 1UL,
546 0 : /* stem_lazy */ 0L,
547 0 : /* rng */ rng,
548 0 : /* scratch */ scratch,
549 0 : /* ctx */ trace_ctx,
550 0 : /* sleep */ sleep );
551 :
552 0 : for( int j = 0; j < 2; ++j ){
553 0 : fd_fseq_delete( fd_fseq_leave( fseq_tbl[j] ) );
554 0 : }
555 0 : }
|