00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #include "lwip/opt.h"
00081
00082 #if LWIP_IGMP
00083
00084 #include "lwip/igmp.h"
00085 #include "lwip/debug.h"
00086 #include "lwip/def.h"
00087 #include "lwip/mem.h"
00088 #include "lwip/ip.h"
00089 #include "lwip/inet_chksum.h"
00090 #include "lwip/netif.h"
00091 #include "lwip/icmp.h"
00092 #include "lwip/udp.h"
00093 #include "lwip/tcp.h"
00094 #include "lwip/stats.h"
00095
00096 #include "string.h"
00097
00098
00099
00100
00101 #define IGMP_TTL 1
00102 #define IGMP_MINLEN 8
00103 #define ROUTER_ALERT 0x9404U
00104 #define ROUTER_ALERTLEN 4
00105
00106
00107
00108
00109 #define IGMP_MEMB_QUERY 0x11
00110 #define IGMP_V1_MEMB_REPORT 0x12
00111 #define IGMP_V2_MEMB_REPORT 0x16
00112 #define IGMP_LEAVE_GROUP 0x17
00113
00114
00115 #define IGMP_GROUP_NON_MEMBER 0
00116 #define IGMP_GROUP_DELAYING_MEMBER 1
00117 #define IGMP_GROUP_IDLE_MEMBER 2
00118
00119
00120
00121
00122 #ifdef PACK_STRUCT_USE_INCLUDES
00123 # include "arch/bpstruct.h"
00124 #endif
00125 PACK_STRUCT_BEGIN
00126 struct igmp_msg {
00127 PACK_STRUCT_FIELD(u8_t igmp_msgtype);
00128 PACK_STRUCT_FIELD(u8_t igmp_maxresp);
00129 PACK_STRUCT_FIELD(u16_t igmp_checksum);
00130 PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address);
00131 } PACK_STRUCT_STRUCT;
00132 PACK_STRUCT_END
00133 #ifdef PACK_STRUCT_USE_INCLUDES
00134 # include "arch/epstruct.h"
00135 #endif
00136
00137
00138 static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
00139 static err_t igmp_remove_group(struct igmp_group *group);
00140 static void igmp_timeout( struct igmp_group *group);
00141 static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
00142 static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
00143 static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
00144 static void igmp_send(struct igmp_group *group, u8_t type);
00145
00146
00147 static struct igmp_group* igmp_group_list;
00148 static ip_addr_t allsystems;
00149 static ip_addr_t allrouters;
00150
00151
00152
00153
00154
00155 void
00156 igmp_init(void)
00157 {
00158 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_init: initializing\n"));
00159
00160 IP4_ADDR(&allsystems, 224, 0, 0, 1);
00161 IP4_ADDR(&allrouters, 224, 0, 0, 2);
00162 }
00163
00164 #ifdef LWIP_DEBUG
00165
00166
00167
00168 void
00169 igmp_dump_group_list()
00170 {
00171 struct igmp_group *group = igmp_group_list;
00172
00173 while (group != NULL) {
00174 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
00175 ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
00176 LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
00177 group = group->next;
00178 }
00179 LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
00180 }
00181 #else
00182 #define igmp_dump_group_list()
00183 #endif
00184
00185
00186
00187
00188
00189
00190 err_t
00191 igmp_start(struct netif *netif)
00192 {
00193 struct igmp_group* group;
00194
00195 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: starting IGMP processing on if %p\n", netif));
00196
00197 group = igmp_lookup_group(netif, &allsystems);
00198
00199 if (group != NULL) {
00200 group->group_state = IGMP_GROUP_IDLE_MEMBER;
00201 group->use++;
00202
00203
00204 if (netif->igmp_mac_filter != NULL) {
00205 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
00206 ip_addr_debug_print(IGMP_DEBUG, &allsystems);
00207 LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
00208 netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);
00209 }
00210
00211 return ERR_OK;
00212 }
00213
00214 return ERR_MEM;
00215 }
00216
00217
00218
00219
00220
00221
00222 err_t
00223 igmp_stop(struct netif *netif)
00224 {
00225 struct igmp_group *group = igmp_group_list;
00226 struct igmp_group *prev = NULL;
00227 struct igmp_group *next;
00228
00229
00230 while (group != NULL) {
00231 next = group->next;
00232
00233 if (group->netif == netif) {
00234
00235 if (group == igmp_group_list) {
00236 igmp_group_list = next;
00237 }
00238
00239 if (prev != NULL) {
00240 prev->next = next;
00241 }
00242
00243 if (netif->igmp_mac_filter != NULL) {
00244 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_stop: igmp_mac_filter(DEL "));
00245 ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
00246 LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
00247 netif->igmp_mac_filter(netif, &(group->group_address), IGMP_DEL_MAC_FILTER);
00248 }
00249
00250 memp_free(MEMP_IGMP_GROUP, group);
00251 } else {
00252
00253 prev = group;
00254 }
00255
00256 group = next;
00257 }
00258 return ERR_OK;
00259 }
00260
00261
00262
00263
00264
00265
00266 void
00267 igmp_report_groups(struct netif *netif)
00268 {
00269 struct igmp_group *group = igmp_group_list;
00270
00271 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
00272
00273 while (group != NULL) {
00274 if (group->netif == netif) {
00275 igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
00276 }
00277 group = group->next;
00278 }
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 struct igmp_group *
00290 igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr)
00291 {
00292 struct igmp_group *group = igmp_group_list;
00293
00294 while (group != NULL) {
00295 if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
00296 return group;
00297 }
00298 group = group->next;
00299 }
00300
00301
00302
00303
00304 return NULL;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 struct igmp_group *
00316 igmp_lookup_group(struct netif *ifp, ip_addr_t *addr)
00317 {
00318 struct igmp_group *group = igmp_group_list;
00319
00320
00321 group = igmp_lookfor_group(ifp, addr);
00322 if (group != NULL) {
00323
00324 return group;
00325 }
00326
00327
00328 group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
00329 if (group != NULL) {
00330 group->netif = ifp;
00331 ip_addr_set(&(group->group_address), addr);
00332 group->timer = 0;
00333 group->group_state = IGMP_GROUP_NON_MEMBER;
00334 group->last_reporter_flag = 0;
00335 group->use = 0;
00336 group->next = igmp_group_list;
00337
00338 igmp_group_list = group;
00339 }
00340
00341 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to ")));
00342 ip_addr_debug_print(IGMP_DEBUG, addr);
00343 LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", ifp));
00344
00345 return group;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 static err_t
00355 igmp_remove_group(struct igmp_group *group)
00356 {
00357 err_t err = ERR_OK;
00358
00359
00360 if (igmp_group_list == group) {
00361 igmp_group_list = group->next;
00362 } else {
00363
00364 struct igmp_group *tmpGroup;
00365 for (tmpGroup = igmp_group_list; tmpGroup != NULL; tmpGroup = tmpGroup->next) {
00366 if (tmpGroup->next == group) {
00367 tmpGroup->next = group->next;
00368 break;
00369 }
00370 }
00371
00372 if (tmpGroup == NULL)
00373 err = ERR_ARG;
00374 }
00375
00376 memp_free(MEMP_IGMP_GROUP, group);
00377
00378 return err;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388 void
00389 igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
00390 {
00391 struct ip_hdr * iphdr;
00392 struct igmp_msg* igmp;
00393 struct igmp_group* group;
00394 struct igmp_group* groupref;
00395
00396 IGMP_STATS_INC(igmp.recv);
00397
00398
00399 iphdr = (struct ip_hdr *)p->payload;
00400 if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
00401 pbuf_free(p);
00402 IGMP_STATS_INC(igmp.lenerr);
00403 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: length error\n"));
00404 return;
00405 }
00406
00407 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: message from "));
00408 ip_addr_debug_print(IGMP_DEBUG, &(iphdr->src));
00409 LWIP_DEBUGF(IGMP_DEBUG, (" to address "));
00410 ip_addr_debug_print(IGMP_DEBUG, &(iphdr->dest));
00411 LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", inp));
00412
00413
00414 igmp = (struct igmp_msg *)p->payload;
00415 if (inet_chksum(igmp, p->len)) {
00416 pbuf_free(p);
00417 IGMP_STATS_INC(igmp.chkerr);
00418 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: checksum error\n"));
00419 return;
00420 }
00421
00422
00423 group = igmp_lookfor_group(inp, dest);
00424
00425
00426 if (!group) {
00427 pbuf_free(p);
00428 IGMP_STATS_INC(igmp.drop);
00429 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
00430 return;
00431 }
00432
00433
00434 switch (igmp->igmp_msgtype) {
00435 case IGMP_MEMB_QUERY: {
00436
00437 if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) {
00438
00439 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)));
00440
00441 if (igmp->igmp_maxresp == 0) {
00442 IGMP_STATS_INC(igmp.rx_v1);
00443 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
00444 igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
00445 } else {
00446 IGMP_STATS_INC(igmp.rx_general);
00447 }
00448
00449 groupref = igmp_group_list;
00450 while (groupref) {
00451
00452 if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
00453 igmp_delaying_member(groupref, igmp->igmp_maxresp);
00454 }
00455 groupref = groupref->next;
00456 }
00457 } else {
00458
00459 if (!ip_addr_isany(&igmp->igmp_group_address)) {
00460 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
00461 ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
00462 if (ip_addr_cmp(dest, &allsystems)) {
00463 ip_addr_t groupaddr;
00464 LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
00465
00466 ip_addr_copy(groupaddr, igmp->igmp_group_address);
00467 group = igmp_lookfor_group(inp, &groupaddr);
00468 } else {
00469 LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
00470 }
00471
00472 if (group != NULL) {
00473 IGMP_STATS_INC(igmp.rx_group);
00474 igmp_delaying_member(group, igmp->igmp_maxresp);
00475 } else {
00476 IGMP_STATS_INC(igmp.drop);
00477 }
00478 } else {
00479 IGMP_STATS_INC(igmp.proterr);
00480 }
00481 }
00482 break;
00483 }
00484 case IGMP_V2_MEMB_REPORT: {
00485 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
00486 IGMP_STATS_INC(igmp.rx_report);
00487 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
00488
00489 group->timer = 0;
00490 group->group_state = IGMP_GROUP_IDLE_MEMBER;
00491 group->last_reporter_flag = 0;
00492 }
00493 break;
00494 }
00495 default: {
00496 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
00497 igmp->igmp_msgtype, group->group_state, &group, group->netif));
00498 IGMP_STATS_INC(igmp.proterr);
00499 break;
00500 }
00501 }
00502
00503 pbuf_free(p);
00504 return;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514 err_t
00515 igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
00516 {
00517 err_t err = ERR_VAL;
00518 struct igmp_group *group;
00519 struct netif *netif;
00520
00521
00522 LWIP_ERROR("igmp_joingroup: attempt to join non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
00523 LWIP_ERROR("igmp_joingroup: attempt to join allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
00524
00525
00526 netif = netif_list;
00527 while (netif != NULL) {
00528
00529 if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {
00530
00531 group = igmp_lookup_group(netif, groupaddr);
00532
00533 if (group != NULL) {
00534
00535 if (group->group_state != IGMP_GROUP_NON_MEMBER) {
00536 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to group not in state IGMP_GROUP_NON_MEMBER\n"));
00537 } else {
00538
00539 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: join to new group: "));
00540 ip_addr_debug_print(IGMP_DEBUG, groupaddr);
00541 LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
00542
00543
00544 if ((group->use==0) && (netif->igmp_mac_filter != NULL)) {
00545 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: igmp_mac_filter(ADD "));
00546 ip_addr_debug_print(IGMP_DEBUG, groupaddr);
00547 LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
00548 netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
00549 }
00550
00551 IGMP_STATS_INC(igmp.tx_join);
00552 igmp_send(group, IGMP_V2_MEMB_REPORT);
00553
00554 igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
00555
00556
00557 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
00558 }
00559
00560 group->use++;
00561
00562 err = ERR_OK;
00563 } else {
00564
00565
00566 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_joingroup: Not enought memory to join to group\n"));
00567 return ERR_MEM;
00568 }
00569 }
00570
00571 netif = netif->next;
00572 }
00573
00574 return err;
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 err_t
00585 igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
00586 {
00587 err_t err = ERR_VAL;
00588 struct igmp_group *group;
00589 struct netif *netif;
00590
00591
00592 LWIP_ERROR("igmp_leavegroup: attempt to leave non-multicast address", ip_addr_ismulticast(groupaddr), return ERR_VAL;);
00593 LWIP_ERROR("igmp_leavegroup: attempt to leave allsystems address", (!ip_addr_cmp(groupaddr, &allsystems)), return ERR_VAL;);
00594
00595
00596 netif = netif_list;
00597 while (netif != NULL) {
00598
00599 if ((netif->flags & NETIF_FLAG_IGMP) && ((ip_addr_isany(ifaddr) || ip_addr_cmp(&(netif->ip_addr), ifaddr)))) {
00600
00601 group = igmp_lookfor_group(netif, groupaddr);
00602
00603 if (group != NULL) {
00604
00605 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: Leaving group: "));
00606 ip_addr_debug_print(IGMP_DEBUG, groupaddr);
00607 LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
00608
00609
00610 if (group->use <= 1) {
00611
00612 if (group->last_reporter_flag) {
00613 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
00614 IGMP_STATS_INC(igmp.tx_leave);
00615 igmp_send(group, IGMP_LEAVE_GROUP);
00616 }
00617
00618
00619 if (netif->igmp_mac_filter != NULL) {
00620 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: igmp_mac_filter(DEL "));
00621 ip_addr_debug_print(IGMP_DEBUG, groupaddr);
00622 LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
00623 netif->igmp_mac_filter(netif, groupaddr, IGMP_DEL_MAC_FILTER);
00624 }
00625
00626 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: remove group: "));
00627 ip_addr_debug_print(IGMP_DEBUG, groupaddr);
00628 LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
00629
00630
00631 igmp_remove_group(group);
00632 } else {
00633
00634 group->use--;
00635 }
00636
00637 err = ERR_OK;
00638 } else {
00639
00640 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: not member of group\n"));
00641 }
00642 }
00643
00644 netif = netif->next;
00645 }
00646
00647 return err;
00648 }
00649
00650
00651
00652
00653
00654 void
00655 igmp_tmr(void)
00656 {
00657 struct igmp_group *group = igmp_group_list;
00658
00659 while (group != NULL) {
00660 if (group->timer > 0) {
00661 group->timer--;
00662 if (group->timer == 0) {
00663 igmp_timeout(group);
00664 }
00665 }
00666 group = group->next;
00667 }
00668 }
00669
00670
00671
00672
00673
00674
00675
00676 static void
00677 igmp_timeout(struct igmp_group *group)
00678 {
00679
00680 if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
00681 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
00682 ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));
00683 LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
00684
00685 IGMP_STATS_INC(igmp.tx_report);
00686 igmp_send(group, IGMP_V2_MEMB_REPORT);
00687 }
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697 static void
00698 igmp_start_timer(struct igmp_group *group, u8_t max_time)
00699 {
00700
00701 if (max_time == 0) {
00702 max_time = 1;
00703 }
00704
00705 group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714 static void
00715 igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
00716 {
00717 if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
00718 ((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
00719 ((group->timer == 0) || (maxresp < group->timer)))) {
00720 igmp_start_timer(group, maxresp);
00721 group->group_state = IGMP_GROUP_DELAYING_MEMBER;
00722 }
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 static err_t
00745 igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif)
00746 {
00747
00748 u16_t ra[2];
00749 ra[0] = PP_HTONS(ROUTER_ALERT);
00750 ra[1] = 0x0000;
00751 IGMP_STATS_INC(igmp.xmit);
00752 return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
00753 }
00754
00755
00756
00757
00758
00759
00760
00761 static void
00762 igmp_send(struct igmp_group *group, u8_t type)
00763 {
00764 struct pbuf* p = NULL;
00765 struct igmp_msg* igmp = NULL;
00766 ip_addr_t src = *IP_ADDR_ANY;
00767 ip_addr_t* dest = NULL;
00768
00769
00770 p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
00771
00772 if (p) {
00773 igmp = (struct igmp_msg *)p->payload;
00774 LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
00775 (p->len >= sizeof(struct igmp_msg)));
00776 ip_addr_copy(src, group->netif->ip_addr);
00777
00778 if (type == IGMP_V2_MEMB_REPORT) {
00779 dest = &(group->group_address);
00780 ip_addr_copy(igmp->igmp_group_address, group->group_address);
00781 group->last_reporter_flag = 1;
00782 } else {
00783 if (type == IGMP_LEAVE_GROUP) {
00784 dest = &allrouters;
00785 ip_addr_copy(igmp->igmp_group_address, group->group_address);
00786 }
00787 }
00788
00789 if ((type == IGMP_V2_MEMB_REPORT) || (type == IGMP_LEAVE_GROUP)) {
00790 igmp->igmp_msgtype = type;
00791 igmp->igmp_maxresp = 0;
00792 igmp->igmp_checksum = 0;
00793 igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
00794
00795 igmp_ip_output_if(p, &src, dest, group->netif);
00796 }
00797
00798 pbuf_free(p);
00799 } else {
00800 LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
00801 IGMP_STATS_INC(igmp.memerr);
00802 }
00803 }
00804
00805 #endif