⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igmp.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file * IGMP - Internet Group Management Protocol * *//* * Copyright (c) 2002 CITEL Technologies Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors  *    may be used to endorse or promote products derived from this software  *    without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  * ARE DISCLAIMED.  IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  * SUCH DAMAGE.  * * This file is a contribution to the lwIP TCP/IP stack. * The Swedish Institute of Computer Science and Adam Dunkels * are specifically granted permission to redistribute this * source code.*//*-------------------------------------------------------------Note 1)Although the rfc requires V1 AND V2 capabilitywe will only support v2 since now V1 is very old (August 1989)V1 can be added if requireda debug print and statistic have been implemented toshow this up.--------------------------------------------------------------------------------------------------------------------------Note 2)A query for a specific group address (as opposed to ALLHOSTS)has now been implemented as I am unsure if it is requireda debug print and statistic have been implemented toshow this up.--------------------------------------------------------------------------------------------------------------------------Note 3)The router alert rfc 2113 is implemented in outgoing packetsbut not checked rigorously incoming-------------------------------------------------------------Steve Reynolds------------------------------------------------------------*//*----------------------------------------------------------------------------- * RFC 988  - Host extensions for IP multicasting                         - V0 * RFC 1054 - Host extensions for IP multicasting                         - * RFC 1112 - Host extensions for IP multicasting                         - V1 * RFC 2236 - Internet Group Management Protocol, Version 2               - V2  <- this code is based on this RFC (it's the "de facto" standard) * RFC 3376 - Internet Group Management Protocol, Version 3               - V3 * RFC 4604 - Using Internet Group Management Protocol Version 3...       - V3+ * RFC 2113 - IP Router Alert Option                                      -  *----------------------------------------------------------------------------*//*----------------------------------------------------------------------------- * Includes *----------------------------------------------------------------------------*/#include "lwip/opt.h"#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */#include "lwip/igmp.h"#include "lwip/debug.h"#include "lwip/def.h"#include "lwip/mem.h"#include "lwip/ip.h"#include "lwip/inet_chksum.h"#include "lwip/netif.h"#include "lwip/icmp.h"#include "lwip/udp.h"#include "lwip/tcp.h"#include "lwip/stats.h"#include "string.h"/*  * IGMP constants */#define IGMP_TTL                       1#define IGMP_MINLEN                    8#define ROUTER_ALERT                   0x9404U#define ROUTER_ALERTLEN                4/* * IGMP message types, including version number. */#define IGMP_MEMB_QUERY                0x11 /* Membership query         */#define IGMP_V1_MEMB_REPORT            0x12 /* Ver. 1 membership report */#define IGMP_V2_MEMB_REPORT            0x16 /* Ver. 2 membership report */#define IGMP_LEAVE_GROUP               0x17 /* Leave-group message      *//* Group  membership states */#define IGMP_GROUP_NON_MEMBER          0#define IGMP_GROUP_DELAYING_MEMBER     1#define IGMP_GROUP_IDLE_MEMBER         2/** * IGMP packet format. */#ifdef PACK_STRUCT_USE_INCLUDES#  include "arch/bpstruct.h"#endifPACK_STRUCT_BEGINstruct igmp_msg { PACK_STRUCT_FIELD(u8_t           igmp_msgtype); PACK_STRUCT_FIELD(u8_t           igmp_maxresp); PACK_STRUCT_FIELD(u16_t          igmp_checksum); PACK_STRUCT_FIELD(ip_addr_p_t    igmp_group_address);} PACK_STRUCT_STRUCT;PACK_STRUCT_END#ifdef PACK_STRUCT_USE_INCLUDES#  include "arch/epstruct.h"#endifstatic struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);static err_t  igmp_remove_group(struct igmp_group *group);static void   igmp_timeout( struct igmp_group *group);static void   igmp_start_timer(struct igmp_group *group, u8_t max_time);static void   igmp_stop_timer(struct igmp_group *group);static void   igmp_delaying_member(struct igmp_group *group, u8_t maxresp);static err_t  igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);static void   igmp_send(struct igmp_group *group, u8_t type);static struct igmp_group* igmp_group_list;static ip_addr_t     allsystems;static ip_addr_t     allrouters;/** * Initialize the IGMP module */voidigmp_init(void){  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n"));  IP4_ADDR(&allsystems, 224, 0, 0, 1);  IP4_ADDR(&allrouters, 224, 0, 0, 2);}#ifdef LWIP_DEBUG/** * Dump global IGMP groups list */voidigmp_dump_group_list(){   struct igmp_group *group = igmp_group_list;  while (group != NULL) {    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));    ip_addr_debug_print(IGMP_DEBUG, &group->group_address);    LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));    group = group->next;  }  LWIP_DEBUGF(IGMP_DEBUG, ("\n"));}#else#define igmp_dump_group_list()#endif /* LWIP_DEBUG *//** * Start IGMP processing on interface * * @param netif network interface on which start IGMP processing */err_tigmp_start(struct netif *netif){  struct igmp_group* group;  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif));  group = igmp_lookup_group(netif, &allsystems);  if (group != NULL) {    group->group_state = IGMP_GROUP_IDLE_MEMBER;    group->use++;    /* Allow the igmp messages at the MAC level */    if (netif->igmp_mac_filter != NULL) {      LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));      ip_addr_debug_print(IGMP_DEBUG, &allsystems);      LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));      netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);    }    return ERR_OK;  }  return ERR_MEM;}/** * Stop IGMP processing on interface * * @param netif network interface on which stop IGMP processing */err_tigmp_stop(struct netif *netif){  struct igmp_group *group = igmp_group_list;  struct igmp_group *prev  = NULL;  struct igmp_group *next;  /* look for groups joined on this interface further down the list */  while (group != NULL) {    next = group->next;    /* is it a group joined on this interface? */    if (group->netif == netif) {      /* is it the first group of the list? */      if (group == igmp_group_list) {        igmp_group_list = next;      }      /* is there a "previous" group defined? */      if (prev != NULL) {        prev->next = next;      }      /* disable the group at the MAC level */      if (netif->igmp_mac_filter != NULL) {        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));        ip_addr_debug_print(IGMP_DEBUG, &group->group_address);        LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));        netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);      }      /* free group */      memp_free(MEMP_IGMP_GROUP, group);    } else {      /* change the "previous" */      prev = group;    }    /* move to "next" */    group = next;  }  return ERR_OK;}/** * Report IGMP memberships for this interface * * @param netif network interface on which report IGMP memberships */voidigmp_report_groups(struct netif *netif){  struct igmp_group *group = igmp_group_list;  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));  while (group != NULL) {    if (group->netif == netif) {      igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);    }    group = group->next;  }}/** * Search for a group in the global igmp_group_list * * @param ifp the network interface for which to look * @param addr the group ip address to search for * @return a struct igmp_group* if the group has been found, *         NULL if the group wasn't found. */struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr){  struct igmp_group *group = igmp_group_list;  while (group != NULL) {    if ((group->netif == 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 interface for which to look * @param addr the group ip address to search * @return a struct igmp_group*, *         NULL on memory error. */struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr){  struct igmp_group *group = igmp_group_list;    /* Search if the group already exists */  group = igmp_lookfor_group(ifp, addr);  if (group != NULL) {    /* Group already exists. */    return group;  }  /* Group doesn't exist yet, create a new one */  group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);  if (group != NULL) {    group->netif              = ifp;    ip_addr_set(&(group->group_address), addr);    group->timer              = 0; /* Not running */    group->group_state        = IGMP_GROUP_NON_MEMBER;    group->last_reporter_flag = 0;    group->use                = 0;    group->next               = igmp_group_list;        igmp_group_list = group;  }  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));  ip_addr_debug_print(IGMP_DEBUG, addr);  LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));  return group;}/** * Remove a group in the global igmp_group_list * * @param group the group to remove from the global igmp_group_list * @return ERR_OK if group was removed from the list, an err_t otherwise */static err_tigmp_remove_group(struct igmp_group *group){  err_t err = ERR_OK;  /* Is it the first group? */  if (igmp_group_list == group) {    igmp_group_list = group->next;  } else {    /* look for group further down the list */    struct igmp_group *tmpGroup;    for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {      if (tmpGroup->next == group) {        tmpGroup->next = group->next;        break;      }    }    /* Group not found in the global igmp_group_list */    if (tmpGroup == NULL)      err = ERR_ARG;  }  /* free group */  memp_free(MEMP_IGMP_GROUP, group);  return err;}/** * 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 */voidigmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest){  struct ip_hdr *    iphdr;  struct igmp_msg*   igmp;  struct igmp_group* group;  struct igmp_group* groupref;  IGMP_STATS_INC(igmp.recv);  /* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */      iphdr = (struct ip_hdr *)p->payload;  if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {    pbuf_free(p);    IGMP_STATS_INC(igmp.lenerr);    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));    return;  }  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));  ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -