106 #define IGMP_MINLEN 8 107 #define ROUTER_ALERT 0x9404 108 #define ROUTER_ALERTLEN 4 113 #define IGMP_MEMB_QUERY 0x11 114 #define IGMP_V1_MEMB_REPORT 0x12 115 #define IGMP_V2_MEMB_REPORT 0x16 116 #define IGMP_LEAVE_GROUP 0x17 119 #define IGMP_GROUP_NON_MEMBER 0 120 #define IGMP_GROUP_DELAYING_MEMBER 1 121 #define IGMP_GROUP_IDLE_MEMBER 2 126 #ifdef PACK_STRUCT_USE_INCLUDES 127 # include "arch/bpstruct.h" 137 #ifdef PACK_STRUCT_USE_INCLUDES 138 # include "arch/epstruct.h" 152 static struct igmp_group* igmp_group_list;
165 IP4_ADDR(&allsystems, 224, 0, 0, 1);
166 IP4_ADDR(&allrouters, 224, 0, 0, 2);
174 igmp_dump_group_list()
176 struct igmp_group *group = igmp_group_list;
178 while (group !=
NULL) {
187 #define igmp_dump_group_list() 198 struct igmp_group* group;
202 group = igmp_lookup_group(netif, &allsystems);
205 group->group_state = IGMP_GROUP_IDLE_MEMBER;
209 if (netif->igmp_mac_filter !=
NULL) {
213 netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);
228 igmp_stop(
struct netif *netif)
230 struct igmp_group *group = igmp_group_list;
231 struct igmp_group *prev =
NULL;
232 struct igmp_group *next;
235 while (group !=
NULL) {
238 if (group->netif == netif) {
240 if (group == igmp_group_list) {
241 igmp_group_list = next;
248 if (netif->igmp_mac_filter !=
NULL) {
252 netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
272 igmp_report_groups(
struct netif *netif)
274 struct igmp_group *group = igmp_group_list;
278 while (group !=
NULL) {
279 if (group->netif == netif) {
280 igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
295 igmp_lookfor_group(
struct netif *ifp,
ip_addr_t *addr)
297 struct igmp_group *group = igmp_group_list;
299 while (group !=
NULL) {
300 if ((group->netif == ifp) && (
ip_addr_cmp(&(group->group_address), addr))) {
321 igmp_lookup_group(
struct netif *ifp,
ip_addr_t *addr)
323 struct igmp_group *group = igmp_group_list;
326 group = igmp_lookfor_group(ifp, addr);
333 group = (
struct igmp_group *)
memp_malloc(MEMP_IGMP_GROUP);
338 group->group_state = IGMP_GROUP_NON_MEMBER;
339 group->last_reporter_flag = 0;
341 group->next = igmp_group_list;
343 igmp_group_list = group;
346 LWIP_DEBUGF(
IGMP_DEBUG, (
"igmp_lookup_group: %sallocated a new group with address ", (group?
"":
"impossible to ")));
360 igmp_remove_group(
struct igmp_group *group)
365 if (igmp_group_list == group) {
366 igmp_group_list = group->next;
369 struct igmp_group *tmpGroup;
370 for (tmpGroup = igmp_group_list; tmpGroup !=
NULL; tmpGroup = tmpGroup->next) {
371 if (tmpGroup->next == group) {
372 tmpGroup->next = group->next;
377 if (tmpGroup ==
NULL)
394 igmp_input(
struct pbuf *p,
struct netif *inp,
ip_addr_t *dest)
397 struct igmp_msg* igmp;
398 struct igmp_group* group;
399 struct igmp_group* groupref;
419 igmp = (
struct igmp_msg *)p->
payload;
428 group = igmp_lookfor_group(inp, dest);
439 switch (igmp->igmp_msgtype) {
440 case IGMP_MEMB_QUERY: {
444 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)));
446 if (igmp->igmp_maxresp == 0) {
448 LWIP_DEBUGF(
IGMP_DEBUG, (
"igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
449 igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
454 groupref = igmp_group_list;
457 if ((groupref->netif == inp) && (!(
ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
458 igmp_delaying_member(groupref, igmp->igmp_maxresp);
460 groupref = groupref->next;
469 LWIP_DEBUGF(
IGMP_DEBUG, (
" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (
int)(igmp->igmp_maxresp)));
472 group = igmp_lookfor_group(inp, &groupaddr);
474 LWIP_DEBUGF(
IGMP_DEBUG, (
" with the group address as destination [igmp_maxresp=%i]\n", (
int)(igmp->igmp_maxresp)));
479 igmp_delaying_member(group, igmp->igmp_maxresp);
489 case IGMP_V2_MEMB_REPORT: {
492 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
495 group->group_state = IGMP_GROUP_IDLE_MEMBER;
496 group->last_reporter_flag = 0;
502 igmp->igmp_msgtype, group->group_state, &group, group->netif));
523 struct igmp_group *group;
532 while (netif !=
NULL) {
536 group = igmp_lookup_group(netif, groupaddr);
540 if (group->group_state != IGMP_GROUP_NON_MEMBER) {
549 if ((group->use==0) && (netif->igmp_mac_filter !=
NULL)) {
553 netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
557 igmp_send(group, IGMP_V2_MEMB_REPORT);
559 igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
562 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
593 struct igmp_group *group;
602 while (netif !=
NULL) {
606 group = igmp_lookfor_group(netif, groupaddr);
615 if (group->use <= 1) {
617 if (group->last_reporter_flag) {
620 igmp_send(group, IGMP_LEAVE_GROUP);
624 if (netif->igmp_mac_filter !=
NULL) {
628 netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
636 igmp_remove_group(group);
662 struct igmp_group *group = igmp_group_list;
664 while (group !=
NULL) {
665 if (group->timer > 0) {
667 if (group->timer == 0) {
682 igmp_timeout(
struct igmp_group *group)
685 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
691 igmp_send(group, IGMP_V2_MEMB_REPORT);
703 igmp_start_timer(
struct igmp_group *group,
u8_t max_time)
710 group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
719 igmp_stop_timer(
struct igmp_group *group)
731 igmp_delaying_member(
struct igmp_group *group,
u8_t maxresp)
733 if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
734 ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
735 ((group->timer == 0) || (maxresp < group->timer)))) {
736 igmp_start_timer(group, maxresp);
737 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
768 return ip_output_if_opt(p, src, dest, IGMP_TTL, 0,
IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
778 igmp_send(
struct igmp_group *group,
u8_t type)
781 struct igmp_msg* igmp =
NULL;
789 igmp = (
struct igmp_msg *)p->
payload;
790 LWIP_ASSERT(
"igmp_send: check that first pbuf can hold struct igmp_msg",
791 (p->
len >=
sizeof(
struct igmp_msg)));
794 if (type == IGMP_V2_MEMB_REPORT) {
795 dest = &(group->group_address);
796 ip_addr_copy(igmp->igmp_group_address, group->group_address);
797 group->last_reporter_flag = 1;
799 if (type == IGMP_LEAVE_GROUP) {
801 ip_addr_copy(igmp->igmp_group_address, group->group_address);
805 if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {
806 igmp->igmp_msgtype = type;
807 igmp->igmp_maxresp = 0;
808 igmp->igmp_checksum = 0;
809 igmp->igmp_checksum =
inet_chksum(igmp, IGMP_MINLEN);
811 igmp_ip_output_if(p, &src, dest, group->netif);
void memp_free(memp_t type, void *mem) ICACHE_FLASH_ATTR
u16_t inet_chksum(void *dataptr, u16_t len) ICACHE_FLASH_ATTR
#define ip_addr_set(dest, src)
struct netif * netif_list
#define IGMP_STATS_INC(x)
#define ip_addr_debug_print(debug, ipaddr)
const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR
#define ICACHE_FLASH_ATTR
void * memp_malloc(memp_t type) ICACHE_FLASH_ATTR
#define LWIP_ERROR(message, expression, handler)
#define LWIP_DEBUGF(debug, message)
#define ip_addr_cmp(addr1, addr2)
#define ip_addr_copy(dest, src)
#define PACK_STRUCT_STRUCT
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
#define ip_addr_isany(addr1)
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
#define PACK_STRUCT_BEGIN
u8_t pbuf_header(struct pbuf *p, s16_t header_size) ICACHE_FLASH_ATTR
#define LWIP_ASSERT(message, assertion)
#define ip_addr_ismulticast(addr1)
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) ICACHE_FLASH_ATTR
#define IP4_ADDR(ipaddr, a, b, c, d)
#define PACK_STRUCT_FIELD(x)