From a185e19bc102a0ddf7e7308b6da2ba4afbeb4e57 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Fri, 8 Jun 2007 12:54:40 +0000 Subject: [PATCH] Let lookup_group() call lookfor_group() to reduce code size, done some work on task #1549 (function documentation) and minor changes to meet coding standard --- src/core/ipv4/igmp.c | 709 ++++++++++++++++++++++++------------------- 1 file changed, 395 insertions(+), 314 deletions(-) diff --git a/src/core/ipv4/igmp.c b/src/core/ipv4/igmp.c index 5aca3f03..5a6b85c6 100644 --- a/src/core/ipv4/igmp.c +++ b/src/core/ipv4/igmp.c @@ -87,331 +87,410 @@ Steve Reynolds * Globales *----------------------------------------------------------------------------*/ -struct igmp_group* GroupList; +struct igmp_group* group_list; struct igmp_stats igmpstats; struct ip_addr allsystems; struct ip_addr allrouters; -/*----------------------------------------------------------------------------- - * igmp_init - *----------------------------------------------------------------------------*/ -void igmp_init(void) -{ struct igmp_group* group; +/** + * Initialize this module + * + * Only network interfaces registered when this function is called + * are igmp-enabled. + */ +void +igmp_init(void) +{ + struct igmp_group* group; struct netif* netif; - + LWIP_DEBUGF(IGMP_DEBUG, ("IGMP Initialising\n")); - IP4_ADDR (&allsystems, 224, 0, 0, 1); - IP4_ADDR (&allrouters, 224, 0, 0, 2); - - GroupList = NULL; - memset( &igmpstats, 0, sizeof(igmpstats)); - - for( netif = netif_list; netif != NULL; netif = netif->next) - { group = lookup_group (netif, &allsystems); + IP4_ADDR(&allsystems, 224, 0, 0, 1); + IP4_ADDR(&allrouters, 224, 0, 0, 2); + + group_list = NULL; + memset(&igmpstats, 0, sizeof(igmpstats)); + + for (netif = netif_list; netif != NULL; netif = netif->next) { + group = lookup_group(netif, &allsystems); - if (group) - { group->group_state = IDLE_MEMBER; - - /* Allow the igmp messages at the MAC level */ - if (netif->igmp_mac_filter!=NULL) - { netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER); - netif->igmp_mac_filter( netif, &allrouters, IGMP_ADD_MAC_FILTER); - } + if (group) { + group->group_state = IDLE_MEMBER; + + /* Allow the igmp messages at the MAC level */ + if (netif->igmp_mac_filter != NULL) { + netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER); + netif->igmp_mac_filter(netif, &allrouters, IGMP_ADD_MAC_FILTER); } - } + } + } } -/*----------------------------------------------------------------------------- - * lookfor_group - *----------------------------------------------------------------------------*/ -struct igmp_group * lookfor_group( struct netif *ifp, struct ip_addr *addr) -{ struct igmp_group *group = GroupList; +/** + * Search for a group in the global group_list + * + * @param ifp the network interfacefor which to look + * @param addr the group ip address to search + * @return a struct igmp_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct igmp_group * +lookfor_group(struct netif *ifp, struct ip_addr *addr) +{ + struct igmp_group *group = group_list; + + while (group) { + if ((group->interface == ifp) && (ip_addr_cmp(&(group->group_address), addr))) { + return group; + } + group = group->next; + } + + /* to be clearer, we return NULL here instead of + * 'group' (which is also NULL at this point). + */ + return NULL; +} + +/** + * Search for a specific igmp group and create a new one if not found- + * + * @param ifp the network interfacefor which to look + * @param addr the group ip address to search + * @return a struct igmp_group*, + * NULL on memory error. + */ +struct igmp_group * +lookup_group(struct netif *ifp, struct ip_addr *addr) +{ + struct igmp_group *group = group_list; - while (group) - { if ((group->interface == ifp) && (ip_addr_cmp (&(group->group_address), addr))) - { return group; - } - group = group->next; - } - + /* Search if the group already exists */ + group = lookfor_group(ifp, addr); + if (group != NULL) { + /* Group already exists. */ + return group; + } + + /* Group doesn't exist yet, create a new one. */ + group = mem_malloc(sizeof(struct igmp_group)); + if (group) { + group->interface = ifp; + ip_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = NON_MEMBER; + group->last_reporter_flag = 0; + group->next = group_list; + + group_list = group; + + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d allocated a new group with address %x on if %x \n", __LINE__, (int) addr, (int) ifp)); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d impossible to allocated a new group with address %x on if %x \n", __LINE__, (int) addr, (int) ifp)); + } + return group; } -/*----------------------------------------------------------------------------- - * lookup_group - *----------------------------------------------------------------------------*/ -struct igmp_group * lookup_group( struct netif *ifp, struct ip_addr *addr) -{ struct igmp_group *group = GroupList; - - while (group) - { if ((group->interface == ifp) && (ip_addr_cmp (&(group->group_address), addr))) - { return group; - } - group = group->next; - } - - group = mem_malloc (sizeof (struct igmp_group)); - - if (group) - { group->interface = ifp; - ip_addr_set (&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = NON_MEMBER; - group->last_reporter_flag = 0; - group->next = GroupList; - - GroupList = group; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d allocated a new group with address %x on if %x \n", __LINE__, (int) addr, (int) ifp)); - } - else - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d impossible to allocated a new group with address %x on if %x \n", __LINE__, (int) addr, (int) ifp)); - } - - return group; -} - -/*----------------------------------------------------------------------------- - * igmp_input - *----------------------------------------------------------------------------*/ -void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest) -{ struct ip_hdr * iphdr; +/** + * Called from ip_input() if a new IGMP packet is received. + * + * @param p received igmp packet, p->payload pointing to the ip header + * @param inp network interface on which the packet was received + * @param dest destination ip address of the igmp packet + */ +void +igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest) +{ + struct ip_hdr * iphdr; struct igmpmsg* igmp; struct igmp_group* group; struct igmp_group* groupref; - + iphdr = p->payload; igmp = (struct igmpmsg *)(((u8_t *)p->payload)+((u32_t)(IPH_HL(iphdr) * 4))); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp message to address %l \n", (long) dest->addr)); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp message to address %l \n", (long)dest->addr)); - if (p->len < IGMP_MINLEN) - { /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ - pbuf_free (p); - igmpstats.igmp_length_err++; - LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x igmp length error\n", __LINE__)); - return; - } + if (p->len < IGMP_MINLEN) { + /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */ + pbuf_free(p); + igmpstats.igmp_length_err++; + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x igmp length error\n", __LINE__)); + return; + } /* Now calculate and check the checksum */ - if (inet_chksum (igmp, IGMP_MINLEN /*p->len*/)) - { pbuf_free (p); - igmpstats.igmp_checksum_err++; - LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d igmp checksum error\n", __LINE__)); - return; - } + if (inet_chksum(igmp, IGMP_MINLEN /*p->len*/)) { + pbuf_free(p); + igmpstats.igmp_checksum_err++; + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d igmp checksum error\n", __LINE__)); + return; + } /* Packet is ok so find the group (or create a new one) */ - group = lookup_group (inp, dest); /* use the incoming IP address! */ + group = lookup_group(inp, dest); /* use the incoming IP address! */ /* If group can be found or create... */ - if (!group) - { pbuf_free (p); - LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d igmp allocation error\n", __LINE__)); - return; - } + if (!group) { + pbuf_free(p); + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d igmp allocation error\n", __LINE__)); + return; + } /* NOW ACT ON THE INCOMING MESSAGE TYPE... */ /* The membership query message goes to the all groups address */ /* and it control block does not have state */ - if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && (ip_addr_cmp (dest, &allsystems)) && (igmp->igmp_group_address.addr == 0)) - { /* THIS IS THE GENERAL QUERY */ - LWIP_DEBUGF(IGMP_DEBUG, ("General IGMP_MEMB_QUERY on ALL SYSTEMS ADDRESS 224.0.0.1\n")); + if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && (ip_addr_cmp(dest, &allsystems)) && + (igmp->igmp_group_address.addr == 0)) { + /* THIS IS THE GENERAL QUERY */ + LWIP_DEBUGF(IGMP_DEBUG, ("General IGMP_MEMB_QUERY on ALL SYSTEMS ADDRESS 224.0.0.1\n")); - if (0 ==igmp->igmp_maxresp ) - { igmpstats.igmp_v1_rxed++; - igmp->igmp_maxresp = 10; - LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n", __LINE__)); - } + if (0 ==igmp->igmp_maxresp) { + igmpstats.igmp_v1_rxed++; + igmp->igmp_maxresp = 10; + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %d got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n", __LINE__)); + } - igmpstats.igmp_group_query_rxed++; - groupref = GroupList; - while (groupref) - { if ((groupref->interface == inp) && (!(ip_addr_cmp (&(groupref->group_address), &allsystems)))) - { /* Do not send messages on the all systems group address! */ - if ((groupref->group_state == IDLE_MEMBER) || ((groupref->group_state == DELAYING_MEMBER) && (igmp->igmp_maxresp > groupref->timer))) - { igmp_start_timer (groupref, (igmp->igmp_maxresp)/2); - groupref->group_state = DELAYING_MEMBER; - } - } - groupref = groupref->next; + igmpstats.igmp_group_query_rxed++; + groupref = group_list; + while (groupref) { + if ((groupref->interface == inp) && + (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) { + /* Do not send messages on the all systems group address! */ + if ((groupref->group_state == IDLE_MEMBER) || + ((groupref->group_state == DELAYING_MEMBER) && + (igmp->igmp_maxresp > groupref->timer))) { + igmp_start_timer(groupref, (igmp->igmp_maxresp)/2); + groupref->group_state = DELAYING_MEMBER; + } } - } - else - if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && ip_addr_cmp (dest, &allsystems) && (group->group_address.addr != 0)) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got a query to a specific group using the allsystems address \n", __LINE__)); + groupref = groupref->next; + } + } else { + if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && ip_addr_cmp (dest, &allsystems) && + (group->group_address.addr != 0)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got a query to a specific group using the allsystems address \n", __LINE__)); - /* we first need to re-lookup the group since we used dest last time */ - group = lookup_group (inp, &igmp->igmp_group_address); /* use the incoming IP address! */ - igmpstats.igmp_unicast_query++; + /* we first need to re-lookup the group since we used dest last time */ + group = lookup_group(inp, &igmp->igmp_group_address); /* use the incoming IP address! */ + igmpstats.igmp_unicast_query++; - if ((IDLE_MEMBER == group->group_state ) || ((DELAYING_MEMBER == group->group_state ) && (igmp->igmp_maxresp > group->timer))) - { igmp_start_timer (group, (igmp->igmp_maxresp)/2); + if ((IDLE_MEMBER == group->group_state ) || ((DELAYING_MEMBER == group->group_state) && + (igmp->igmp_maxresp > group->timer))) { + igmp_start_timer(group, (igmp->igmp_maxresp)/2); group->group_state = DELAYING_MEMBER; } - } - else - if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && !(ip_addr_cmp (dest, &allsystems)) && (group->group_address.addr != 0)) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got a query to a specific group with the group address as destination \n", __LINE__)); + } else { + if ((IGMP_MEMB_QUERY == igmp->igmp_msgtype) && !(ip_addr_cmp (dest, &allsystems)) && + (group->group_address.addr != 0)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got a query to a specific group with the group address as destination \n", __LINE__)); - igmpstats.igmp_unicast_query++; /* This is the unicast query */ - if ((IDLE_MEMBER == group->group_state ) || ((DELAYING_MEMBER == group->group_state ) && (igmp->igmp_maxresp > group->timer))) - { igmp_start_timer (group, (igmp->igmp_maxresp)/2); - group->group_state = DELAYING_MEMBER; + igmpstats.igmp_unicast_query++; /* This is the unicast query */ + if ((IDLE_MEMBER == group->group_state) || ((DELAYING_MEMBER == group->group_state) && + (igmp->igmp_maxresp > group->timer))) { + igmp_start_timer(group, (igmp->igmp_maxresp)/2); + group->group_state = DELAYING_MEMBER; + } + } else { + if (IGMP_V2_MEMB_REPORT == igmp->igmp_msgtype) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got an IGMP_V2_MEMB_REPORT \n", __LINE__)); + + igmpstats.report_rxed++; + if (DELAYING_MEMBER == group->group_state) { + /* This is on a specific group we have already looked up */ + group->timer = 0; /* stopped */ + group->group_state = IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input, Line %x unexpected msg %x in state %x on group %x at interface %x\n", __LINE__, (int) igmp->igmp_msgtype, (int) group->group_state, (int) &group, (int) group->interface)); + } } - } - else - if (IGMP_V2_MEMB_REPORT == igmp->igmp_msgtype ) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c,Line %x got an IGMP_V2_MEMB_REPORT \n", __LINE__)); - - igmpstats.report_rxed++; - if (DELAYING_MEMBER == group->group_state ) - { /* This is on a specific group we have already looked up */ - group->timer = 0; /* stopped */ - group->group_state = IDLE_MEMBER; - group->last_reporter_flag = 0; - } - } - else - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input, Line %x unexpected msg %x in state %x on group %x at interface %x\n", __LINE__, (int) igmp->igmp_msgtype, (int) group->group_state, (int) &group, (int) group->interface)); - } - - pbuf_free (p); + } + } + pbuf_free(p); return; } -/*----------------------------------------------------------------------------- - * igmp_joingroup - *----------------------------------------------------------------------------*/ -err_t igmp_joingroup( struct netif *ifp, struct ip_addr *groupaddr) -{ struct igmp_group *group; - - group = lookup_group (ifp, groupaddr); +/** + * Join a group on one network interface. + * + * @param ifp the network interface which should join a new group + * @param groupaddr the ip address of the group which to join + * @return ERR_OK if group was joined, an err_t otherwise + */ +err_t +igmp_joingroup(struct netif *ifp, struct ip_addr *groupaddr) +{ + struct igmp_group *group; - if (group) - { /* This should create a new group, check the state to make sure */ - if (group->group_state != NON_MEMBER) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c Line %x join to group not in state NON_MEMBER\n", __LINE__)); - return ERR_OK; - } + group = lookup_group(ifp, groupaddr); - /* OK - it was new group */ - igmpstats.igmp_joins++; - - LWIP_DEBUGF(IGMP_DEBUG, ("igmp join to new group\n")); - - if (ifp->igmp_mac_filter!=NULL) - { ifp->igmp_mac_filter( ifp, groupaddr, IGMP_ADD_MAC_FILTER); - } - - igmp_send( group, IGMP_V2_MEMB_REPORT); - - igmp_start_timer( group, 5); - - /* Need to work out where this timer comes from */ - group->group_state = DELAYING_MEMBER; - - return ERR_OK; - } - - return ERR_MEM; -} + if (group) { + /* This should create a new group, check the state to make sure */ + if (group->group_state != NON_MEMBER) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c Line %x join to group not in state NON_MEMBER\n", __LINE__)); + return ERR_OK; + } -/*----------------------------------------------------------------------------- - * igmp_leavegroup - *----------------------------------------------------------------------------*/ -err_t igmp_leavegroup( struct netif *ifp, struct ip_addr *groupaddr) -{ struct igmp_group *group; - - group = lookup_group (ifp, groupaddr); + /* OK - it was new group */ + igmpstats.igmp_joins++; - if (group) - { /* Only send a leave if the flag is set according to the state diagram */ - if (group->last_reporter_flag) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c Line %x Leaving group\n", __LINE__)); - igmpstats.igmp_leave_sent++; - igmp_send( group, IGMP_LEAVE_GROUP); - } - - /* The block is not deleted since the group still exists and we may rejoin */ - group->last_reporter_flag = 0; - group->group_state = NON_MEMBER; - group->timer = 0; - - if (ifp->igmp_mac_filter!=NULL) - { ifp->igmp_mac_filter( ifp, groupaddr, IGMP_DEL_MAC_FILTER); - } - - return ERR_OK; - } + LWIP_DEBUGF(IGMP_DEBUG, ("igmp join to new group\n")); + + if (ifp->igmp_mac_filter != NULL) { + ifp->igmp_mac_filter(ifp, groupaddr, IGMP_ADD_MAC_FILTER); + } + + igmp_send(group, IGMP_V2_MEMB_REPORT); + + igmp_start_timer(group, 5); + + /* Need to work out where this timer comes from */ + group->group_state = DELAYING_MEMBER; + + return ERR_OK; + } return ERR_MEM; } -/*----------------------------------------------------------------------------- - * igmp_tmr - *----------------------------------------------------------------------------*/ -void igmp_tmr() -{ struct igmp_group *group = GroupList; +/** + * Leave a group on one network interface. + * + * @param ifp the network interface which should leave a group + * @param groupaddr the ip address of the group which to leave + * @return ERR_OK if group was left, an err_t otherwise + */ +err_t +igmp_leavegroup(struct netif *ifp, struct ip_addr *groupaddr) +{ + struct igmp_group *group; - while (group) - { if (group->timer != 0) - { group->timer -=1; - if (group->timer == 0) - { igmp_timeout (group); - } - } - group = group->next; - } + group = lookup_group(ifp, groupaddr); + + if (group) { + /* Only send a leave if the flag is set according to the state diagram */ + if (group->last_reporter_flag) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c Line %x Leaving group\n", __LINE__)); + igmpstats.igmp_leave_sent++; + igmp_send(group, IGMP_LEAVE_GROUP); + } + + /* The block is not deleted since the group still exists and we may rejoin */ + group->last_reporter_flag = 0; + group->group_state = NON_MEMBER; + group->timer = 0; + + if (ifp->igmp_mac_filter != NULL) { + ifp->igmp_mac_filter(ifp, groupaddr, IGMP_DEL_MAC_FILTER); + } + + return ERR_OK; + } + + return ERR_MEM; } -/*----------------------------------------------------------------------------- - * igmp_timeout - *----------------------------------------------------------------------------*/ -void igmp_timeout( struct igmp_group *group) -{ /* If the state is DELAYING_MEMBER then we send a report for this group */ +/** + * The igmp timer function (both for NO_SYS=1 and =0) + * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). + */ +void +igmp_tmr() +{ + struct igmp_group *group = group_list; + + while (group) { + if (group->timer != 0) { + group->timer -= 1; + if (group->timer == 0) { + igmp_timeout(group); + } + } + group = group->next; + } +} + +/** + * Called if a timeout for one group is reached. + * Sends a report for this group. + * + * @param group an igmp_group for which a timeout is reached + */ +void +igmp_timeout(struct igmp_group *group) +{ + /* If the state is DELAYING_MEMBER then we send a report for this group */ LWIP_DEBUGF(IGMP_DEBUG, ("igmp.c, got a timeout\n")); - if (DELAYING_MEMBER == group->group_state) - { igmp_send( group, IGMP_V2_MEMB_REPORT); - } + if (DELAYING_MEMBER == group->group_state) { + igmp_send(group, IGMP_V2_MEMB_REPORT); + } } -/*----------------------------------------------------------------------------- - * igmp_start_timer - *----------------------------------------------------------------------------*/ -void igmp_start_timer( struct igmp_group *group, u8_t max_time) -{ /* Important !! this should be random 0 -> max_time */ - /* find out how to do this */ +/** + * Start a timer for an igmp group + * + * @param group the igmp_group for which to start a timer + * @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with + * every call to igmp_tmr()) + */ +void +igmp_start_timer(struct igmp_group *group, u8_t max_time) +{ + /* Important !! this should be random 0 -> max_time + * find out how to do this + */ group->timer = max_time; } -/*----------------------------------------------------------------------------- - * igmp_stop_timer - *----------------------------------------------------------------------------*/ -void igmp_stop_timer( struct igmp_group *group) -{ group->timer = 0; +/** + * Stop a timer for an igmp_group + * + * @param group the igmp_group for which to stop the timer + */ +void +igmp_stop_timer(struct igmp_group *group) +{ + group->timer = 0; } -/*----------------------------------------------------------------------------- - * igmp_ip_output_if +/** * Sends an IP packet on a network interface. This function constructs the IP header * and calculates the IP header checksum. If the source IP address is NULL, * the IP address of the outgoing network interface is filled in as source address. - *----------------------------------------------------------------------------*/ -err_t igmp_ip_output_if( struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto, struct netif *netif) -{ static struct ip_hdr * iphdr = NULL; + * + * @param p the packet to send (p->payload points to the data, e.g. next + protocol header; if dest == IP_HDRINCL, p already includes an IP + header and p->payload points to that IP header) + * @param src the source IP address to send from (if src == IP_ADDR_ANY, the + * IP address of the netif used to send is used as source address) + * @param dest the destination IP address to send the packet to + * @param ttl the TTL value to be set in the IP header + * @param proto the PROTOCOL to be set in the IP header + * @param netif the netif on which to send this packet + * @return ERR_OK if the packet was sent OK + * ERR_BUF if p doesn't have enough space for IP/LINK headers + * returns errors returned by netif->output + */ +err_t +igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, + u8_t ttl, u8_t proto, struct netif *netif) +{ + static struct ip_hdr * iphdr = NULL; static u16_t ip_id = 0; u16_t * ra = NULL; /* First write in the "router alert" */ - if (pbuf_header (p, ROUTER_ALERTLEN)) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n")); - return ERR_BUF; - } + if (pbuf_header(p, ROUTER_ALERTLEN)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n")); + return ERR_BUF; + } /* This is the "router alert" option */ ra = p->payload; @@ -419,95 +498,97 @@ err_t igmp_ip_output_if( struct pbuf *p, struct ip_addr *src, struct ip_addr *de ra[1] = 0x0000; /* now the normal ip header */ - if (pbuf_header (p, IP_HLEN)) - { LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n")); - return ERR_BUF; - } + if (pbuf_header(p, IP_HLEN)) { + LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: not enough room for IP header in pbuf\n")); + return ERR_BUF; + } iphdr = p->payload; - if (dest != IP_HDRINCL) - { iphdr->_ttl_proto = (proto<<8); - iphdr->_ttl_proto |= ttl; + if (dest != IP_HDRINCL) { + iphdr->_ttl_proto = (proto<<8); + iphdr->_ttl_proto |= ttl; - /* iphdr->dest = dest->addr; */ - ip_addr_set (&(iphdr->dest), dest); + /* iphdr->dest = dest->addr; */ + ip_addr_set(&(iphdr->dest), dest); #ifdef HAVE_BITFIELDS - iphdr->_v_hl_tos |= ((IP_HLEN+ ROUTER_ALERTLEN)/4)<<16; - iphdr->_v_hl_tos |= 4<<24; + iphdr->_v_hl_tos |= ((IP_HLEN+ ROUTER_ALERTLEN)/4)<<16; + iphdr->_v_hl_tos |= 4<<24; #else - iphdr->_v_hl_tos = (4 << 4) | ((IP_HLEN + ROUTER_ALERTLEN)/ 4 & 0xf); + iphdr->_v_hl_tos = (4 << 4) | ((IP_HLEN + ROUTER_ALERTLEN)/ 4 & 0xf); #endif /* HAVE_BITFIELDS */ - iphdr->_v_hl_tos |= 0; - iphdr->_len = htons (p->tot_len); - iphdr->_offset = htons (0); - iphdr->_id = htons (ip_id++); + iphdr->_v_hl_tos |= 0; + iphdr->_len = htons(p->tot_len); + iphdr->_offset = htons(0); + iphdr->_id = htons(ip_id++); - if (ip_addr_isany (src)) - { ip_addr_set (&(iphdr->src), &(netif->ip_addr)); - } - else - { ip_addr_set (&(iphdr->src), src); - } + if (ip_addr_isany(src)) { + ip_addr_set(&(iphdr->src), &(netif->ip_addr)); + } else { + ip_addr_set(&(iphdr->src), src); + } - iphdr->_chksum = 0; - iphdr->_chksum = inet_chksum (iphdr, IP_HLEN + ROUTER_ALERTLEN); - } - else - { dest = &(iphdr->dest); - } + iphdr->_chksum = 0; + iphdr->_chksum = inet_chksum(iphdr, IP_HLEN + ROUTER_ALERTLEN); + } else { + dest = &(iphdr->dest); + } #if IP_DEBUG - ip_debug_print (p); + ip_debug_print(p); #endif LWIP_DEBUGF(IGMP_DEBUG, ("IGMP sending to netif %x \n", (int) netif)); - return netif->output (netif, p, dest); + return netif->output(netif, p, dest); } -/*----------------------------------------------------------------------------- - * igmp_send - *----------------------------------------------------------------------------*/ -void igmp_send( struct igmp_group *group, u8_t type) -{ struct pbuf* p = NULL; +/** + * Send an igmp packet to a specific group. + * + * @param the group to which to send the packet + * @param type the type of igmp packet to send + */ +void +igmp_send(struct igmp_group *group, u8_t type) +{ + struct pbuf* p = NULL; struct igmpmsg* igmp = NULL; struct ip_addr src = {0}; struct ip_addr* dest = NULL; /* IP header + IGMP header */ - p = pbuf_alloc( PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); + p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM); - if (p) - { igmp = p->payload; - ip_addr_set (&src, &((group->interface)->ip_addr)); + if (p) { + igmp = p->payload; + ip_addr_set(&src, &((group->interface)->ip_addr)); - if (IGMP_V2_MEMB_REPORT == type) - { dest = &(group->group_address); - igmpstats.report_sent++; - ip_addr_set (&(igmp->igmp_group_address), &(group->group_address)); - group->last_reporter_flag = 1; /* Remember we were the last to report */ - } - else - if (IGMP_LEAVE_GROUP == type) - { dest = &allrouters; - ip_addr_set (&(igmp->igmp_group_address), &(group->group_address)); + if (IGMP_V2_MEMB_REPORT == type) { + dest = &(group->group_address); + igmpstats.report_sent++; + ip_addr_set(&(igmp->igmp_group_address), &(group->group_address)); + group->last_reporter_flag = 1; /* Remember we were the last to report */ + } else { + if (IGMP_LEAVE_GROUP == type) { + dest = &allrouters; + ip_addr_set(&(igmp->igmp_group_address), &(group->group_address)); } + } - if ((IGMP_V2_MEMB_REPORT == type) || (IGMP_LEAVE_GROUP == type)) - { igmp->igmp_msgtype = type; - igmp->igmp_maxresp = 0; - igmp->igmp_checksum = 0; - igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN); - - igmp_ip_output_if( p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface); - } - - pbuf_free (p); - } - else - { LWIP_DEBUGF(IGMP_DEBUG, ("IGMP, not enough memory for igmp_send\n")); + if ((IGMP_V2_MEMB_REPORT == type) || (IGMP_LEAVE_GROUP == type)) { + igmp->igmp_msgtype = type; + igmp->igmp_maxresp = 0; + igmp->igmp_checksum = 0; + igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN); + + igmp_ip_output_if( p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface); } + + pbuf_free (p); + } else { + LWIP_DEBUGF(IGMP_DEBUG, ("IGMP, not enough memory for igmp_send\n")); + } } #endif /* LWIP_IGMP */