LCOV - code coverage report
Current view: top level - util/net - fd_net_headers.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 44 44 100.0 %
Date: 2026-09-17 04:28:31 Functions: 4 462 0.9 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_net_fd_net_headers_h
       2             : #define HEADER_fd_src_util_net_fd_net_headers_h
       3             : 
       4             : #include "fd_udp.h"
       5             : #include "fd_eth.h"
       6             : 
       7             : /* fd_ip4_udp_hdrs is useful to construct Ethernet+IPv4+UDP network
       8             :    headers. Assumes that the IPv4 header has no options (IHL=5). */
       9             : 
      10             : union fd_ip4_udp_hdrs {
      11             :   uchar uc[ 42 ];
      12             :   struct {
      13             :     fd_eth_hdr_t eth[1];
      14             :     fd_ip4_hdr_t ip4[1];
      15             :     fd_udp_hdr_t udp[1];
      16             :   };
      17             : };
      18             : 
      19             : typedef union fd_ip4_udp_hdrs fd_ip4_udp_hdrs_t;
      20             : 
      21             : FD_PROTOTYPES_BEGIN
      22             : 
      23             : /* Helper method to populate a header template containing Ethernet,
      24             :    IPv4 (no options), and UDP headers.  Note that IPv4 and UDP header
      25             :    checksums are set to 0. */
      26             : 
      27             : static inline fd_ip4_udp_hdrs_t *
      28             : fd_ip4_udp_hdr_init( fd_ip4_udp_hdrs_t * hdrs,
      29             :                      ulong               payload_sz,
      30             :                      uint                src_ip,
      31         189 :                      ushort              src_port ) {
      32         189 :   fd_eth_hdr_t * eth = hdrs->eth;
      33         189 :   memset( eth->dst, 0, 6UL );
      34         189 :   memset( eth->src, 0, 6UL );
      35         189 :   eth->net_type  = fd_ushort_bswap( FD_ETH_HDR_TYPE_IP );
      36             : 
      37         189 :   fd_ip4_hdr_t * ip4 = hdrs->ip4;
      38         189 :   ip4->verihl       = FD_IP4_VERIHL( 4U, 5U );
      39         189 :   ip4->tos          = (uchar)0;
      40         189 :   ip4->net_tot_len  = fd_ushort_bswap( (ushort)(payload_sz + sizeof(fd_ip4_hdr_t)+sizeof(fd_udp_hdr_t)) );
      41         189 :   ip4->net_frag_off = fd_ushort_bswap( FD_IP4_HDR_FRAG_OFF_DF );
      42         189 :   ip4->ttl          = (uchar)64;
      43         189 :   ip4->protocol     = FD_IP4_HDR_PROTOCOL_UDP;
      44         189 :   ip4->check        = 0U;
      45         189 :   ip4->saddr        = src_ip;
      46         189 :   ip4->daddr        = 0;
      47             : 
      48         189 :   fd_udp_hdr_t * udp = hdrs->udp;
      49         189 :   udp->net_sport = fd_ushort_bswap( src_port );
      50         189 :   udp->net_dport = (ushort)0;
      51         189 :   udp->net_len   = fd_ushort_bswap( (ushort)(payload_sz + sizeof(fd_udp_hdr_t)) );
      52         189 :   udp->check     = (ushort)0;
      53             : 
      54         189 :   return hdrs;
      55         189 : }
      56             : 
      57             : FD_PROTOTYPES_END
      58             : 
      59             : union fd_ip4_port {
      60             :   struct {
      61             :     uint   addr;  /* net order */
      62             :     ushort port;  /* net order */
      63             :   };
      64             :   ulong l : 48;
      65             : };
      66             : 
      67             : typedef union fd_ip4_port fd_ip4_port_t;
      68             : 
      69             : /* fd_ip4_udp_hdr_strip deconstructs a network packet.  If any opt_* are
      70             :    set to NULL, then they are not populated. It copies pointers to
      71             :    Ethernet, IPv4 (no options), and UDP headers into opt_eth, opt_ip4,
      72             :    and opt_udp respectively. It copies a pointer to the start of the
      73             :    packet payload into opt_payload, and the packet payload size into
      74             :    opt_payload_sz.
      75             : 
      76             :    A few basic integrity checks are preformed on included size fields.
      77             :    Returns 1 on success and 0 on failure */
      78             : 
      79             : static inline int
      80             : fd_ip4_udp_hdr_strip( uchar const *         data,
      81             :                       ulong                 data_sz,
      82             :                       uchar ** const        opt_payload,
      83             :                       ulong *               opt_payload_sz,
      84             :                       fd_eth_hdr_t ** const opt_eth,
      85             :                       fd_ip4_hdr_t ** const opt_ip4,
      86         165 :                       fd_udp_hdr_t ** const opt_udp ) {
      87         165 :   ulong const eth_ip4_sz = sizeof(fd_eth_hdr_t) + sizeof(fd_ip4_hdr_t);
      88         165 :   if( FD_UNLIKELY( data_sz<eth_ip4_sz ) ) return 0;
      89             : 
      90         159 :   fd_eth_hdr_t const * eth        = (fd_eth_hdr_t const *)data;
      91         159 :   fd_ip4_hdr_t const * ip4        = (fd_ip4_hdr_t const *)( data + sizeof(fd_eth_hdr_t) );
      92         159 :   ulong const          ip4_hdr_sz = FD_IP4_GET_LEN( *ip4 );
      93             : 
      94             :   /* IHL cannot place the UDP header inside the minimum IPv4 header. */
      95         159 :   if( FD_UNLIKELY( ip4_hdr_sz<sizeof(fd_ip4_hdr_t) ) ) return 0;
      96             : 
      97         144 :   ulong const hdr_sz = sizeof(fd_eth_hdr_t) + ip4_hdr_sz + sizeof(fd_udp_hdr_t);
      98             : 
      99             :   /* data_sz is less than the observed combined header size */
     100         144 :   if( FD_UNLIKELY( data_sz<hdr_sz ) ) return 0;
     101             : 
     102         144 :   fd_udp_hdr_t const * udp = (fd_udp_hdr_t const *)( data + sizeof(fd_eth_hdr_t) + ip4_hdr_sz );
     103         144 :   ulong udp_sz = fd_ushort_bswap( udp->net_len );
     104             : 
     105             :   /* observed udp_hdr+payload sz is smaller than minimum udp header sz */
     106         144 :   if( FD_UNLIKELY( udp_sz<sizeof(fd_udp_hdr_t) ) ) return 0;
     107         144 :   ulong payload_sz_ = udp_sz-sizeof(fd_udp_hdr_t);
     108         144 :   uchar * payload_ = (uchar *)( data + hdr_sz );
     109             : 
     110             :   /* payload_sz is greater than the total packet size */
     111         144 :   if( FD_UNLIKELY( payload_sz_>data_sz-hdr_sz ) ) return 0;
     112             : 
     113         144 :   if( opt_eth        ) *opt_eth        = (fd_eth_hdr_t *)eth;
     114         144 :   if( opt_ip4        ) *opt_ip4        = (fd_ip4_hdr_t *)ip4;
     115         144 :   if( opt_udp        ) *opt_udp        = (fd_udp_hdr_t *)udp;
     116         144 :   if( opt_payload    ) *opt_payload    = payload_;
     117         144 :   if( opt_payload_sz ) *opt_payload_sz = payload_sz_;
     118             : 
     119         144 :   return 1;
     120         144 : }
     121             : 
     122             : #endif /* HEADER_fd_src_util_net_fd_net_headers_h */

Generated by: LCOV version 1.14