Line data Source code
1 : #include "fd_pcapng_private.h"
2 : #include "../fd_util.h"
3 :
4 : /* Capture related ****************************************************/
5 :
6 : #include <errno.h>
7 : #if defined(__linux__) || defined(__FreeBSD__)
8 : #include <net/if.h>
9 : #endif
10 :
11 : void
12 0 : fd_pcapng_shb_defaults( fd_pcapng_shb_opts_t * opt ) {
13 0 : # if FD_HAS_X86
14 0 : opt->hardware = "x86_64";
15 0 : # endif
16 :
17 0 : # if defined(__linux__)
18 0 : opt->os = "Linux";
19 0 : # endif
20 :
21 0 : opt->userappl = "Firedancer";
22 0 : }
23 :
24 : int
25 : fd_pcapng_idb_defaults( fd_pcapng_idb_opts_t * opt,
26 0 : uint if_idx ) {
27 0 : # if defined(__linux__) || defined(__FreeBSD__)
28 0 : static FD_TL char _name[ IF_NAMESIZE ];
29 0 : char * name = if_indextoname( if_idx, _name );
30 0 : if( FD_UNLIKELY( !name ) ) return 0;
31 0 : FD_STATIC_ASSERT( 16>=IF_NAMESIZE, ifname_sz );
32 0 : memcpy( opt->name, _name, 16UL );
33 : # else
34 : (void)if_idx;
35 : # endif
36 :
37 0 : opt->tsresol = FD_PCAPNG_TSRESOL_NS;
38 :
39 : /* TODO get ip4_addr, mac_addr, hardware from rtnetlink */
40 :
41 0 : return 1;
42 0 : }
43 :
44 : #if FD_HAS_HOSTED
45 :
46 : #include <stdio.h>
47 :
48 : /* fwrite-style funcs *************************************************/
49 :
50 : /* What follows are a bunch of serialization / writer functions. They
51 : maintain the following properties:
52 :
53 : - file handle is 4 byte aligned
54 : - buf is the write buffer up to
55 : - cursor is the next free byte in buffer (or next byte after end of
56 : buf is space exhausted)
57 : - Invariant: cursor <= FD_PCAPNG_BLOCK_SZ
58 : - fwrite is called once per func and write size is 4 byte aligned
59 : and no larger than FD_PCAPNG_BLOCK_SZ */
60 :
61 : /* FD_PCAPNG_FWRITE_OPT writes an option in the context of an fwrite-
62 : style function. Assumes that given length is <=65532.
63 :
64 : Args:
65 : ushort t (option type)
66 : ushort l (option length)
67 : void * v (ptr to option data) */
68 :
69 : #define FD_PCAPNG_FWRITE_OPT(t,l,v) \
70 57 : do { \
71 57 : ulong _sz = (ushort)( l ); \
72 57 : ulong _sz_align = (ushort)fd_ulong_align_up( _sz, 4UL ); \
73 57 : if( FD_UNLIKELY( cursor+4UL+_sz_align > FD_PCAPNG_BLOCK_SZ ) ) { \
74 0 : FD_LOG_WARNING(( "oversz pcapng block" )); \
75 0 : return 0UL; \
76 0 : } \
77 57 : *(ushort *)( buf+cursor ) = ( (ushort)(t) ); cursor+=2UL; \
78 57 : *(ushort *)( buf+cursor ) = ( (ushort)_sz ); cursor+=2UL; \
79 57 : if( _sz ) fd_memcpy( buf+cursor, (v), _sz ); \
80 57 : fd_memset( buf+cursor+_sz, 0, _sz_align-_sz ); \
81 57 : cursor+=_sz_align; \
82 57 : } while(0);
83 :
84 : #define FD_PCAPNG_FWRITE_NULLOPT() \
85 15 : do { \
86 15 : if( FD_UNLIKELY( cursor+4UL > FD_PCAPNG_BLOCK_SZ ) ) { \
87 0 : FD_LOG_WARNING(( "oversz pcapng block" )); \
88 0 : return 0UL; \
89 0 : } \
90 15 : fd_memset( buf+cursor, 0, 4UL ); \
91 15 : cursor+=4UL; \
92 15 : } while(0);
93 :
94 :
95 : /* FD_PCAPNG_FWRITE_BLOCK_TERM terminates a block buffer being
96 : serialized in the context of an fwrite-style function. */
97 :
98 : #define FD_PCAPNG_FWRITE_BLOCK_TERM() \
99 15 : do { \
100 15 : if( FD_UNLIKELY( cursor+4UL > FD_PCAPNG_BLOCK_SZ ) ) { \
101 0 : FD_LOG_WARNING(( "oversz pcapng block" )); \
102 0 : return 0UL; \
103 0 : } \
104 15 : block->block_sz = (uint)(cursor+4UL); \
105 15 : *(uint *)( buf+cursor ) = (uint)(cursor+4UL); \
106 15 : cursor+=4UL; \
107 15 : } while(0);
108 :
109 : ulong
110 : fd_pcapng_fwrite_shb( fd_pcapng_shb_opts_t const * opt,
111 9 : void * file ) {
112 :
113 9 : uchar buf[ FD_PCAPNG_BLOCK_SZ ];
114 :
115 9 : fd_pcapng_shb_t * block = (fd_pcapng_shb_t *)buf;
116 :
117 9 : ulong cursor = sizeof(fd_pcapng_shb_t);
118 9 : *block = (fd_pcapng_shb_t) {
119 9 : .block_type = FD_PCAPNG_BLOCK_TYPE_SHB,
120 : /* block_sz set later */
121 9 : .byte_order_magic = FD_PCAPNG_BYTE_ORDER_MAGIC,
122 9 : .version_major = (ushort)1,
123 9 : .version_minor = (ushort)0,
124 9 : .section_sz = ULONG_MAX
125 9 : };
126 :
127 9 : if( opt ) {
128 9 : if( opt->hardware ) FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_SHB_OPT_HARDWARE, strlen( opt->hardware ), opt->hardware );
129 9 : if( opt->os ) FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_SHB_OPT_OS, strlen( opt->os ), opt->os );
130 9 : if( opt->userappl ) FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_SHB_OPT_USERAPPL, strlen( opt->userappl ), opt->userappl );
131 9 : }
132 9 : FD_PCAPNG_FWRITE_NULLOPT();
133 :
134 9 : FD_PCAPNG_FWRITE_BLOCK_TERM();
135 :
136 9 : return fwrite( buf, cursor, 1UL, (FILE *)file );
137 9 : }
138 :
139 : ulong
140 : fd_pcapng_fwrite_idb( uint link_type,
141 : fd_pcapng_idb_opts_t const * opt,
142 6 : void * file ) {
143 :
144 6 : uchar buf[ FD_PCAPNG_BLOCK_SZ ];
145 :
146 6 : fd_pcapng_idb_t * block = (fd_pcapng_idb_t *)buf;
147 :
148 6 : ulong cursor = sizeof(fd_pcapng_idb_t);
149 6 : *block = (fd_pcapng_idb_t) {
150 6 : .block_type = FD_PCAPNG_BLOCK_TYPE_IDB,
151 : /* block_sz set later */
152 6 : .link_type = (ushort)link_type,
153 6 : .snap_len = 0U, /* FIXME should appropriately set snap_len
154 : But this is not trivial. Needs balancing
155 : between buffer space available for meta
156 : and payload. (meta is variable length) */
157 6 : };
158 :
159 6 : uchar tsresol = FD_PCAPNG_TSRESOL_NS;
160 6 : FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_IDB_OPT_TSRESOL, 1UL, &tsresol );
161 :
162 6 : if( opt ) {
163 :
164 6 : if( opt->name[0] )
165 6 : FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_IDB_OPT_NAME, fd_cstr_nlen( opt->name, 16UL ), opt->name );
166 6 : if( fd_uint_load_4( opt->ip4_addr ) )
167 6 : FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_IDB_OPT_IPV4_ADDR, 4UL, opt->ip4_addr );
168 6 : if( fd_ulong_load_6( opt->mac_addr ) )
169 6 : FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_IDB_OPT_MAC_ADDR, 6UL, opt->mac_addr );
170 :
171 6 : if( opt->hardware[0] )
172 6 : FD_PCAPNG_FWRITE_OPT( FD_PCAPNG_IDB_OPT_HARDWARE, fd_cstr_nlen( opt->hardware, 64UL ), opt->hardware );
173 :
174 6 : }
175 6 : FD_PCAPNG_FWRITE_NULLOPT();
176 :
177 6 : FD_PCAPNG_FWRITE_BLOCK_TERM();
178 :
179 6 : return fwrite( buf, cursor, 1UL, (FILE *)file );
180 6 : }
181 :
182 : ulong
183 : fd_pcapng_fwrite_pkt1( void * _file,
184 : void const * payload,
185 : ulong payload_sz,
186 : void const * options,
187 : ulong options_sz,
188 : uint if_idx,
189 12 : long ts ) {
190 :
191 12 : FILE * file = (FILE *)_file;
192 12 : FD_TEST( fd_ulong_is_aligned( (ulong)ftell( file ), 4UL ) );
193 :
194 12 : ulong cursor = sizeof(fd_pcapng_epb_t);
195 12 : fd_pcapng_epb_t block = {
196 12 : .block_type = FD_PCAPNG_BLOCK_TYPE_EPB,
197 : /* block_sz set later */
198 12 : .if_idx = if_idx,
199 12 : .ts_hi = (uint)( (ulong)ts >> 32UL ),
200 12 : .ts_lo = (uint)( (ulong)ts ),
201 12 : .cap_len = (uint)payload_sz,
202 12 : .orig_len = (uint)payload_sz
203 12 : };
204 :
205 12 : ulong payload_sz_align = fd_ulong_align_up( payload_sz, 4UL );
206 12 : uchar pad[8UL]={0};
207 12 : ulong pad_sz = payload_sz_align-payload_sz;
208 12 : cursor+=payload_sz_align;
209 :
210 : /* option list */
211 12 : cursor += options_sz;
212 12 : cursor += 4UL;
213 :
214 : /* Trailer */
215 12 : block.block_sz = (uint)cursor+4U;
216 :
217 : /* write header */
218 12 : if( FD_UNLIKELY( 1UL!=fwrite( &block, sizeof(fd_pcapng_epb_t), 1UL, file ) ) )
219 0 : return 0UL;
220 : /* copy payload */
221 12 : if( FD_UNLIKELY( 1UL!=fwrite( payload, payload_sz, 1UL, file ) ) )
222 0 : return 0UL;
223 : /* align */
224 12 : if( pad_sz )
225 9 : if( FD_UNLIKELY( 1UL!=fwrite( pad, pad_sz, 1UL, file ) ) )
226 0 : return 0UL;
227 12 : if( options_sz )
228 0 : if( FD_UNLIKELY( 1UL!=fwrite( options, options_sz, 1UL, file ) ) )
229 0 : return 0UL;
230 : /* empty options */
231 12 : if( FD_UNLIKELY( 1UL!=fwrite( pad, 4UL, 1UL, file ) ) )
232 0 : return 0UL;
233 : /* write length trailer */
234 12 : if( FD_UNLIKELY( 1UL!=fwrite( &block.block_sz, 4UL, 1UL, file ) ) )
235 0 : return 0UL;
236 :
237 12 : return 1UL;
238 12 : }
239 :
240 : ulong
241 : fd_pcapng_fwrite_tls_key_log( uchar const * log,
242 : uint log_sz,
243 6 : void * _file ) {
244 :
245 6 : FILE * file = (FILE *)_file;
246 6 : FD_TEST( fd_ulong_is_aligned( (ulong)ftell( file ), 4UL ) );
247 :
248 6 : ulong cursor = sizeof(fd_pcapng_dsb_t);
249 6 : fd_pcapng_dsb_t block = {
250 6 : .block_type = FD_PCAPNG_BLOCK_TYPE_DSB,
251 : /* block_sz set later */
252 6 : .secret_type = FD_PCAPNG_SECRET_TYPE_TLS,
253 6 : .secret_sz = log_sz
254 6 : };
255 :
256 6 : uint log_sz_align = fd_uint_align_up( log_sz, 4UL );
257 6 : uchar pad[8] = {0};
258 6 : ulong pad_sz = log_sz_align-log_sz;
259 6 : cursor+=log_sz_align;
260 :
261 : /* end of options block */
262 6 : cursor+=4UL;
263 :
264 : /* derive size ahead of time */
265 6 : block.block_sz = (uint)cursor + 4U;
266 :
267 : /* write header */
268 6 : if( FD_UNLIKELY( 1UL!=fwrite( &block, sizeof(fd_pcapng_dsb_t), 1UL, file ) ) )
269 0 : return 0UL;
270 : /* copy log */
271 6 : if( FD_UNLIKELY( 1UL!=fwrite( log, log_sz, 1UL, file ) ) )
272 0 : return 0UL;
273 : /* align */
274 6 : if( pad_sz )
275 6 : if( FD_UNLIKELY( 1UL!=fwrite( pad, pad_sz, 1UL, file ) ) )
276 0 : return 0UL;
277 : /* empty options */
278 6 : if( FD_UNLIKELY( 1UL!=fwrite( pad, 4UL, 1UL, file ) ) )
279 0 : return 0UL;
280 : /* write length trailer */
281 6 : if( FD_UNLIKELY( 1UL!=fwrite( &block.block_sz, sizeof(uint), 1, file ) ) )
282 0 : return 0UL;
283 :
284 6 : return 1UL;
285 6 : }
286 :
287 : #endif /* FD_HAS_HOSTED */
|