diff --git a/igmp.c b/igmp.c index 53eb87c1..9ef7cccb 100644 --- a/igmp.c +++ b/igmp.c @@ -42,6 +42,42 @@ #include "defs.h" +//#ifdef GIL_SUPPORT_IGMPV3 //24Oct13, can be moved to ./igmpv3.h +#define IGMPV3_HOST_MEMBERSHIP_REPORT 0x22 /* V3 version of 0x11 */ +/* V3 group record types [grec_type] */ +#define IGMPV3_MODE_IS_INCLUDE 1 +#define IGMPV3_MODE_IS_EXCLUDE 2 +#define IGMPV3_CHANGE_TO_INCLUDE 3 +#define IGMPV3_CHANGE_TO_EXCLUDE 4 +#define IGMPV3_ALLOW_NEW_SOURCES 5 +#define IGMPV3_BLOCK_OLD_SOURCES 6 + +//Support iGMPv3 w/o support 'grec_src[]'! +//From all in BigEndian Format +/* V3 group record types [grec_type] */ +#define IGMPV3_MODE_IS_INCLUDE 1 +#define IGMPV3_MODE_IS_EXCLUDE 2 +#define IGMPV3_CHANGE_TO_INCLUDE 3 +#define IGMPV3_CHANGE_TO_EXCLUDE 4 +#define IGMPV3_ALLOW_NEW_SOURCES 5 +#define IGMPV3_BLOCK_OLD_SOURCES 6 +struct igmpv3_grec { + u_int8_t grec_type; + u_int8_t grec_auxwords; + u_int16_t grec_nsrcs; + u_int32 grec_mca; + u_int32 grec_src[0]; +}; +struct igmpv3_report { + u_int8_t type; + u_int8_t resv1; + u_int16_t csum; + u_int16_t resv2; + u_int16_t ngrec; + struct igmpv3_grec grec[0]; +}; +//#endif /*GIL_SUPPORT_IGMPV3*/ + /* * Exported variables. */ @@ -262,6 +298,48 @@ static void accept_igmp(ssize_t recvlen) return; } +//#ifdef GIL_SUPPORT_IGMPV3 //24Oct13 + case IGMPV3_HOST_MEMBERSHIP_REPORT: //Join / Leave + { + int ngrec, grec_i; + char *NextGrecPtr; + struct igmpv3_report *igmpv3; + struct igmpv3_grec *Grec; + + igmpv3 = (struct igmpv3_report *)(igmp_recv_buf + iphdrlen); + ngrec = ntohs(igmpv3->ngrec); + + //logit(LOG_DEBUG, 0, "GIL 24OCT13 accept_igmp V3iGMP_Report type:0x%x src:%s dst:%s num_grp:%u", + // igmpv3->type, inet_fmt(src, s1, sizeof(s1)), inet_fmt(dst, s2, sizeof(s2)), ngrec ); + Grec = &igmpv3->grec[0]; + NextGrecPtr = (char *)Grec; + for (grec_i = 0; grec_i < ngrec; grec_i++) + { + u_int8_t grec_type = Grec->grec_type; //was: igmpv3->grec[grec_i].grec_type; + u_int16_t num_src = ntohs(Grec->grec_nsrcs); //was: ntohs(igmpv3->grec[grec_i].grec_nsrcs); + + group = Grec->grec_mca; //Keep it in BigEndian/NetworkOrder //was: igmpv3->grec[grec_i].grec_mca; + //logit(LOG_DEBUG, 0, "..GIL 24OCT13 accept_igmp grec:%u type:%u #src:%u group:%s ptr-match:%u", grec_i, grec_type, num_src, + // inet_fmt(group, s2, sizeof(s2)), (NextGrecPtr==(char *)&igmpv3->grec[grec_i]) ); + //Note "dst" is not as in IGMP_V1/V2 it is always 224.0.0.22, but it is ignored by the following callee + //Also type is only checked against IGMP_V1_MEMBERSHIP_REPORT or else... + //advance Grec for next loop! + NextGrecPtr += sizeof(struct igmpv3_grec); // Normal advance (i.e. for SOURCE EXCLUDE) + if (num_src > 1) + NextGrecPtr += (num_src - 1) * sizeof(u_int32); // adjust for grec_src[N] + Grec = (struct igmpv3_grec *)NextGrecPtr; + + if (num_src != 0) + continue; + if ((grec_type == IGMPV3_MODE_IS_EXCLUDE) || (grec_type == IGMPV3_CHANGE_TO_EXCLUDE)) + accept_group_report(src, dst, group, igmp->igmp_type); + else if (grec_type == IGMPV3_CHANGE_TO_INCLUDE) + accept_leave_message(src, dst, group); + } + } + return; +//#endif /*GIL_SUPPORT_IGMPV3*/ + case IGMP_PIM: return; /* TODO: this is PIM v1 message. Handle it?. */ diff --git a/vif.c b/vif.c index 9e339f7b..f1253ae2 100644 --- a/vif.c +++ b/vif.c @@ -39,6 +39,10 @@ #include "defs.h" +//#ifdef GIL_SUPPORT_IGMPV3 //24Oct13 Add IGMPV3 Manage-Ip k_join/k_leave +#include +#define MCAST_ALL_IGMP_ROUTERS "224.0.0.22" //IGMPv3 Manage-Ip +//#endif /*GIL_SUPPORT_IGMPV3*/ /* @@ -318,6 +322,12 @@ static void start_vif(vifi_t vifi) */ k_join(igmp_socket, allrouters_group, v); +//#ifdef GIL_SUPPORT_IGMPV3 //24Oct13 Add IGMPV3 Manage-Ip k_join/k_leave + /* + * TO support V3 MEMBERSHIP_REPORT need to join ALL-IGMP-ROUTERS + */ + k_join(igmp_socket, inet_addr(MCAST_ALL_IGMP_ROUTERS), v); +//#endif /*GIL_SUPPORT_IGMPV3*/ /* * Until neighbors are discovered, assume responsibility for sending * periodic group membership queries to the subnet. Send the first @@ -368,6 +378,9 @@ static void stop_vif(vifi_t vifi) if (!(v->uv_flags & VIFF_REGISTER)) { k_leave(igmp_socket, allpimrouters_group, v); k_leave(igmp_socket, allrouters_group, v); +//#ifdef GIL_SUPPORT_IGMPV3 //24Oct13 Add IGMPV3 Manage-Ip k_join/k_leave + k_leave(igmp_socket, inet_addr(MCAST_ALL_IGMP_ROUTERS), v); +//#endif /*GIL_SUPPORT_IGMPV3*/ /* * Discard all group addresses. (No need to tell kernel; * the k_del_vif() call will clean up kernel state.)