103#define ROUTER_ALERT 0x9404U
104#define ROUTER_ALERTLEN 4
109#define IGMP_MEMB_QUERY 0x11
110#define IGMP_V1_MEMB_REPORT 0x12
111#define IGMP_V2_MEMB_REPORT 0x16
112#define IGMP_LEAVE_GROUP 0x17
115#define IGMP_GROUP_NON_MEMBER 0
116#define IGMP_GROUP_DELAYING_MEMBER 1
117#define IGMP_GROUP_IDLE_MEMBER 2
122#ifdef PACK_STRUCT_USE_INCLUDES
123# include "arch/bpstruct.h"
133#ifdef PACK_STRUCT_USE_INCLUDES
134# include "arch/epstruct.h"
138static struct igmp_group *igmp_lookup_group(
struct netif *ifp,
ip_addr_t *addr);
139static err_t igmp_remove_group(
struct igmp_group *group);
140static void igmp_timeout(
struct igmp_group *group);
141static void igmp_start_timer(
struct igmp_group *group,
u8_t max_time);
142static void igmp_delaying_member(
struct igmp_group *group,
u8_t maxresp);
144static void igmp_send(
struct igmp_group *group,
u8_t type);
147static struct igmp_group* igmp_group_list;
160 IP4_ADDR(&allsystems, 224, 0, 0, 1);
161 IP4_ADDR(&allrouters, 224, 0, 0, 2);
169igmp_dump_group_list()
171 struct igmp_group *group = igmp_group_list;
173 while (group !=
NULL) {
182#define igmp_dump_group_list()
193 struct igmp_group* group;
197 group = igmp_lookup_group(
netif, &allsystems);
200 group->group_state = IGMP_GROUP_IDLE_MEMBER;
208 netif->igmp_mac_filter(
netif, &allsystems, IGMP_ADD_MAC_FILTER);
225 struct igmp_group *group = igmp_group_list;
226 struct igmp_group *prev =
NULL;
227 struct igmp_group *
next;
230 while (group !=
NULL) {
233 if (group->netif ==
netif) {
235 if (group == igmp_group_list) {
236 igmp_group_list =
next;
247 netif->igmp_mac_filter(
netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
269 struct igmp_group *group = igmp_group_list;
273 while (group !=
NULL) {
274 if (group->netif ==
netif) {
275 igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
292 struct igmp_group *group = igmp_group_list;
294 while (group !=
NULL) {
295 if ((group->netif == ifp) && (
ip_addr_cmp(&(group->group_address), addr))) {
318 struct igmp_group *group = igmp_group_list;
321 group = igmp_lookfor_group(ifp, addr);
328 group = (
struct igmp_group *)
memp_malloc(MEMP_IGMP_GROUP);
333 group->group_state = IGMP_GROUP_NON_MEMBER;
334 group->last_reporter_flag = 0;
336 group->next = igmp_group_list;
338 igmp_group_list = group;
341 LWIP_DEBUGF(
IGMP_DEBUG, (
"igmp_lookup_group: %sallocated a new group with address ", (group?
"":
"impossible to ")));
355igmp_remove_group(
struct igmp_group *group)
360 if (igmp_group_list == group) {
361 igmp_group_list = group->next;
364 struct igmp_group *tmpGroup;
365 for (tmpGroup = igmp_group_list; tmpGroup !=
NULL; tmpGroup = tmpGroup->next) {
366 if (tmpGroup->next == group) {
367 tmpGroup->next = group->next;
372 if (tmpGroup ==
NULL)
392 struct igmp_msg* igmp;
393 struct igmp_group* group;
394 struct igmp_group* groupref;
414 igmp = (
struct igmp_msg *)p->
payload;
423 group = igmp_lookfor_group(inp, dest);
434 switch (igmp->igmp_msgtype) {
435 case IGMP_MEMB_QUERY: {
439 LWIP_DEBUGF(
IGMP_DEBUG, (
"igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (
int)(igmp->igmp_maxresp)));
441 if (igmp->igmp_maxresp == 0) {
443 LWIP_DEBUGF(
IGMP_DEBUG, (
"igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
444 igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
449 groupref = igmp_group_list;
452 if ((groupref->netif == inp) && (!(
ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
453 igmp_delaying_member(groupref, igmp->igmp_maxresp);
455 groupref = groupref->next;
464 LWIP_DEBUGF(
IGMP_DEBUG, (
" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (
int)(igmp->igmp_maxresp)));
467 group = igmp_lookfor_group(inp, &groupaddr);
469 LWIP_DEBUGF(
IGMP_DEBUG, (
" with the group address as destination [igmp_maxresp=%i]\n", (
int)(igmp->igmp_maxresp)));
474 igmp_delaying_member(group, igmp->igmp_maxresp);
484 case IGMP_V2_MEMB_REPORT: {
487 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
490 group->group_state = IGMP_GROUP_IDLE_MEMBER;
491 group->last_reporter_flag = 0;
497 igmp->igmp_msgtype, group->group_state, &group, group->netif));
518 struct igmp_group *group;
531 group = igmp_lookup_group(
netif, groupaddr);
535 if (group->group_state != IGMP_GROUP_NON_MEMBER) {
544 if ((group->use==0) && (
netif->igmp_mac_filter !=
NULL)) {
548 netif->igmp_mac_filter(
netif, groupaddr, IGMP_ADD_MAC_FILTER);
552 igmp_send(group, IGMP_V2_MEMB_REPORT);
554 igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
557 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
588 struct igmp_group *group;
601 group = igmp_lookfor_group(
netif, groupaddr);
610 if (group->use <= 1) {
612 if (group->last_reporter_flag) {
615 igmp_send(group, IGMP_LEAVE_GROUP);
623 netif->igmp_mac_filter(
netif, groupaddr, IGMP_DEL_MAC_FILTER);
631 igmp_remove_group(group);
657 struct igmp_group *group = igmp_group_list;
659 while (group !=
NULL) {
660 if (group->timer > 0) {
662 if (group->timer == 0) {
677igmp_timeout(
struct igmp_group *group)
680 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
686 igmp_send(group, IGMP_V2_MEMB_REPORT);
698igmp_start_timer(
struct igmp_group *group,
u8_t max_time)
705 group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
715igmp_delaying_member(
struct igmp_group *group,
u8_t maxresp)
717 if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
718 ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
719 ((group->timer == 0) || (maxresp < group->timer)))) {
720 igmp_start_timer(group, maxresp);
721 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
752 return ip_output_if_opt(p, src, dest, IGMP_TTL, 0,
IP_PROTO_IGMP,
netif, ra, ROUTER_ALERTLEN);
762igmp_send(
struct igmp_group *group,
u8_t type)
765 struct igmp_msg* igmp =
NULL;
773 igmp = (
struct igmp_msg *)p->
payload;
774 LWIP_ASSERT(
"igmp_send: check that first pbuf can hold struct igmp_msg",
775 (p->
len >=
sizeof(
struct igmp_msg)));
778 if (
type == IGMP_V2_MEMB_REPORT) {
779 dest = &(group->group_address);
780 ip_addr_copy(igmp->igmp_group_address, group->group_address);
781 group->last_reporter_flag = 1;
783 if (
type == IGMP_LEAVE_GROUP) {
785 ip_addr_copy(igmp->igmp_group_address, group->group_address);
789 if ((
type == IGMP_V2_MEMB_REPORT) || (
type == IGMP_LEAVE_GROUP)) {
790 igmp->igmp_msgtype =
type;
791 igmp->igmp_maxresp = 0;
792 igmp->igmp_checksum = 0;
793 igmp->igmp_checksum =
inet_chksum(igmp, IGMP_MINLEN);
795 igmp_ip_output_if(p, &src, dest, group->netif);
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_FIELD(x)
#define PACK_STRUCT_STRUCT
#define LWIP_DEBUGF(debug, message)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
u16_t inet_chksum(void *dataptr, u16_t len)
#define ip_addr_cmp(addr1, addr2)
#define ip_addr_isany(addr1)
#define ip_addr_ismulticast(addr1)
#define ip_addr_set(dest, src)
#define IP4_ADDR(ipaddr, a, b, c, d)
#define ip_addr_copy(dest, src)
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
#define ip_addr_debug_print(debug, ipaddr)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
struct netif * netif_list
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
#define IGMP_STATS_INC(x)