Line data Source code
1 : #ifndef HEADER_fd_src_util_net_fd_udp_h 2 : #define HEADER_fd_src_util_net_fd_udp_h 3 : 4 : #include "fd_ip4.h" /* UDP is tightly tied to IP regardless of standard intent due to pseudo header layer violating BS */ 5 : 6 : /* FIXME: UDP CRASH COURSE HERE */ 7 : 8 : union fd_udp_hdr { 9 : struct { 10 : ushort net_sport; /* src port, net order */ 11 : ushort net_dport; /* dst port, net order */ 12 : ushort net_len; /* datagram length, from first byte of this header to last byte of the udp payload */ 13 : ushort check; /* UDP checksum ("invariant" order), from first byte of pseudo header prepended before this header to last 14 : byte of udp payload with zero padding to even length inclusive. In IP4, 0 indicates no checksum. */ 15 : }; 16 : uchar uc[8]; 17 : }; 18 : 19 : typedef union fd_udp_hdr fd_udp_hdr_t; 20 : 21 : /* FIXME: CONSIDER A PRETTY PRINTER FOR A FD_UDP_HDR? */ 22 : 23 : FD_PROTOTYPES_BEGIN 24 : 25 : /* fd_ip4_udp_check is used for udp check field computation and 26 : validation. If the dgram has no checksum (check==0), this returns 27 : the value to use for check. If the dgram has a checksum (check!=0), 28 : this returns 0 if the message has a valid checksum or non-zero if 29 : not. ip4_saddr and ip4_daddr are the ip4 source and destination 30 : addresses to use for the udp pseudo header. udp is a non-NULL 31 : pointer to the first byte of a memory region containing the udp 32 : header and dgram is a non-NULL pointer to the first byte of a memory 33 : region containing a datagram of size: 34 : 35 : dgram_sz = fd_ushort_bswap(udp->net_len) - sizeof(fd_udp_hdr_t) 36 : 37 : bytes. This assumes it is safe to read up to 3 bytes past the end of 38 : dgram (technically it will read the fd_align_up(dgram_sz,4UL) bytes 39 : dgram). The contents of the tail read region are irrelevant. 40 : 41 : This is neither a particularly fast calculation (reasonably fast 42 : O(dgram_sz)) nor a particularly robust and it can inhibit cut-through 43 : usage. So in general it is best to avoid UDP checksums, usually by 44 : exploiting their optionality in IP4 (note that the Ethernet CRC is 45 : reasonably strong and still provides protection). 46 : 47 : As such, this is mostly here for the rare application that needs to 48 : manually compute / validate UDP checksums (e.g. overhead doesn't 49 : matter or when the hardware sending/receiving the packet doesn't do 50 : various checksum offload computations and UDP checksums are 51 : required). */ 52 : 53 : FD_FN_PURE static inline ushort 54 : fd_ip4_udp_check( uint ip4_saddr, 55 : uint ip4_daddr, 56 : fd_udp_hdr_t const * udp, 57 0 : void const * dgram ) { /* Assumed safe to tail read up to 3 bytes past end of msg */ 58 0 : ushort net_len = udp->net_len; /* In net order */ 59 0 : uint rem = (uint)fd_ushort_bswap( net_len ) - (uint)sizeof(fd_udp_hdr_t); 60 0 : 61 0 : /* Sum the pseudo header and UDP header words */ 62 0 : ulong ul = ((((ulong)FD_IP4_HDR_PROTOCOL_UDP)<<8) | (((ulong)net_len)<<16)) 63 0 : + ((ulong)ip4_saddr) 64 0 : + ((ulong)ip4_daddr) 65 0 : + ((ulong)FD_LOAD( uint, udp->uc )) 66 0 : + ((ulong)FD_LOAD( uint, udp->uc+4 )); 67 0 : 68 0 : /* Sum the dgram words (reads up to 4 past end of msg) */ 69 0 : uchar const * u = dgram; 70 0 : for( ; rem>3U; rem-=4U, u+=4 ) ul += (ulong)FD_LOAD( uint, u ); 71 0 : ul += (ulong)( FD_LOAD( uint, u ) & ((1U<<(8U*rem))-1U) ); 72 0 : 73 0 : /* Reduce the sum to a 16-bit one's complement sum */ 74 0 : ul = ( ul>>32 ) + 75 0 : ((ul>>16) & 0xffffUL) + 76 0 : ( ul & 0xffffUL); 77 0 : ul = ( ul>>16 ) + 78 0 : ( ul & 0xffffUL); 79 0 : ul += ( ul>>16 ); 80 0 : 81 0 : /* And complement it */ 82 0 : return (ushort)~ul; 83 0 : } 84 : 85 : /* fd_udp_hdr_bswap reverses the endianness of all fields in the UDP 86 : header. */ 87 : 88 : static inline void 89 27717935 : fd_udp_hdr_bswap( fd_udp_hdr_t * hdr ) { 90 27717935 : hdr->net_sport = (ushort)fd_ushort_bswap( hdr->net_sport ); 91 27717935 : hdr->net_dport = (ushort)fd_ushort_bswap( hdr->net_dport ); 92 27717935 : hdr->net_len = (ushort)fd_ushort_bswap( hdr->net_len ); 93 27717935 : hdr->check = (ushort)fd_ushort_bswap( hdr->check ); 94 27717935 : } 95 : 96 : FD_PROTOTYPES_END 97 : 98 : #endif /* HEADER_fd_src_util_net_fd_udp_h */