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