Line data Source code
1 : #ifndef HEADER_fd_src_util_net_fd_igmp_h 2 : #define HEADER_fd_src_util_net_fd_igmp_h 3 : 4 : #include <string.h> 5 : 6 : #include "fd_ip4.h" 7 : 8 : /* FIXME: IGMP CRASH COURSE HERE */ 9 : 10 : /* FD_IGMP_TYPE_{QUERY,V1_REPORT,V2_REPORT,V2_LEAVE}: 11 : 12 : QUERY - IGMP is a query (if to a specific ip4, specific query, if to 13 : 224.0.0.1, general query) from LAN switch regarding host's 14 : mcast join status 15 : V1_REPORT - IGMP is a V1 report to router indicating to join / remain 16 : in mcast group (V1 IGMP host) 17 : V2_REPORT - IGMP is a V2 report to router indicating to join / remain 18 : in mcast group (V1 IGMP host) 19 : LEAVE - IGMP is a V2 report to router indicating to leave mcast 20 : group (V2 IGMP host) */ 21 : 22 : #define FD_IGMP_TYPE_QUERY ((uchar)0x11) 23 : #define FD_IGMP_TYPE_V1_REPORT ((uchar)0x12) 24 : #define FD_IGMP_TYPE_V2_REPORT ((uchar)0x16) 25 : #define FD_IGMP_TYPE_V2_LEAVE ((uchar)0x17) 26 : 27 : union fd_igmp { 28 : struct { 29 : uchar type; /* IGMP type */ 30 : uchar resp; /* v1 - 0 on send, ignore on recv, v2 - 0 on send, required response time in 0.1 s increments on recv */ 31 : ushort check; /* IGMP checksum ("invariant" order) */ 32 : uint group; /* IGMP group (IP4 mcast addr), technically net order but all APIs below work with this directly */ 33 : }; 34 : uint u[2]; /* Used for checksum calcs */ 35 : }; 36 : 37 : typedef union fd_igmp fd_igmp_t; 38 : 39 : /* FIXME: CONSIDER AN OVERALL IGMP PRETTY PRINTER? */ 40 : 41 : struct fd_ip4_igmp { 42 : fd_ip4_hdr_t ip4[1]; 43 : uchar opt[4]; 44 : fd_igmp_t igmp[1]; 45 : }; 46 : 47 : typedef struct fd_ip4_igmp fd_ip4_igmp_t; 48 : 49 : FD_PROTOTYPES_BEGIN 50 : 51 : /* fd_igmp_check is used for igmp check field computation and 52 : validation. igmp points to the first byte a memory region containing 53 : an igmp message. If the message has no checksum (check==0), this 54 : returns the value to use for check. If the message has a checksum 55 : (check!=0), this returns 0 if message has a valid checksum or 56 : non-zero if not. Reasonably fast O(1). */ 57 : 58 : FD_FN_PURE static inline ushort 59 0 : fd_igmp_check( fd_igmp_t const * igmp ) { 60 0 : uint const * u = igmp->u; 61 0 : ulong c = (ulong)u[0] + (ulong)u[1]; 62 0 : c = ( c>>32 ) + 63 0 : ((c>>16) & 0xffffUL) + 64 0 : ( c & 0xffffUL); 65 0 : c += ( c>>16 ); 66 0 : return (ushort)~c; 67 0 : } 68 : 69 : /* fd_ip4_igmp populates the memory region of size sizeof(fd_ip4_igmp_t) 70 : and whose first byte is pointed to by the non-NULL _msg with a well 71 : formed ip4 / igmp message. The message is addressed as from 72 : ip4_saddr (assumed valid ip4 ucast on subnet) and to ip4_daddr 73 : (assumed valid ip4 mcast). It be an igmp of the given type, with the 74 : given response and to the given igmp_group (usually igmp_group should 75 : be ip4_daddr). Returns _msg. */ 76 : 77 : static inline fd_ip4_igmp_t * 78 : fd_ip4_igmp( void * _msg, 79 : uint ip4_saddr, 80 : uint ip4_daddr, 81 : uchar igmp_type, 82 : uchar igmp_resp, 83 0 : uint igmp_group ) { 84 0 : fd_ip4_igmp_t * msg = (fd_ip4_igmp_t *)_msg; 85 0 : 86 0 : msg->ip4->verihl = FD_IP4_VERIHL(6U,4U); 87 0 : msg->ip4->tos = FD_IP4_HDR_TOS_PREC_INTERNETCONTROL; 88 0 : msg->ip4->net_tot_len = fd_ushort_bswap( (ushort)32 ); 89 0 : msg->ip4->net_id = (ushort)0; 90 0 : msg->ip4->net_frag_off = fd_ushort_bswap( FD_IP4_HDR_FRAG_OFF_DF ); 91 0 : msg->ip4->ttl = (uchar)1; 92 0 : msg->ip4->protocol = FD_IP4_HDR_PROTOCOL_IGMP; 93 0 : msg->ip4->check = (ushort)0; /* Computation completed below */ 94 0 : 95 0 : memcpy( msg->ip4->saddr_c, &ip4_saddr, 4U ); 96 0 : memcpy( msg->ip4->daddr_c, &ip4_daddr, 4U ); 97 0 : 98 0 : msg->opt[0] = FD_IP4_OPT_RA; 99 0 : msg->opt[1] = (uchar)4; 100 0 : msg->opt[2] = (uchar)0; 101 0 : msg->opt[3] = (uchar)0; 102 0 : 103 0 : msg->igmp->type = igmp_type; 104 0 : msg->igmp->resp = igmp_resp; 105 0 : msg->igmp->check = (ushort)0; /* Computation completed below */ 106 0 : msg->igmp->group = igmp_group; 107 0 : 108 0 : msg->ip4->check = fd_ip4_hdr_check( msg->ip4 ); 109 0 : msg->igmp->check = fd_igmp_check ( msg->igmp ); 110 0 : 111 0 : return msg; 112 0 : } 113 : 114 : FD_PROTOTYPES_END 115 : 116 : #endif /* HEADER_fd_src_util_net_fd_igmp_h */