LCOV - code coverage report
Current view: top level - util/net - fd_pcapng_iter.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 192 340 56.5 %
Date: 2026-09-17 04:28:31 Functions: 9 11 81.8 %

          Line data    Source code
       1             : #include "fd_pcapng_private.h"
       2             : #include "../fd_util.h"
       3             : #include "../sanitize/fd_msan.h"
       4             : #include <errno.h>
       5             : #include <stdio.h>
       6             : 
       7             : FD_FN_CONST ulong
       8           6 : fd_pcapng_iter_align( void ) {
       9           6 :   return alignof(fd_pcapng_iter_t);
      10           6 : }
      11             : 
      12             : FD_FN_CONST ulong
      13           6 : fd_pcapng_iter_footprint( void ) {
      14           6 :   return sizeof(fd_pcapng_iter_t);
      15           6 : }
      16             : 
      17             : static char const *
      18             : fd_pcapng_iter_strerror( int    error,
      19           0 :                          FILE * file ) {
      20           0 :   static FD_TL char err_cstr_buf[ 1024UL ];
      21           0 :   char * err_cstr = fd_cstr_init( err_cstr_buf );
      22           0 :   if( error==EPROTO ) {
      23           0 :     return fd_cstr_printf( err_cstr, sizeof(err_cstr_buf), NULL, "parse error at %#lx", (ulong)ftell(file) );
      24           0 :   } else if( error==-1 && !feof( file ) ) {
      25           0 :     return "end of section";
      26           0 :   } else {
      27           0 :     return fd_cstr_printf( err_cstr, sizeof(err_cstr_buf), NULL, "%i-%s", error, fd_io_strerror( error ) );
      28           0 :   }
      29           0 : }
      30             : 
      31             : static int
      32             : fd_pcapng_read_block( FILE *                  stream,
      33             :                       fd_pcapng_iter_t *      iter,
      34          33 :                       fd_pcapng_block_hdr_t * _hdr ) {
      35             : 
      36             :   /* Remember offset of block */
      37          33 :   long pos = ftell( stream );
      38          33 :   if( FD_UNLIKELY( pos<0L ) )
      39           0 :     return ferror( stream );
      40          33 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)pos, 4U ) ) ) {
      41           0 :     FD_LOG_DEBUG(( "pcapng: misaligned stream at %#lx", (ulong)pos ));
      42           0 :     return EPROTO;
      43           0 :   }
      44             : 
      45             :   /* Read header */
      46          33 :   fd_pcapng_block_hdr_t hdr;
      47          33 :   if( FD_UNLIKELY( 1UL!=fread( &hdr, sizeof(fd_pcapng_block_hdr_t), 1, stream ) ) ) {
      48           6 :     if( FD_LIKELY( feof( stream ) ) ) return -1; /* eof */
      49           0 :     else                              return ferror( stream );
      50           6 :   }
      51             : 
      52             :   /* Coherence check length field */
      53          27 :   if( FD_UNLIKELY( (hdr.block_sz <   12U) /* header and footer are mandatory */
      54          27 :                  | (hdr.block_sz >32768U) /* way too large */
      55          27 :                  | (!fd_ulong_is_aligned( hdr.block_sz, 4U )) ) ) {
      56           0 :     FD_LOG_DEBUG(( "pcapng: block with invalid size %#x at %#lx", hdr.block_sz, (ulong)pos ));
      57           0 :     return EPROTO;
      58           0 :   }
      59             : 
      60          27 :   if( FD_UNLIKELY( hdr.block_sz>FD_PCAPNG_BLOCK_SZ ) ) {
      61           0 :     FD_LOG_DEBUG(( "pcapng: block too large for buffer (%#x)", hdr.block_sz ));
      62           0 :     return EPROTO;
      63           0 :   }
      64             : 
      65          27 :   memcpy( iter->block_buf, &hdr, sizeof(fd_pcapng_block_hdr_t) );
      66          27 :   ulong remaining = hdr.block_sz - sizeof(fd_pcapng_block_hdr_t);
      67             : 
      68             :   /* Read rest of block */
      69          27 :   if( FD_UNLIKELY( 1UL!=fread( iter->block_buf + sizeof(fd_pcapng_block_hdr_t), remaining, 1, stream ) ) ) {
      70           0 :     if( FD_LIKELY( feof( stream ) ) ) return EPROTO; /* truncated block */
      71           0 :     else                              return ferror( stream );
      72           0 :   }
      73             : 
      74          27 :   iter->block_buf_sz  = hdr.block_sz;
      75          27 :   iter->block_buf_pos = sizeof(fd_pcapng_block_hdr_t);
      76             : 
      77             :   /* Verify footer */
      78          27 :   uint * footer = (uint *)( iter->block_buf + hdr.block_sz - sizeof(uint) );
      79          27 :   uint block_sz = *footer;
      80             : 
      81             :   /* Check that header and footer match */
      82          27 :   if( FD_UNLIKELY( hdr.block_sz != block_sz ) ) {
      83           0 :     FD_LOG_DEBUG(( "pcapng: block size in header and footer don't match at %#lx", (ulong)pos ));
      84           0 :     return EPROTO;
      85           0 :   }
      86             : 
      87          27 :   *_hdr = hdr;
      88             : 
      89          27 :   return 0; /* success */
      90          27 : }
      91             : 
      92             : static int
      93             : fd_pcapng_read_option( fd_pcapng_iter_t *   iter,
      94          45 :                        fd_pcapng_option_t * opt ) {
      95             : 
      96          45 :   if( FD_UNLIKELY( iter->block_buf_pos + 4UL > iter->block_buf_sz ) ) {
      97           3 :     opt->type  = 0;
      98           3 :     opt->sz    = 0;
      99           3 :     opt->value = NULL;
     100           3 :     return 0;
     101           3 :   }
     102             : 
     103          42 :   struct __attribute__((packed)) {
     104          42 :     ushort type;
     105          42 :     ushort sz;
     106          42 :   } opt_hdr;
     107          42 :   memcpy( &opt_hdr, iter->block_buf + iter->block_buf_pos, 4UL );
     108          42 :   iter->block_buf_pos += 4UL;
     109          42 :   if( FD_UNLIKELY( opt_hdr.sz > (iter->block_buf_sz - iter->block_buf_pos) ) ) {
     110           0 :     iter->error = EPROTO;
     111           0 :     FD_LOG_WARNING(( "option size out of bounds" ));
     112           0 :     return EPROTO;
     113           0 :   }
     114             : 
     115          42 :   uint read_sz = fd_uint_min( opt_hdr.sz, opt->sz );
     116          42 :   opt->type = opt_hdr.type;
     117          42 :   opt->sz   = (ushort)read_sz;
     118             : 
     119          42 :   if( read_sz ) {
     120          21 :     if( FD_UNLIKELY( iter->block_buf_pos + read_sz > iter->block_buf_sz ) ) {
     121           0 :     iter->error = EPROTO;
     122           0 :       FD_LOG_WARNING(( "out of bounds option" ));
     123           0 :       return EPROTO;
     124           0 :     }
     125          21 :     memcpy( opt->value, iter->block_buf + iter->block_buf_pos, read_sz );
     126          21 :     fd_msan_unpoison( opt->value, read_sz );
     127          21 :   }
     128             : 
     129          42 :   iter->block_buf_pos += fd_uint_align_up( opt_hdr.sz, 4U );
     130          42 :   if( FD_UNLIKELY( iter->block_buf_pos > iter->block_buf_sz ) )
     131           0 :     return EPROTO;
     132             : 
     133          42 :   return 0; /* success */
     134          42 : }
     135             : 
     136             : fd_pcapng_iter_t *
     137             : fd_pcapng_iter_new( void * mem,
     138           6 :                     void * _file ) {
     139             : 
     140           6 :   if( FD_UNLIKELY( !mem ) ) {
     141           0 :     FD_LOG_WARNING(( "NULL mem" ));
     142           0 :     return NULL;
     143           0 :   }
     144           6 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_pcapng_iter_t) ) ) ) {
     145           0 :     FD_LOG_WARNING(( "unaligned mem" ));
     146           0 :     return NULL;
     147           0 :   }
     148           6 :   if( FD_UNLIKELY( !_file ) ) {
     149           0 :     FD_LOG_WARNING(( "NULL file" ));
     150           0 :     return NULL;
     151           0 :   }
     152             : 
     153           6 :   FILE * file = (FILE *)_file;
     154             : 
     155           6 :   memset( mem, 0, sizeof(fd_pcapng_iter_t) );
     156           6 :   fd_pcapng_iter_t * iter = (fd_pcapng_iter_t *)mem;
     157           6 :   iter->stream = (FILE *)file;
     158           6 :   iter->empty  = 1;
     159             : 
     160             :   /* File starts with a Section Header Block */
     161             : 
     162           6 :   fd_pcapng_block_hdr_t shb_hdr;
     163           6 :   int err = fd_pcapng_read_block( file, iter, &shb_hdr );
     164           6 :   if( FD_UNLIKELY( err ) ) {
     165           0 :     FD_LOG_WARNING(( "pcapng: SHB read failed (%s)", fd_pcapng_iter_strerror( err, file ) ));
     166           0 :     return NULL;
     167           0 :   }
     168           6 :   if( FD_UNLIKELY( shb_hdr.block_type!=FD_PCAPNG_BLOCK_TYPE_SHB
     169           6 :                 || shb_hdr.block_sz  < sizeof(fd_pcapng_shb_t)  ) ) {
     170           0 :     FD_LOG_WARNING(( "pcapng: not a valid Section Header Block" ));
     171           0 :     return NULL;
     172           0 :   }
     173             : 
     174             : 
     175           6 :   fd_pcapng_shb_t shb = FD_LOAD( fd_pcapng_shb_t, iter->block_buf );
     176           6 :   if( FD_UNLIKELY( (shb.version_major!=1) | (shb.version_minor!=0) ) ) {
     177           0 :     FD_LOG_WARNING(( "pcapng: unsupported file format version %u.%u",
     178           0 :                      shb.version_major, shb.version_minor ));
     179           0 :     return NULL;
     180           0 :   }
     181             : 
     182           6 :   return iter;
     183           6 : }
     184             : 
     185             : void *
     186           3 : fd_pcapng_iter_delete( fd_pcapng_iter_t * iter ) {
     187           3 :   void * mem = (void *)iter;
     188           3 :   memset( mem, 0, sizeof(fd_pcapng_iter_t) );
     189           3 :   return mem;
     190           3 : }
     191             : 
     192             : static fd_pcapng_frame_t *
     193          21 : fd_pcapng_iter_next1( fd_pcapng_iter_t * iter ) {
     194          21 :   fd_pcapng_frame_t * pkt = &iter->pkt;
     195             : 
     196             :   /* Clear fields */
     197          21 :   pkt->ts      = 0L;
     198          21 :   pkt->type    = 0U;
     199          21 :   pkt->data_sz = 0U;
     200          21 :   pkt->orig_sz = 0U;
     201          21 :   pkt->if_idx  = 0U;
     202          21 :   pkt->idb     = NULL;
     203             : 
     204          21 :   FILE * stream = iter->stream;
     205             : 
     206             :   /* Attempt a number of times to find a frame of known type.
     207             :      Abort if there are too many unknown frames. */
     208          27 :   for( uint attempt=0U; attempt<256U; attempt++ ) {
     209             : 
     210          27 :     fd_pcapng_block_hdr_t hdr;
     211          27 :     if( FD_UNLIKELY( 0!=(iter->error = fd_pcapng_read_block( stream, iter, &hdr )) ) ) {
     212           6 :       if( FD_UNLIKELY( iter->error != -1 ) )
     213           0 :         FD_LOG_WARNING(( "pcapng: read failed (%s)", fd_pcapng_iter_strerror( iter->error, stream ) ));
     214           6 :       return NULL;
     215           6 :     }
     216             : 
     217          21 :     switch( hdr.block_type ) {
     218           0 :     case FD_PCAPNG_BLOCK_TYPE_SHB: {
     219           0 :       iter->error = -1; /* eof */
     220             :       /* FIXME CONSIDER SILENTLY CONTINUING? */
     221           0 :       return NULL;
     222           0 :     }
     223           6 :     case FD_PCAPNG_BLOCK_TYPE_IDB: {
     224             :       /* Read IDB */
     225           6 :       if( FD_UNLIKELY( hdr.block_sz<sizeof(fd_pcapng_idb_t) ) ) {
     226           0 :         iter->error = EPROTO;
     227           0 :         FD_LOG_WARNING(( "pcapng: invalid IDB block size (%#x)", hdr.block_sz ));
     228           0 :         return NULL;
     229           0 :       }
     230           6 :       fd_pcapng_idb_t idb = FD_LOAD( fd_pcapng_idb_t, iter->block_buf );
     231           6 :       iter->block_buf_pos = sizeof(fd_pcapng_idb_t);
     232             : 
     233             :       /* Add interface to list */
     234           6 :       if( FD_UNLIKELY( iter->iface_cnt>=FD_PCAPNG_IFACE_CNT ) ) {
     235           0 :         iter->error = EPROTO;
     236           0 :         FD_LOG_WARNING(( "pcapng: too many interfaces (max %d)", FD_PCAPNG_IFACE_CNT ));
     237           0 :         return NULL;
     238           0 :       }
     239             : 
     240           6 :       fd_pcapng_idb_desc_t * iface = &iter->iface[ iter->iface_cnt++ ];
     241           6 :       memset( iface, 0, sizeof(fd_pcapng_idb_desc_t) );
     242           6 :       iface->link_type = idb.link_type;
     243             : 
     244             :       /* Read options */
     245          27 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     246          27 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     247          27 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     248          27 :         if( FD_UNLIKELY( 0!=(iter->error = fd_pcapng_read_option( iter, &opt )) ) ) {
     249           0 :           FD_LOG_WARNING(( "pcapng: read failed (%s)", fd_pcapng_iter_strerror( iter->error, stream ) ));
     250           0 :           return NULL;
     251           0 :         }
     252          27 :         if( !opt.type ) break;
     253          21 :         switch( opt.type ) {
     254           0 :         case FD_PCAPNG_OPT_COMMENT:
     255           0 :           FD_LOG_HEXDUMP_DEBUG(( "IDB comment", opt_buf, opt.sz ));
     256           0 :           break;
     257           6 :         case FD_PCAPNG_IDB_OPT_NAME:
     258           6 :           fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( iface->opts.name ), (char const *)opt_buf, fd_ulong_min( sizeof(iface->opts.name)-1, opt.sz ) ) );
     259           6 :           iface->opts.name[ sizeof(iface->opts.name)-1 ] = '\0';
     260           6 :           break;
     261           3 :         case FD_PCAPNG_IDB_OPT_HARDWARE:
     262           3 :           fd_cstr_fini( fd_cstr_append_text( fd_cstr_init( iface->opts.hardware ), (char const *)opt_buf, fd_ulong_min( sizeof(iface->opts.hardware)-1, opt.sz ) ) );
     263           3 :           iface->opts.hardware[ sizeof(iface->opts.hardware)-1 ] = '\0';
     264           3 :           break;
     265           3 :         case FD_PCAPNG_IDB_OPT_IPV4_ADDR:
     266           3 :           if( FD_UNLIKELY( opt.sz!=4U ) )
     267           0 :             continue;
     268           3 :           memcpy( iface->opts.ip4_addr, opt_buf, 4UL );
     269           3 :           break;
     270           3 :         case FD_PCAPNG_IDB_OPT_MAC_ADDR:
     271           3 :           if( FD_UNLIKELY( opt.sz!=6U ) )
     272           0 :             continue;
     273           3 :           memcpy( iface->opts.mac_addr, opt_buf, 6UL );
     274           3 :           break;
     275           6 :         case FD_PCAPNG_IDB_OPT_TSRESOL:
     276           6 :           if( FD_UNLIKELY( opt.sz!=1U ) )
     277           0 :             continue;
     278           6 :           iface->opts.tsresol = opt_buf[ 0 ];
     279           6 :           break;
     280           0 :         default:
     281           0 :           FD_LOG_DEBUG(( "Ignoring unknown IDB option type %#x", opt.type ));
     282           0 :           break;
     283          21 :         }
     284          21 :       }
     285             : 
     286           6 :       break;
     287           6 :     }
     288           6 :     case FD_PCAPNG_BLOCK_TYPE_SPB: {
     289             :       /* Read SPB */
     290           0 :       if( FD_UNLIKELY( hdr.block_sz<sizeof(fd_pcapng_spb_t) ) ) {
     291           0 :         iter->error = EPROTO;
     292           0 :         FD_LOG_WARNING(( "pcapng: invalid SPB block size (%#x)", hdr.block_sz ));
     293           0 :         return NULL;
     294           0 :       }
     295             : 
     296           0 :       uint hdr_sz  = sizeof(fd_pcapng_spb_t);
     297           0 :       uint data_sz = hdr.block_sz - hdr_sz;
     298             : 
     299           0 :       fd_pcapng_spb_t spb = FD_LOAD( fd_pcapng_spb_t, iter->block_buf );
     300           0 :       iter->block_buf_pos = hdr_sz;
     301             : 
     302           0 :       if( FD_UNLIKELY( spb.orig_len > (iter->block_buf_sz - iter->block_buf_pos) ) ) {
     303           0 :         iter->error = EPROTO;
     304           0 :         FD_LOG_WARNING(( "pcapng: invalid SPB block size (%#x)", hdr.block_sz ));
     305           0 :         return NULL;
     306           0 :       }
     307           0 :       pkt->data = iter->block_buf + iter->block_buf_pos;
     308             : 
     309           0 :       pkt->type    = FD_PCAPNG_FRAME_SIMPLE;
     310           0 :       pkt->data_sz = (ushort)data_sz;
     311           0 :       pkt->orig_sz = (ushort)spb.orig_len;
     312           0 :       return pkt;
     313           0 :     }
     314          12 :     case FD_PCAPNG_BLOCK_TYPE_EPB: {
     315             :       /* Read EPB */
     316          12 :       if( FD_UNLIKELY( hdr.block_sz<sizeof(fd_pcapng_epb_t) ) ) {
     317           0 :         iter->error = EPROTO;
     318           0 :         FD_LOG_WARNING(( "pcapng: invalid EPB block size (%#x)", hdr.block_sz ));
     319           0 :         return NULL;
     320           0 :       }
     321             : 
     322          12 :       fd_pcapng_epb_t epb = FD_LOAD( fd_pcapng_epb_t, iter->block_buf );
     323          12 :       iter->block_buf_pos = sizeof(fd_pcapng_epb_t);
     324             : 
     325          12 :       if( FD_UNLIKELY( epb.cap_len > (iter->block_buf_sz - iter->block_buf_pos) ) ) {
     326           0 :         iter->error = EPROTO;
     327           0 :         FD_LOG_WARNING(( "pcapng: invalid EPB block size (%#x)", hdr.block_sz ));
     328           0 :         return NULL;
     329           0 :       }
     330          12 :       pkt->data = iter->block_buf + iter->block_buf_pos;
     331          12 :       iter->block_buf_pos += fd_uint_align_up( epb.cap_len, 4U );
     332             : 
     333             :       /* Read options */
     334          15 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     335          15 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     336          15 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     337          15 :         if( FD_UNLIKELY( 0!=(iter->error = fd_pcapng_read_option( iter, &opt )) ) ) {
     338           0 :           FD_LOG_WARNING(( "pcapng: read failed (%s)", fd_pcapng_iter_strerror( iter->error, stream ) ));
     339           0 :           return NULL;
     340           0 :         }
     341          15 :         if( !opt.type ) break;
     342           3 :         switch( opt.type ) {
     343           0 :         case FD_PCAPNG_OPT_COMMENT:
     344           0 :           FD_LOG_HEXDUMP_DEBUG(( "Packet comment", opt_buf, opt.sz ));
     345           0 :           break;
     346           3 :         default:
     347           3 :           FD_LOG_DEBUG(( "Ignoring unknown EPB option type %#x", opt.type ));
     348           3 :           break;
     349           3 :         }
     350           3 :       }
     351             : 
     352          12 :       if( FD_LIKELY( epb.if_idx < iter->iface_cnt ) ) {
     353          12 :         ulong raw = ( ((ulong)epb.ts_hi << 32UL) | (ulong)epb.ts_lo );
     354             :         /* FIXME support more timestamp resolutions */
     355          12 :         if( iter->iface[ epb.if_idx ].opts.tsresol == FD_PCAPNG_TSRESOL_NS ) {
     356          12 :           pkt->ts = (long)raw;
     357          12 :         }
     358          12 :       }
     359             : 
     360          12 :       pkt->type    = FD_PCAPNG_FRAME_ENHANCED;
     361          12 :       pkt->data_sz = (ushort)epb.cap_len;
     362          12 :       pkt->orig_sz = (ushort)epb.orig_len;
     363          12 :       pkt->if_idx  = epb.if_idx;
     364          12 :       pkt->idb     = (epb.if_idx<iter->iface_cnt) ? &iter->iface[ epb.if_idx ] : NULL;
     365          12 :       return pkt;
     366          12 :     }
     367           3 :     case FD_PCAPNG_BLOCK_TYPE_DSB: {
     368             :       /* Read DSB */
     369           3 :       if( FD_UNLIKELY( hdr.block_sz<sizeof(fd_pcapng_dsb_t) ) ) {
     370           0 :         iter->error = EPROTO;
     371           0 :         FD_LOG_WARNING(( "pcapng: invalid DSB block size (%#x)", hdr.block_sz ));
     372           0 :         return NULL;
     373           0 :       }
     374             : 
     375           3 :       fd_pcapng_dsb_t dsb = FD_LOAD( fd_pcapng_dsb_t, iter->block_buf );
     376           3 :       iter->block_buf_pos = sizeof(fd_pcapng_dsb_t);
     377             : 
     378           3 :       if( FD_UNLIKELY( dsb.secret_sz > (iter->block_buf_sz - iter->block_buf_pos) ) ) {
     379           0 :         iter->error = EPROTO;
     380           0 :         FD_LOG_WARNING(( "pcapng: invalid DSB block size (%#x)", hdr.block_sz ));
     381           0 :         return NULL;
     382           0 :       }
     383           3 :       pkt->data = iter->block_buf + sizeof(fd_pcapng_dsb_t);
     384           3 :       iter->block_buf_pos += fd_uint_align_up( dsb.secret_sz, 4U );
     385             : 
     386             :       /* Read options */
     387           3 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     388           3 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     389           3 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     390           3 :         if( FD_UNLIKELY( 0!=(iter->error = fd_pcapng_read_option( iter, &opt )) ) ) {
     391           0 :           FD_LOG_WARNING(( "pcapng: read failed (%s)", fd_pcapng_iter_strerror( iter->error, stream ) ));
     392           0 :           return NULL;
     393           0 :         }
     394           3 :         if( !opt.type ) break;
     395           0 :         switch( opt.type ) {
     396           0 :         case FD_PCAPNG_OPT_COMMENT:
     397           0 :           FD_LOG_HEXDUMP_DEBUG(( "Decryption secrets comment", opt_buf, opt.sz ));
     398           0 :           break;
     399           0 :         default:
     400           0 :           FD_LOG_DEBUG(( "Ignoring unknown DSB option type %#x", opt.type ));
     401           0 :           break;
     402           0 :         }
     403           0 :       }
     404             : 
     405           3 :       if( dsb.secret_type!=FD_PCAPNG_SECRET_TYPE_TLS ) {
     406           0 :         FD_LOG_DEBUG(( "Ignoring secret (type %#x)", dsb.secret_type ));
     407           0 :         break;
     408           0 :       }
     409             : 
     410           3 :       pkt->type    = FD_PCAPNG_FRAME_TLSKEYS;
     411           3 :       pkt->data_sz = dsb.secret_sz;
     412           3 :       return pkt;
     413           3 :     }
     414           0 :     default:
     415           0 :       FD_LOG_DEBUG(( "pcapng: skipping unknown block (type=%#x)", hdr.block_type ));
     416           0 :       break;
     417          21 :     }
     418          21 :   }
     419             : 
     420             :   /* Found no blocks that are interesting to user */
     421           0 :   iter->error = EPROTO;
     422           0 :   FD_LOG_WARNING(( "pcapng: aborting, too many non-packet frames" ));
     423           0 :   return NULL;
     424          21 : }
     425             : 
     426             : fd_pcapng_frame_t *
     427          21 : fd_pcapng_iter_next( fd_pcapng_iter_t * iter ) {
     428          21 :   fd_pcapng_frame_t * frame = fd_pcapng_iter_next1( iter );
     429          21 :   iter->empty = !frame;
     430          21 :   return frame;
     431          21 : }
     432             : 
     433             : fd_pcapng_frame_t *
     434           0 : fd_pcapng_iter_ele( fd_pcapng_iter_t * iter ) {
     435           0 :   if( FD_UNLIKELY( iter->empty ) ) return NULL;
     436           0 :   return &iter->pkt;
     437           0 : }
     438             : 
     439             : FD_FN_PURE int
     440           9 : fd_pcapng_iter_err( fd_pcapng_iter_t const * iter ) {
     441           9 :   return iter->error;
     442           9 : }

Generated by: LCOV version 1.14