LCOV - code coverage report
Current view: top level - util/net - fd_pcapng_iter.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 340 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 11 0.0 %

          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           0 : fd_pcapng_iter_align( void ) {
       9           0 :   return alignof(fd_pcapng_iter_t);
      10           0 : }
      11             : 
      12             : FD_FN_CONST ulong
      13           0 : fd_pcapng_iter_footprint( void ) {
      14           0 :   return sizeof(fd_pcapng_iter_t);
      15           0 : }
      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           0 :                       fd_pcapng_block_hdr_t * _hdr ) {
      35             : 
      36             :   /* Remember offset of block */
      37           0 :   long pos = ftell( stream );
      38           0 :   if( FD_UNLIKELY( pos<0L ) )
      39           0 :     return ferror( stream );
      40           0 :   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           0 :   fd_pcapng_block_hdr_t hdr;
      47           0 :   if( FD_UNLIKELY( 1UL!=fread( &hdr, sizeof(fd_pcapng_block_hdr_t), 1, stream ) ) ) {
      48           0 :     if( FD_LIKELY( feof( stream ) ) ) return -1; /* eof */
      49           0 :     else                              return ferror( stream );
      50           0 :   }
      51             : 
      52             :   /* Coherence check length field */
      53           0 :   if( FD_UNLIKELY( (hdr.block_sz <   12U) /* header and footer are mandatory */
      54           0 :                  | (hdr.block_sz >32768U) /* way too large */
      55           0 :                  | (!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           0 :   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           0 :   memcpy( iter->block_buf, &hdr, sizeof(fd_pcapng_block_hdr_t) );
      66           0 :   ulong remaining = hdr.block_sz - sizeof(fd_pcapng_block_hdr_t);
      67             : 
      68             :   /* Read rest of block */
      69           0 :   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           0 :   iter->block_buf_sz  = hdr.block_sz;
      75           0 :   iter->block_buf_pos = sizeof(fd_pcapng_block_hdr_t);
      76             : 
      77             :   /* Verify footer */
      78           0 :   uint * footer = (uint *)( iter->block_buf + hdr.block_sz - sizeof(uint) );
      79           0 :   uint block_sz = *footer;
      80             : 
      81             :   /* Check that header and footer match */
      82           0 :   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           0 :   *_hdr = hdr;
      88             : 
      89           0 :   return 0; /* success */
      90           0 : }
      91             : 
      92             : static int
      93             : fd_pcapng_read_option( fd_pcapng_iter_t *   iter,
      94           0 :                        fd_pcapng_option_t * opt ) {
      95             : 
      96           0 :   if( FD_UNLIKELY( iter->block_buf_pos + 4UL > iter->block_buf_sz ) ) {
      97           0 :     opt->type  = 0;
      98           0 :     opt->sz    = 0;
      99           0 :     opt->value = NULL;
     100           0 :     return 0;
     101           0 :   }
     102             : 
     103           0 :   struct __attribute__((packed)) {
     104           0 :     ushort type;
     105           0 :     ushort sz;
     106           0 :   } opt_hdr;
     107           0 :   memcpy( &opt_hdr, iter->block_buf + iter->block_buf_pos, 4UL );
     108           0 :   iter->block_buf_pos += 4UL;
     109           0 :   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           0 :   uint read_sz = fd_uint_min( opt_hdr.sz, opt->sz );
     116           0 :   opt->type = opt_hdr.type;
     117           0 :   opt->sz   = (ushort)read_sz;
     118             : 
     119           0 :   if( read_sz ) {
     120           0 :     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           0 :     memcpy( opt->value, iter->block_buf + iter->block_buf_pos, read_sz );
     126           0 :     fd_msan_unpoison( opt->value, read_sz );
     127           0 :   }
     128             : 
     129           0 :   iter->block_buf_pos += fd_uint_align_up( opt_hdr.sz, 4U );
     130           0 :   if( FD_UNLIKELY( iter->block_buf_pos > iter->block_buf_sz ) )
     131           0 :     return EPROTO;
     132             : 
     133           0 :   return 0; /* success */
     134           0 : }
     135             : 
     136             : fd_pcapng_iter_t *
     137             : fd_pcapng_iter_new( void * mem,
     138           0 :                     void * _file ) {
     139             : 
     140           0 :   if( FD_UNLIKELY( !mem ) ) {
     141           0 :     FD_LOG_WARNING(( "NULL mem" ));
     142           0 :     return NULL;
     143           0 :   }
     144           0 :   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           0 :   if( FD_UNLIKELY( !_file ) ) {
     149           0 :     FD_LOG_WARNING(( "NULL file" ));
     150           0 :     return NULL;
     151           0 :   }
     152             : 
     153           0 :   FILE * file = (FILE *)_file;
     154             : 
     155           0 :   memset( mem, 0, sizeof(fd_pcapng_iter_t) );
     156           0 :   fd_pcapng_iter_t * iter = (fd_pcapng_iter_t *)mem;
     157           0 :   iter->stream = (FILE *)file;
     158           0 :   iter->empty  = 1;
     159             : 
     160             :   /* File starts with a Section Header Block */
     161             : 
     162           0 :   fd_pcapng_block_hdr_t shb_hdr;
     163           0 :   int err = fd_pcapng_read_block( file, iter, &shb_hdr );
     164           0 :   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           0 :   if( FD_UNLIKELY( shb_hdr.block_type!=FD_PCAPNG_BLOCK_TYPE_SHB
     169           0 :                 || 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           0 :   fd_pcapng_shb_t shb = FD_LOAD( fd_pcapng_shb_t, iter->block_buf );
     176           0 :   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           0 :   return iter;
     183           0 : }
     184             : 
     185             : void *
     186           0 : fd_pcapng_iter_delete( fd_pcapng_iter_t * iter ) {
     187           0 :   void * mem = (void *)iter;
     188           0 :   memset( mem, 0, sizeof(fd_pcapng_iter_t) );
     189           0 :   return mem;
     190           0 : }
     191             : 
     192             : static fd_pcapng_frame_t *
     193           0 : fd_pcapng_iter_next1( fd_pcapng_iter_t * iter ) {
     194           0 :   fd_pcapng_frame_t * pkt = &iter->pkt;
     195             : 
     196             :   /* Clear fields */
     197           0 :   pkt->ts      = 0L;
     198           0 :   pkt->type    = 0U;
     199           0 :   pkt->data_sz = 0U;
     200           0 :   pkt->orig_sz = 0U;
     201           0 :   pkt->if_idx  = 0U;
     202           0 :   pkt->idb     = NULL;
     203             : 
     204           0 :   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           0 :   for( uint attempt=0U; attempt<256U; attempt++ ) {
     209             : 
     210           0 :     fd_pcapng_block_hdr_t hdr;
     211           0 :     if( FD_UNLIKELY( 0!=(iter->error = fd_pcapng_read_block( stream, iter, &hdr )) ) ) {
     212           0 :       if( FD_UNLIKELY( iter->error != -1 ) )
     213           0 :         FD_LOG_WARNING(( "pcapng: read failed (%s)", fd_pcapng_iter_strerror( iter->error, stream ) ));
     214           0 :       return NULL;
     215           0 :     }
     216             : 
     217           0 :     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           0 :     case FD_PCAPNG_BLOCK_TYPE_IDB: {
     224             :       /* Read IDB */
     225           0 :       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           0 :       fd_pcapng_idb_t idb = FD_LOAD( fd_pcapng_idb_t, iter->block_buf );
     231           0 :       iter->block_buf_pos = sizeof(fd_pcapng_idb_t);
     232             : 
     233             :       /* Add interface to list */
     234           0 :       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           0 :       fd_pcapng_idb_desc_t * iface = &iter->iface[ iter->iface_cnt++ ];
     241           0 :       memset( iface, 0, sizeof(fd_pcapng_idb_desc_t) );
     242           0 :       iface->link_type = idb.link_type;
     243             : 
     244             :       /* Read options */
     245           0 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     246           0 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     247           0 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     248           0 :         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           0 :         if( !opt.type ) break;
     253           0 :         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           0 :         case FD_PCAPNG_IDB_OPT_NAME:
     258           0 :           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           0 :           iface->opts.name[ sizeof(iface->opts.name)-1 ] = '\0';
     260           0 :           break;
     261           0 :         case FD_PCAPNG_IDB_OPT_HARDWARE:
     262           0 :           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           0 :           iface->opts.hardware[ sizeof(iface->opts.hardware)-1 ] = '\0';
     264           0 :           break;
     265           0 :         case FD_PCAPNG_IDB_OPT_IPV4_ADDR:
     266           0 :           if( FD_UNLIKELY( opt.sz!=4U ) )
     267           0 :             continue;
     268           0 :           memcpy( iface->opts.ip4_addr, opt_buf, 4UL );
     269           0 :           break;
     270           0 :         case FD_PCAPNG_IDB_OPT_MAC_ADDR:
     271           0 :           if( FD_UNLIKELY( opt.sz!=6U ) )
     272           0 :             continue;
     273           0 :           memcpy( iface->opts.mac_addr, opt_buf, 6UL );
     274           0 :           break;
     275           0 :         case FD_PCAPNG_IDB_OPT_TSRESOL:
     276           0 :           if( FD_UNLIKELY( opt.sz!=1U ) )
     277           0 :             continue;
     278           0 :           iface->opts.tsresol = opt_buf[ 0 ];
     279           0 :           break;
     280           0 :         default:
     281           0 :           FD_LOG_DEBUG(( "Ignoring unknown IDB option type %#x", opt.type ));
     282           0 :           break;
     283           0 :         }
     284           0 :       }
     285             : 
     286           0 :       break;
     287           0 :     }
     288           0 :     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           0 :     case FD_PCAPNG_BLOCK_TYPE_EPB: {
     315             :       /* Read EPB */
     316           0 :       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           0 :       fd_pcapng_epb_t epb = FD_LOAD( fd_pcapng_epb_t, iter->block_buf );
     323           0 :       iter->block_buf_pos = sizeof(fd_pcapng_epb_t);
     324             : 
     325           0 :       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           0 :       pkt->data = iter->block_buf + iter->block_buf_pos;
     331           0 :       iter->block_buf_pos += fd_uint_align_up( epb.cap_len, 4U );
     332             : 
     333             :       /* Read options */
     334           0 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     335           0 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     336           0 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     337           0 :         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           0 :         if( !opt.type ) break;
     342           0 :         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           0 :         default:
     347           0 :           FD_LOG_DEBUG(( "Ignoring unknown EPB option type %#x", opt.type ));
     348           0 :           break;
     349           0 :         }
     350           0 :       }
     351             : 
     352           0 :       if( FD_LIKELY( epb.if_idx < iter->iface_cnt ) ) {
     353           0 :         ulong raw = ( ((ulong)epb.ts_hi << 32UL) | (ulong)epb.ts_lo );
     354             :         /* FIXME support more timestamp resolutions */
     355           0 :         if( iter->iface[ epb.if_idx ].opts.tsresol == FD_PCAPNG_TSRESOL_NS ) {
     356           0 :           pkt->ts = (long)raw;
     357           0 :         }
     358           0 :       }
     359             : 
     360           0 :       pkt->type    = FD_PCAPNG_FRAME_ENHANCED;
     361           0 :       pkt->data_sz = (ushort)epb.cap_len;
     362           0 :       pkt->orig_sz = (ushort)epb.orig_len;
     363           0 :       pkt->if_idx  = epb.if_idx;
     364           0 :       pkt->idb     = (epb.if_idx<iter->iface_cnt) ? &iter->iface[ epb.if_idx ] : NULL;
     365           0 :       return pkt;
     366           0 :     }
     367           0 :     case FD_PCAPNG_BLOCK_TYPE_DSB: {
     368             :       /* Read DSB */
     369           0 :       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           0 :       fd_pcapng_dsb_t dsb = FD_LOAD( fd_pcapng_dsb_t, iter->block_buf );
     376           0 :       iter->block_buf_pos = sizeof(fd_pcapng_dsb_t);
     377             : 
     378           0 :       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           0 :       pkt->data = iter->block_buf + sizeof(fd_pcapng_dsb_t);
     384           0 :       iter->block_buf_pos += fd_uint_align_up( dsb.secret_sz, 4U );
     385             : 
     386             :       /* Read options */
     387           0 :       for( uint j=0; j<FD_PCAPNG_MAX_OPT_CNT; j++ ) {
     388           0 :         uchar opt_buf[ 128UL ] __attribute__((aligned(32UL)));
     389           0 :         fd_pcapng_option_t opt = { .sz=sizeof(opt_buf), .value=&opt_buf };
     390           0 :         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           0 :         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           0 :       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           0 :       pkt->type    = FD_PCAPNG_FRAME_TLSKEYS;
     411           0 :       pkt->data_sz = dsb.secret_sz;
     412           0 :       return pkt;
     413           0 :     }
     414           0 :     default:
     415           0 :       FD_LOG_DEBUG(( "pcapng: skipping unknown block (type=%#x)", hdr.block_type ));
     416           0 :       break;
     417           0 :     }
     418           0 :   }
     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           0 : }
     425             : 
     426             : fd_pcapng_frame_t *
     427           0 : fd_pcapng_iter_next( fd_pcapng_iter_t * iter ) {
     428           0 :   fd_pcapng_frame_t * frame = fd_pcapng_iter_next1( iter );
     429           0 :   iter->empty = !frame;
     430           0 :   return frame;
     431           0 : }
     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           0 : fd_pcapng_iter_err( fd_pcapng_iter_t const * iter ) {
     441           0 :   return iter->error;
     442           0 : }

Generated by: LCOV version 1.14