LCOV - code coverage report
Current view: top level - util/net - fd_pcapng.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 117 157 74.5 %
Date: 2025-12-06 04:45:29 Functions: 4 6 66.7 %

          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 */

Generated by: LCOV version 1.14