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

📄 igmp.c

📁 最新的lwip 1.3.0版本在ucos平台上的移植
💻 C
📖 第 1 页 / 共 2 页
字号:
         groupref = groupref->next;       }     } else {       /* IGMP_MEMB_QUERY to a specific group ? */       if (group->group_address.addr != 0) {         LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));         ip_addr_debug_print(IGMP_DEBUG, &group->group_address);         if (ip_addr_cmp (dest, &allsystems)) {           LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));           /* we first need to re-lookfor the group since we used dest last time */           group = igmp_lookfor_group(inp, &igmp->igmp_group_address);         } else {           LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));         }         if (group != NULL) {           IGMP_STATS_INC(igmp.unicast_query);           igmp_delaying_member( group, igmp->igmp_maxresp);         }       }     }     break;   }   case IGMP_V2_MEMB_REPORT: {     LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));     IGMP_STATS_INC(igmp.report_rxed);     if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {       /* This is on a specific group we have already looked up */       group->timer = 0; /* stopped */       group->group_state = IGMP_GROUP_IDLE_MEMBER;       group->last_reporter_flag = 0;     }     break;   }   default: {     LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %x in state %x on group %x on if %x\n", (int) igmp->igmp_msgtype, (int) group->group_state, (int) &group, (int) group->interface));     break;   }  }  pbuf_free(p);  return;}/** * Join a group on one network interface. * * @param ifaddr ip address of 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 on the netif(s), an err_t otherwise */err_tigmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr){  err_t              err = ERR_VAL; /* no matching interface */  struct igmp_group *group;  struct netif      *netif;  /* make sure it is multicast address */  LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);  LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);  /* loop through netif's */  netif = netif_list;  while (netif != NULL) {    /* Should we join this interface ? */    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {      /* find group or create a new one if not found */      group = igmp_lookup_group(netif, groupaddr);      if (group != NULL) {        /* This should create a new group, check the state to make sure */        if (group->group_state != IGMP_GROUP_NON_MEMBER) {          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n"));        } else {          /* OK - it was new group */          LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));          ip_addr_debug_print(IGMP_DEBUG, groupaddr);          LWIP_DEBUGF(IGMP_DEBUG, ("\n"));          /* If first use of the group, allow the group at the MAC level */          if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));            ip_addr_debug_print(IGMP_DEBUG, groupaddr);            LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));            netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);          }          IGMP_STATS_INC(igmp.join_sent);          igmp_send(group, IGMP_V2_MEMB_REPORT);          igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);          /* Need to work out where this timer comes from */          group->group_state = IGMP_GROUP_DELAYING_MEMBER;        }        /* Increment group use */        group->use++;        /* Join on this interface */        err = ERR_OK;      } else {        /* Return an error even if some network interfaces are joined */        /** @todo undo any other netif already joined */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n"));        return ERR_MEM;      }    }    /* proceed to next network interface */    netif = netif->next;  }  return err;}/** * Leave a group on one network interface. * * @param ifaddr ip address of 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 on the netif(s), an err_t otherwise */err_tigmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr){  err_t              err = ERR_VAL; /* no matching interface */  struct igmp_group *group;  struct netif      *netif;  /* make sure it is multicast address */  LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);  LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);  /* loop through netif's */  netif = netif_list;  while (netif != NULL) {    /* Should we leave this interface ? */    if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {      /* find group */      group = igmp_lookfor_group(netif, groupaddr);      if (group != NULL) {        /* Only send a leave if the flag is set according to the state diagram */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));        ip_addr_debug_print(IGMP_DEBUG, groupaddr);        LWIP_DEBUGF(IGMP_DEBUG, ("\n"));        /* If there is no other use of the group */        if (group->use <= 1) {          /* If we are the last reporter for this group */          if (group->last_reporter_flag) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));            IGMP_STATS_INC(igmp.leave_sent);            igmp_send(group, IGMP_LEAVE_GROUP);          }                    /* Disable the group at the MAC level */          if (netif->igmp_mac_filter != NULL) {            LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));            ip_addr_debug_print(IGMP_DEBUG, groupaddr);            LWIP_DEBUGF(IGMP_DEBUG, (") on if %x\n", (int) netif));            netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);          }                    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: "));          ip_addr_debug_print(IGMP_DEBUG, groupaddr);          LWIP_DEBUGF(IGMP_DEBUG, ("\n"));                              /* Free the group */          igmp_remove_group(group);        } else {          /* Decrement group use */          group->use--;        }        /* Leave on this interface */        err = ERR_OK;      } else {        /* It's not a fatal error on "leavegroup" */        LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));      }    }    /* proceed to next network interface */    netif = netif->next;  }  return err;}/** * The igmp timer function (both for NO_SYS=1 and =0) * Should be called every IGMP_TMR_INTERVAL milliseconds (100 ms is default). */voidigmp_tmr(void){  struct igmp_group *group = igmp_group_list;  while (group != NULL) {    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 */voidigmp_timeout(struct igmp_group *group){  /* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */  if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {    LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));    ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));    LWIP_DEBUGF(IGMP_DEBUG, (" on if %x\n", (int) group->interface));    igmp_send(group, IGMP_V2_MEMB_REPORT);  }}/** * 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()) */voidigmp_start_timer(struct igmp_group *group, u8_t max_time){  /**   * @todo Important !! this should be random 0 -> max_time. Find out how to do this   */  group->timer = max_time;}/** * Stop a timer for an igmp_group * * @param group the igmp_group for which to stop the timer */voidigmp_stop_timer(struct igmp_group *group){  group->timer = 0;}/** * Delaying membership report for a group if necessary * * @param group the igmp_group for which "delaying" membership report * @param maxresp query delay */voidigmp_delaying_member( struct igmp_group *group, u8_t maxresp){  if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) || ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {    igmp_start_timer(group, (maxresp)/2);    group->group_state = IGMP_GROUP_DELAYING_MEMBER;  }}/** * 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. * * @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_tigmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,                  u8_t ttl, u8_t proto, struct netif *netif){  static u16_t    ip_id = 0;  struct ip_hdr * iphdr = NULL;  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;  }  /* This is the "router alert" option */  ra    = p->payload;  ra[0] = htons (ROUTER_ALERT);  ra[1] = 0x0000; /* Router shall examine packet */  /* 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;  }  iphdr = p->payload;  /* Should the IP header be generated or is it already included in p? */  if (dest != IP_HDRINCL) {    /** @todo should be shared with ip.c - ip_output_if */    IPH_TTL_SET(iphdr, ttl);    IPH_PROTO_SET(iphdr, proto);    ip_addr_set(&(iphdr->dest), dest);    IPH_VHLTOS_SET(iphdr, 4, ((IP_HLEN + ROUTER_ALERTLEN) / 4), 0/*tos*/);    IPH_LEN_SET(iphdr, htons(p->tot_len));    IPH_OFFSET_SET(iphdr, 0);    IPH_ID_SET(iphdr, htons(ip_id));    ++ip_id;    if (ip_addr_isany(src)) {      ip_addr_set(&(iphdr->src), &(netif->ip_addr));    } else {      ip_addr_set(&(iphdr->src), src);    }    IPH_CHKSUM_SET(iphdr, 0);#if CHECKSUM_GEN_IP    IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, (IP_HLEN + ROUTER_ALERTLEN)));#endif  } else {    dest = &(iphdr->dest);  }#if IP_DEBUG  ip_debug_print(p);#endif  LWIP_DEBUGF(IGMP_DEBUG, ("igmp_ip_output_if: sending to if %x\n", (int) netif));  return netif->output(netif, p, dest);}/** * Send an igmp packet to a specific group. * * @param group the group to which to send the packet * @param type the type of igmp packet to send */voidigmp_send(struct igmp_group *group, u8_t type){  struct pbuf*     p    = NULL;  struct igmp_msg* igmp = NULL;  struct ip_addr   src  = {0};  struct ip_addr*  dest = NULL;  /* IP header + "router alert" option + IGMP header */  p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);    if (p) {    igmp = p->payload;    LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",               (p->len >= sizeof(struct igmp_msg)));    ip_addr_set(&src, &((group->interface)->ip_addr));         if (type == IGMP_V2_MEMB_REPORT) {      dest = &(group->group_address);      IGMP_STATS_INC(igmp.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 (type == IGMP_LEAVE_GROUP) {        dest = &allrouters;        ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));      }    }    if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {      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_send: not enough memory for igmp_send\n"));  }}#endif /* LWIP_IGMP */

⌨️ 快捷键说明

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