Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2035738
implemented igmpv3 query sending on downstream interfaces
Apr 25, 2020
9b032b8
added common igmp.h with structs and defines for IGMPv3
zocker007 Apr 26, 2020
a3240b2
fixed includes missing
zocker007 Apr 26, 2020
d96a7df
fixed timer delays
zocker007 Apr 28, 2020
5f514c1
first try to implement SSM with IGMPv3
zocker007 Apr 30, 2020
7ebc53f
fixed linker error
zocker007 Apr 30, 2020
55939ae
fixed compiler error
zocker007 Apr 30, 2020
02df188
fixed logging error in fkt interfaceInRoute
zocker007 May 1, 2020
0242720
fix exclude with sources handled like include, now exclude sources ar…
zocker007 May 1, 2020
e6f0383
fixed IGMPv2 group join
zocker007 May 1, 2020
1d5b193
reworked group join for IGMPv3 SSM, blocking addresses in exclude mod…
zocker007 May 2, 2020
29e359f
fixed filtering of SSDP messages for IGMPv3
zocker007 May 3, 2020
5da3876
fixed length of structures with flexible array members
zocker007 May 3, 2020
2ee6d75
fixed syscall error when to_ex is send twice
zocker007 May 3, 2020
ccc75de
changed timeout fix fo better portability (timeout can be changed in …
zocker007 May 3, 2020
fca44b9
fixed log output in interfaceInRoute
zocker007 May 3, 2020
4e3a1e8
fixed compile errors
zocker007 May 3, 2020
b36f661
fixed checksum calculation
zocker007 May 3, 2020
3be9d1a
set DF flag on IGMP queries
zocker007 May 5, 2020
762c006
Merge pull request #1 from zocker007/fix-timeouts
zocker007 May 8, 2020
dbd313d
change os headers for new igmp.h
zocker007 May 13, 2020
2bea55c
fix source specific leave for last source and more than one upstream …
zocker007 May 13, 2020
203aa8d
fix log message on join/leave
zocker007 May 13, 2020
3ddeb34
add comment
zocker007 May 13, 2020
3c0953a
Merge pull request #2 from zocker007/IGMPv3
zocker007 May 13, 2020
9a86875
add comment on fall through
zocker007 May 13, 2020
e7feb37
add comment on remaining fallthroughs
zocker007 May 13, 2020
5c6e9ec
Merge git://github.com/pali/igmpproxy into pali-master
zocker007 Jun 8, 2021
80569b2
Merge branch 'pali-master'
zocker007 Jun 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/ifvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ void rebuildIfVc () {
my_log(LOG_NOTICE, 0, "%s [Hidden -> Downstream]", Dp->Name);
Dp->state = IF_STATE_DOWNSTREAM;
addVIF(Dp);
k_join(Dp, allrouters_group);
k_join(Dp, allrouters_group, 0);
}

// addVIF when found new IF
if (Dp == IfDescEp) {
my_log(LOG_NOTICE, 0, "%s [New]", Dp->Name);
Dp->state = config->defaultInterfaceState;
addVIF(Dp);
k_join(Dp, allrouters_group);
k_join(Dp, allrouters_group, 0);
IfDescEp++;
}

Expand All @@ -187,7 +187,7 @@ void rebuildIfVc () {
if (IF_STATE_LOST == Dp->state) {
my_log(LOG_NOTICE, 0, "%s [Downstream -> Hidden]", Dp->Name);
Dp->state = IF_STATE_HIDDEN;
k_leave(Dp, allrouters_group);
k_leave(Dp, allrouters_group, 0);
delVIF(Dp);
}
}
Expand Down
75 changes: 38 additions & 37 deletions src/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
*/

#include "igmpproxy.h"
#include "igmpv3.h"

// Globals
uint32_t allhosts_group; /* All hosts addr in net order */
Expand Down Expand Up @@ -71,8 +70,9 @@ void initIgmp(void) {
*/
ip->ip_v = IPVERSION;
ip->ip_hl = (sizeof(struct ip) + 4) >> 2; /* +4 for Router Alert option */
ip->ip_tos = 0xc0; /* Internet Control */
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
ip->ip_tos = 0xc0; /* Internet Control */
ip->ip_off = htons(IP_DF); /* set Don't Fragment flag */
ip->ip_ttl = MAXTTL; /* applies to unicasts only */
ip->ip_p = IPPROTO_IGMP;

allhosts_group = htonl(INADDR_ALLHOSTS_GROUP);
Expand Down Expand Up @@ -107,8 +107,8 @@ void acceptIgmp(int recvlen) {
register uint32_t src, dst, group;
struct ip *ip;
struct igmp *igmp;
struct igmpv3_report *igmpv3;
struct igmpv3_grec *grec;
struct igmp_report *igmpv3;
struct igmp_grouprec *grec;
int ipdatalen, iphdrlen, ngrec, nsrcs, i;

if (recvlen < (int)sizeof(struct ip)) {
Expand All @@ -121,13 +121,6 @@ void acceptIgmp(int recvlen) {
src = ip->ip_src.s_addr;
dst = ip->ip_dst.s_addr;

/* filter local multicast 239.255.255.250 */
if (dst == htonl(0xEFFFFFFA))
{
my_log(LOG_NOTICE, 0, "The IGMP message was local multicast. Ignoring.");
return;
}

/*
* this is most likely a message from the kernel indicating that
* a new src grp pair message has arrived and so, it would be
Expand Down Expand Up @@ -192,7 +185,7 @@ void acceptIgmp(int recvlen) {

igmp = (struct igmp *)(recv_buf + iphdrlen);
if ((ipdatalen < IGMP_MINLEN) ||
(igmp->igmp_type == IGMP_V3_MEMBERSHIP_REPORT && ipdatalen <= IGMPV3_MINLEN)) {
(igmp->igmp_type == IGMP_V3_MEMBERSHIP_REPORT && ipdatalen <= IGMP_V3_REPORT_MINLEN)) {
my_log(LOG_WARNING, 0,
"received IP data field too short (%u bytes) for IGMP, from %s",
ipdatalen, inetFmt(src, s1));
Expand All @@ -207,47 +200,51 @@ void acceptIgmp(int recvlen) {
case IGMP_V1_MEMBERSHIP_REPORT:
case IGMP_V2_MEMBERSHIP_REPORT:
group = igmp->igmp_group.s_addr;
acceptGroupReport(src, group);
acceptGroupReport(src, group, NULL, 0, 0);
return;

case IGMP_V3_MEMBERSHIP_REPORT:
igmpv3 = (struct igmpv3_report *)(recv_buf + iphdrlen);
grec = &igmpv3->igmp_grec[0];
ngrec = ntohs(igmpv3->igmp_ngrec);
igmpv3 = (struct igmp_report *)(recv_buf + iphdrlen);
grec = &igmpv3->ir_groups[0];
ngrec = ntohs(igmpv3->ir_numgrps);
while (ngrec--) {
if ((uint8_t *)igmpv3 + ipdatalen < (uint8_t *)grec + sizeof(*grec))
break;
group = grec->grec_mca.s_addr;
nsrcs = ntohs(grec->grec_nsrcs);
switch (grec->grec_type) {
case IGMPV3_MODE_IS_INCLUDE:
case IGMPV3_CHANGE_TO_INCLUDE:
group = grec->ig_group.s_addr;
nsrcs = ntohs(grec->ig_numsrc);
switch (grec->ig_type) {
case IGMP_MODE_IS_INCLUDE:
case IGMP_CHANGE_TO_INCLUDE_MODE:
if (nsrcs == 0) {
acceptLeaveMessage(src, group);
acceptLeaveMessage(src, group, NULL, 0);
break;
} /* else fall through */
case IGMPV3_MODE_IS_EXCLUDE:
case IGMPV3_CHANGE_TO_EXCLUDE:
case IGMPV3_ALLOW_NEW_SOURCES:
acceptGroupReport(src, group);
case IGMP_ALLOW_NEW_SOURCES:
acceptGroupReport(src, group, grec->ig_sources, nsrcs, grec->ig_type);
break;
case IGMPV3_BLOCK_OLD_SOURCES:
case IGMP_MODE_IS_EXCLUDE:
case IGMP_CHANGE_TO_EXCLUDE_MODE:
acceptGroupReport(src, group, NULL, 0, grec->ig_type);
break;
case IGMP_BLOCK_OLD_SOURCES:
acceptLeaveMessage(src, group, grec->ig_sources, nsrcs);
break;

default:
my_log(LOG_INFO, 0,
"ignoring unknown IGMPv3 group record type %x from %s to %s for %s",
grec->grec_type, inetFmt(src, s1), inetFmt(dst, s2),
grec->ig_type, inetFmt(src, s1), inetFmt(dst, s2),
inetFmt(group, s3));
break;
}
grec = (struct igmpv3_grec *)
(&grec->grec_src[nsrcs] + grec->grec_auxwords * 4);
grec = (struct igmp_grouprec *)
(&grec->ig_sources[nsrcs] + grec->ig_datalen * 4);
}
return;

case IGMP_V2_LEAVE_GROUP:
group = igmp->igmp_group.s_addr;
acceptLeaveMessage(src, group);
acceptLeaveMessage(src, group, NULL, 0);
return;

case IGMP_MEMBERSHIP_QUERY:
Expand All @@ -269,13 +266,14 @@ void acceptIgmp(int recvlen) {
*/
static void buildIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, int datalen) {
struct ip *ip;
struct igmp *igmp;
struct igmpv3 *igmp;
struct Config *conf = getCommonConfig();
extern int curttl;

ip = (struct ip *)send_buf;
ip->ip_src.s_addr = src;
ip->ip_dst.s_addr = dst;
ip_set_len(ip, IP_HEADER_RAOPT_LEN + IGMP_MINLEN + datalen);
ip_set_len(ip, IP_HEADER_RAOPT_LEN + IGMP_V3_QUERY_MINLEN + datalen);

if (IN_MULTICAST(ntohl(dst))) {
ip->ip_ttl = curttl;
Expand All @@ -289,13 +287,16 @@ static void buildIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t g
((unsigned char*)send_buf+MIN_IP_HEADER_LEN)[2] = 0x00;
((unsigned char*)send_buf+MIN_IP_HEADER_LEN)[3] = 0x00;

igmp = (struct igmp *)(send_buf + IP_HEADER_RAOPT_LEN);
igmp = (struct igmpv3 *)(send_buf + IP_HEADER_RAOPT_LEN);
igmp->igmp_type = type;
igmp->igmp_code = code;
igmp->igmp_group.s_addr = group;
igmp->igmp_cksum = 0;
igmp->igmp_misc = conf->robustnessValue & 0x7;
igmp->igmp_qqi = conf->queryInterval;
igmp->igmp_numsrc = 0;
igmp->igmp_cksum = inetChksum((unsigned short *)igmp,
IP_HEADER_RAOPT_LEN + datalen);
IGMP_V3_QUERY_MINLEN + datalen);

}

Expand Down Expand Up @@ -326,7 +327,7 @@ void sendIgmp(uint32_t src, uint32_t dst, int type, int code, uint32_t group, in
#endif
sdst.sin_addr.s_addr = dst;
if (sendto(MRouterFD, send_buf,
IP_HEADER_RAOPT_LEN + IGMP_MINLEN + datalen, 0,
IP_HEADER_RAOPT_LEN + IGMP_V3_QUERY_MINLEN + datalen, 0,
(struct sockaddr *)&sdst, sizeof(sdst)) < 0) {
if (errno == ENETDOWN)
my_log(LOG_ERR, errno, "Sender VIF was down.");
Expand Down
159 changes: 159 additions & 0 deletions src/igmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*-
* Copyright (c) 1988 Stephen Deering.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)igmp.h 8.1 (Berkeley) 6/10/93
* $FreeBSD: releng/11.2/sys/netinet/igmp.h 331722 2018-03-29 02:50:57Z eadler $
*/

#ifndef _NETINET_IGMP_H_
#define _NETINET_IGMP_H_

/*
* Internet Group Management Protocol (IGMP) definitions.
*
* Written by Steve Deering, Stanford, May 1988.
*
* MULTICAST Revision: 3.5.1.2
*/

/* Minimum length of any IGMP protocol message. */
#define IGMP_MINLEN 8

/*
* IGMPv1/v2 query and host report format.
*/
struct igmp {
u_char igmp_type; /* version & type of IGMP message */
u_char igmp_code; /* subtype for routing msgs */
u_short igmp_cksum; /* IP-style checksum */
struct in_addr igmp_group; /* group address being reported */
}; /* (zero for queries) */

/*
* IGMP v3 query format.
*/
struct igmpv3 {
u_char igmp_type; /* version & type of IGMP message */
u_char igmp_code; /* subtype for routing msgs */
u_short igmp_cksum; /* IP-style checksum */
struct in_addr igmp_group; /* group address being reported */
/* (zero for queries) */
u_char igmp_misc; /* reserved/suppress/robustness */
u_char igmp_qqi; /* querier's query interval */
u_short igmp_numsrc; /* number of sources */
/*struct in_addr igmp_sources[];*/ /* source addresses */
};
#define IGMP_V3_QUERY_MINLEN 12
#define IGMP_EXP(x) (((x) >> 4) & 0x07)
#define IGMP_MANT(x) ((x) & 0x0f)
#define IGMP_QRESV(x) (((x) >> 4) & 0x0f)
#define IGMP_SFLAG(x) (((x) >> 3) & 0x01)
#define IGMP_QRV(x) ((x) & 0x07)

struct igmp_grouprec {
u_char ig_type; /* record type */
u_char ig_datalen; /* length of auxiliary data */
u_short ig_numsrc; /* number of sources */
struct in_addr ig_group; /* group address being reported */
struct in_addr ig_sources[]; /* source addresses */
};
#define IGMP_GRPREC_HDRLEN 8

/*
* IGMPv3 host membership report header.
*/
struct igmp_report {
u_char ir_type; /* IGMP_v3_HOST_MEMBERSHIP_REPORT */
u_char ir_rsv1; /* must be zero */
u_short ir_cksum; /* checksum */
u_short ir_rsv2; /* must be zero */
u_short ir_numgrps; /* number of group records */
struct igmp_grouprec ir_groups[]; /* group records */
};
#define IGMP_V3_REPORT_MINLEN 8
#define IGMP_V3_REPORT_MAXRECS 65535

/*
* Message types, including version number.
*/
#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* membership query */
#define IGMP_v1_HOST_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */
#define IGMP_DVMRP 0x13 /* DVMRP routing message */
#define IGMP_PIM 0x14 /* PIMv1 message (historic) */
#define IGMP_v2_HOST_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */
#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* Leave-group message */
#define IGMP_MTRACE_REPLY 0x1e /* mtrace(8) reply */
#define IGMP_MTRACE_QUERY 0x1f /* mtrace(8) probe */
#define IGMP_v3_HOST_MEMBERSHIP_REPORT 0x22 /* Ver. 3 membership report */

/*
* IGMPv3 report modes.
*/
#define IGMP_DO_NOTHING 0 /* don't send a record */
#define IGMP_MODE_IS_INCLUDE 1 /* MODE_IN */
#define IGMP_MODE_IS_EXCLUDE 2 /* MODE_EX */
#define IGMP_CHANGE_TO_INCLUDE_MODE 3 /* TO_IN */
#define IGMP_CHANGE_TO_EXCLUDE_MODE 4 /* TO_EX */
#define IGMP_ALLOW_NEW_SOURCES 5 /* ALLOW_NEW */
#define IGMP_BLOCK_OLD_SOURCES 6 /* BLOCK_OLD */

/*
* IGMPv3 filter modes
*/
#define IGMP_FILTER_MODE_EXCLUDE 1
#define IGMP_FILTER_MODE_INCLUDE 2

/*
* IGMPv3 query types.
*/
#define IGMP_V3_GENERAL_QUERY 1
#define IGMP_V3_GROUP_QUERY 2
#define IGMP_V3_GROUP_SOURCE_QUERY 3

/*
* Maximum report interval for IGMP v1/v2 host membership reports [RFC 1112]
*/
#define IGMP_V1V2_MAX_RI 10
#define IGMP_MAX_HOST_REPORT_DELAY IGMP_V1V2_MAX_RI

/*
* IGMP_TIMER_SCALE denotes that the igmp code field specifies
* time in tenths of a second.
*/
#define IGMP_TIMER_SCALE 10

/*
* Group address or IGMPv3 messages: 224.0.0.22
*/
#define INADDR_ALLIGMPV3_GROUP ((in_addr_t) 0xe0000016)

#endif /* _NETINET_IGMP_H_ */
2 changes: 1 addition & 1 deletion src/igmpproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ void igmpProxyRun(void) {
timeout = NULL;
} else {
timeout->tv_nsec = 0;
timeout->tv_sec = (secs > 3) ? 3 : secs; // aimwang: set max timeout
timeout->tv_sec = secs = (secs > 3) ? 3 : secs; // aimwang: set max timeout
}

// Prepare for select.
Expand Down
13 changes: 7 additions & 6 deletions src/igmpproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,24 +242,25 @@ void k_hdr_include(int hdrincl);
void k_set_ttl(int t);
void k_set_loop(int l);
void k_set_if(uint32_t ifa);
void k_join(struct IfDesc *ifd, uint32_t grp);
void k_leave(struct IfDesc *ifd, uint32_t grp);
int k_joinleave(int cmd, struct IfDesc *ifd, uint32_t grp, uint32_t originAddr)
void k_join(struct IfDesc *ifd, uint32_t grp, uint32_t originAddr);
void k_leave(struct IfDesc *ifd, uint32_t grp, uint32_t originAddr);

/* rttable.c
*/
void initRouteTable(void);
void clearAllRoutes(void);
int insertRoute(uint32_t group, int ifx, uint32_t src);
int insertRoute(uint32_t group, int ifx, uint32_t src, struct in_addr *originAddr, u_short numOriginAddr, u_char type);
int activateRoute(uint32_t group, uint32_t originAddr, int upstrVif);
void ageActiveRoutes(void);
void setRouteLastMemberMode(uint32_t group, uint32_t src);
void setRouteLastMemberMode(uint32_t group, uint32_t src, struct in_addr *originAddr, u_short numOriginAddr );
int lastMemberGroupAge(uint32_t group);
int interfaceInRoute(int32_t group, int Ix);

/* request.c
*/
void acceptGroupReport(uint32_t src, uint32_t group);
void acceptLeaveMessage(uint32_t src, uint32_t group);
void acceptGroupReport(uint32_t src, uint32_t group, struct in_addr *originAddr, u_short numOriginAddr, u_char type);
void acceptLeaveMessage(uint32_t src, uint32_t group, struct in_addr *originAddr, u_short numOriginAddr );
void sendGeneralMembershipQuery(void);

/* callout.c
Expand Down
Loading