LCOV - code coverage report
Current view: top level - util/net - fd_pcapng_iter.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 175 336 52.1 %
Date: 2025-12-06 04:45:29 Functions: 8 11 72.7 %

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

Generated by: LCOV version 1.14