update to igmpproxy-0.3, from Joel Knight, minor tweaks from me

This commit is contained in:
sthen 2021-01-12 17:59:49 +00:00
parent c9f4cbfe1a
commit fc6ddb5aa5
24 changed files with 1071 additions and 1336 deletions

View File

@ -1,33 +1,33 @@
# $OpenBSD: Makefile,v 1.19 2019/07/12 20:48:28 sthen Exp $
# $OpenBSD: Makefile,v 1.20 2021/01/12 17:59:49 sthen Exp $
COMMENT = multicast router utilizing IGMP forwarding
VERSION = 0.1-beta2
DISTNAME = igmpproxy-src-${VERSION}
PKGNAME = igmpproxy-${VERSION:S/-beta/b/}
REVISION = 12
VERSION = 0.3
DISTNAME = igmpproxy-${VERSION}
CATEGORIES = net
MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=igmpproxy/}
MASTER_SITES = https://github.com/pali/igmpproxy/releases/download/${VERSION}/
HOMEPAGE = http://igmpproxy.sourceforge.net/
HOMEPAGE = https://github.com/pali/igmpproxy/
# GPLv2+ + mrouted license in igmpproxy/doc/mrouted-LICENSE
# GPLv2+ + mrouted license in igmpproxy/COPYING
PERMIT_PACKAGE = Yes
WANTLIB = c
USE_GMAKE = Yes
CFLAGS += -Wall
MAKE_FLAGS = LDFLAGS="${LDFLAGS}"
DEBUG_PACKAGES = ${BUILD_PACKAGES}
NO_TEST = Yes
WRKDIST = ${WRKDIR}/igmpproxy/src
CONFIGURE_STYLE = gnu
do-install:
${INSTALL_PROGRAM} ${WRKSRC}/igmpproxy ${PREFIX}/sbin
${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.8 ${PREFIX}/man/man8
${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.conf.5 ${PREFIX}/man/man5
${INSTALL_PROGRAM} ${WRKSRC}/src/igmpproxy ${PREFIX}/sbin
${INSTALL_MAN} ${WRKSRC}/doc/igmpproxy.8 ${PREFIX}/man/man8
${INSTALL_MAN} ${WRKSRC}/doc/igmpproxy.conf.5 ${PREFIX}/man/man5
${INSTALL_DATA_DIR} ${PREFIX}/share/examples/igmpproxy
${INSTALL_DATA} ${WRKSRC}/igmpproxy.conf \
${PREFIX}/share/examples/igmpproxy

View File

@ -1,2 +1,2 @@
SHA256 (igmpproxy-src-0.1-beta2.tar.gz) = f25UhuhIJxUMjKQClnyWM0u9Yrn3hRlcTuhNoSGKu0A=
SIZE (igmpproxy-src-0.1-beta2.tar.gz) = 35103
SHA256 (igmpproxy-0.3.tar.gz) = 0fwkTLL7v5n3IL2j6EH+WezptpGQc3kLS4knObG4ROs=
SIZE (igmpproxy-0.3.tar.gz) = 168403

View File

@ -1,28 +0,0 @@
$OpenBSD: patch-Makefile,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
--- Makefile.orig Sat Aug 20 13:34:18 2005
+++ Makefile Sat Jan 26 13:16:23 2008
@@ -6,12 +6,11 @@ MANDIR=/usr/share/man
# CFLAGS=-g
-CFLAGS=-O
+CFLAGS?=-O
+CFLAGS+=-Wall
-default : build.h igmpproxy
+all : build.h igmpproxy
-all : igmpproxy
-
clean :
rm -f *.o *.asm build.h igmpproxy
@@ -21,7 +20,7 @@ install :
cp ../doc/igmpproxy.conf.5 ${MANDIR}/man5
if [ ! -e ${ETCDIR}/igmpproxy.conf ]; then cp igmpproxy.conf ${ETCDIR}; fi
-igmpproxy : igmpproxy.o config.o confread.o request.o udpsock.o mcgroup.o rttable.o \
+igmpproxy : igmpproxy.o config.o confread.o request.o mcgroup.o rttable.o \
igmp.o ifvc.o callout.o kern.o syslog.o lib.o mroute-api.o
build.h :

View File

@ -1,93 +0,0 @@
$OpenBSD: patch-config_c,v 1.3 2016/12/23 13:44:31 rzalamena Exp $
--- config.c.orig Thu Dec 15 19:50:23 2016
+++ config.c Mon Dec 19 21:02:00 2016
@@ -177,7 +177,7 @@
}
// Loop through all VIFs...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
// Now try to find a matching config...
@@ -241,11 +241,10 @@
tmpPtr->allowednets = NULL;
// Make a copy of the token to store the IF name
- tmpPtr->name = (char *)malloc( sizeof(char) * strlen(token) );
+ tmpPtr->name = strdup(token);
if(tmpPtr->name == NULL) {
log(LOG_ERR, 0, "Out of memory.");
}
- strcpy(tmpPtr->name, token);
// Set the altnet pointer to the allowednets pointer.
anetPtr = &tmpPtr->allowednets;
@@ -255,8 +254,6 @@
while(token != NULL) {
if(strcmp("altnet", token)==0) {
// Altnet...
- struct in_addr networkAddr;
-
token = nextConfigToken();
IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Got altnet token %s.",token);
@@ -328,29 +325,18 @@
*/
struct SubnetList *parseSubnetAddress(char *addrstr) {
struct SubnetList *tmpSubnet;
- char *tmpStr;
uint32 addr = 0x00000000;
uint32 mask = 0xFFFFFFFF;
+ int bitcnt;
- // First get the network part of the address...
- tmpStr = strtok(addrstr, "/");
- addr = inet_addr(tmpStr);
-
- tmpStr = strtok(NULL, "/");
- if(tmpStr != NULL) {
- int bitcnt = atoi(tmpStr);
- if(bitcnt <= 0 || bitcnt > 32) {
- log(LOG_WARNING, 0, "The bits part of the address is invalid : %d.",tmpStr);
- return NULL;
- }
-
- mask <<= (32 - bitcnt);
- }
-
- if(addr == -1 || addr == 0) {
- log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr);
+ bitcnt = inet_net_pton(AF_INET, addrstr, &addr, sizeof(addr));
+ if(bitcnt<0) {
+ log(LOG_WARNING, 0, "Unable to parse address token '%s'.",addrstr);
return NULL;
- }
+ } else if(bitcnt>0)
+ mask <<= (32 - bitcnt);
+ else
+ mask = 0;
tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList));
tmpSubnet->subnet_addr = addr;
@@ -363,3 +349,20 @@
return tmpSubnet;
}
+struct vifconfig *
+config_getinterface(const char *ifname)
+{
+ struct vifconfig *vc;
+
+ if (vifconf == NULL)
+ return (NULL);
+
+ for (vc = vifconf; vc; vc = vc->next) {
+ if (strcmp(vc->name, ifname))
+ continue;
+
+ return (vc);
+ }
+
+ return (NULL);
+}

View File

@ -1,107 +0,0 @@
$OpenBSD: patch-defs_h,v 1.4 2016/12/23 13:44:31 rzalamena Exp $
--- defs.h.orig Thu Dec 15 19:50:23 2016
+++ defs.h Mon Dec 19 21:20:06 2016
@@ -40,10 +40,13 @@
#include <stdlib.h>
#include <syslog.h>
#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/time.h>
+#include <sys/ioctl.h>
#include <net/if.h>
@@ -52,13 +55,32 @@
#include <linux/in.h>
#include <linux/mroute.h>
#else
+ #include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/igmp.h>
+ #include <netinet/ip_mroute.h>
#include <arpa/inet.h>
#endif
+#ifndef IGMP_MEMBERSHIP_QUERY
+#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
+#endif
+#ifndef IGMP_V1_MEMBERSHIP_REPORT
+#define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT
+#endif
+#ifndef IGMP_V2_MEMBERSHIP_REPORT
+#define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT
+#endif
+#ifndef IGMP_V2_LEAVE_GROUP
+#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
+#endif
+#ifndef INADDR_ALLRTRS_GROUP
+/* address for multicast mtrace msg */
+#define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */
+#endif
+
// The default path for the config file...
#define IGMPPROXY_CONFIG_FILEPATH "/etc/igmpproxy.conf"
#define ENABLE_DEBUG 1
@@ -73,8 +95,12 @@
#define MAX_MC_VIFS 32 // !!! check this const in the specific includes
// Useful macros..
+#ifndef MIN
#define MIN( a, b ) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
#define MAX( a, b ) ((a) < (b) ? (b) : (a))
+#endif
#define VCMC( Vc ) (sizeof( Vc ) / sizeof( (Vc)[ 0 ] ))
#define VCEP( Vc ) (&(Vc)[ VCMC( Vc ) ])
@@ -126,6 +152,7 @@
#define IF_DEBUG if(Log2Stderr & LOG_DEBUG)
+#define log logit
void log( int Serverity, int Errno, const char *FmtSt, ... );
/* ifvc.c
@@ -196,6 +223,7 @@
struct IfDesc *getIfByName( const char *IfName );
struct IfDesc *getIfByIx( unsigned Ix );
struct IfDesc *getIfByAddress( uint32 Ix );
+int isAdressValidForIf( struct IfDesc* intrface, uint32 ipaddr );
/* mroute-api.c
*/
@@ -221,6 +249,7 @@
int loadConfig(char *configFile);
void configureVifs();
struct Config *getCommonConfig();
+struct vifconfig *config_getinterface(const char *ifname);
/* igmp.c
*/
@@ -235,7 +264,7 @@
char *fmtInAdr( char *St, struct in_addr InAdr );
char *inetFmt(uint32 addr, char *s);
char *inetFmts(uint32 addr, uint32 mask, char *s);
-int inetCksum(u_short *addr, u_int len);
+int inetChksum(u_short *addr, u_int len);
/* kern.c
*/
@@ -264,7 +293,7 @@
void initRouteTable();
void clearAllRoutes();
int insertRoute(uint32 group, int ifx);
-int activateRoute(uint32 group, uint32 originAddr);
+int activateRoute(uint32 group, uint32 originAddr, int downIf);
void ageActiveRoutes();
void setRouteLastMemberMode(uint32 group);
int lastMemberGroupAge(uint32 group);

View File

@ -1,189 +0,0 @@
$OpenBSD: patch-ifvc_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
--- ifvc.c.orig Thu Dec 15 19:50:23 2016
+++ ifvc.c Mon Dec 19 21:22:11 2016
@@ -32,7 +32,8 @@
*/
#include "defs.h"
-#include <linux/sockios.h>
+//#include <linux/sockios.h>
+#include <ifaddrs.h>
struct IfDesc IfDescVc[ MAX_IF ], *IfDescEp = IfDescVc;
@@ -42,119 +43,93 @@
**
*/
void buildIfVc() {
- struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] ) ];
- struct ifreq *IfEp;
+ struct ifaddrs *ifap, *ifa;
+ struct IfDesc *ifp;
+ struct SubnetList *net;
- int Sock;
+ if (getifaddrs(&ifap) < 0)
+ log( LOG_ERR, errno, "getifaddrs" );
- if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
- log( LOG_ERR, errno, "RAW socket open" );
-
- /* get If vector
- */
- {
- struct ifconf IoCtlReq;
-
- IoCtlReq.ifc_buf = (void *)IfVc;
- IoCtlReq.ifc_len = sizeof( IfVc );
-
- if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
- log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );
-
- IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);
- }
-
/* loop over interfaces and copy interface info to IfDescVc
*/
{
- struct ifreq *IfPt;
- struct IfDesc *IfDp;
-
// Temp keepers of interface params...
uint32 addr, subnet, mask;
- for ( IfPt = IfVc; IfPt < IfEp; IfPt++ ) {
- struct ifreq IfReq;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
char FmtBu[ 32 ];
- strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name ) );
+ if (IfDescEp >= &IfDescVc[ MAX_IF ]) {
+ log(LOG_WARNING, 0, "Too many interfaces, skipping %d", ifa->ifa_name);
+ continue;
+ }
- // Currently don't set any allowed nets...
- //IfDescEp->allowednets = NULL;
-
- // Set the index to -1 by default.
- IfDescEp->index = -1;
-
- /* don't retrieve more info for non-IP interfaces
+ /* ignore non-IP interfaces
*/
- if ( IfPt->ifr_addr.sa_family != AF_INET ) {
- IfDescEp->InAdr.s_addr = 0; /* mark as non-IP interface */
- IfDescEp++;
+ if ( ifa->ifa_addr->sa_family != AF_INET )
continue;
- }
- // Get the interface adress...
- IfDescEp->InAdr = ((struct sockaddr_in *)&IfPt->ifr_addr)->sin_addr;
- addr = IfDescEp->InAdr.s_addr;
+ if ((ifp = getIfByName(ifa->ifa_name)) == NULL) {
+ if (config_getinterface(ifa->ifa_name) == NULL)
+ continue;
- memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name ) );
+ strlcpy( IfDescEp->Name, ifa->ifa_name, sizeof( IfDescEp->Name ) );
- // Get the subnet mask...
- if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
- log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", IfReq.ifr_name);
- mask = ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr;
- subnet = addr & mask;
+ log(LOG_DEBUG, 0, "Adding Physical Index value of IF '%s' is %d",
+ IfDescEp->Name, if_nametoindex(IfDescEp->Name));
- // Get the physical index of the Interface
- if (ioctl(Sock, SIOCGIFINDEX, &IfReq ) < 0)
- log(LOG_ERR, errno, "ioctl SIOCGIFINDEX for %s", IfReq.ifr_name);
-
- log(LOG_DEBUG, 0, "Physical Index value of IF '%s' is %d",
- IfDescEp->Name, IfReq.ifr_ifindex);
+ // Set the index to -1 by default.
+ IfDescEp->index = -1;
+ // Get the interface adress...
+ IfDescEp->InAdr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
- /* get if flags
- **
- ** typical flags:
- ** lo 0x0049 -> Running, Loopback, Up
- ** ethx 0x1043 -> Multicast, Running, Broadcast, Up
- ** ipppx 0x0091 -> NoArp, PointToPoint, Up
- ** grex 0x00C1 -> NoArp, Running, Up
- ** ipipx 0x00C1 -> NoArp, Running, Up
- */
- if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
- log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );
+ /* get if flags
+ **
+ ** typical flags:
+ ** lo 0x0049 -> Running, Loopback, Up
+ ** ethx 0x1043 -> Multicast, Running, Broadcast, Up
+ ** ipppx 0x0091 -> NoArp, PointToPoint, Up
+ ** grex 0x00C1 -> NoArp, Running, Up
+ ** ipipx 0x00C1 -> NoArp, Running, Up
+ */
- IfDescEp->Flags = IfReq.ifr_flags;
+ IfDescEp->Flags = ifa->ifa_flags;
+ // Set the default params for the IF...
+ IfDescEp->state = IF_STATE_DOWNSTREAM;
+ IfDescEp->robustness = DEFAULT_ROBUSTNESS;
+ IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */
+ IfDescEp->ratelimit = DEFAULT_RATELIMIT;
+ IfDescEp->allowednets = NULL;
+ ifp = IfDescEp++;
+ }
+
// Insert the verified subnet as an allowed net...
- IfDescEp->allowednets = (struct SubnetList *)malloc(sizeof(struct SubnetList));
- if(IfDescEp->allowednets == NULL) log(LOG_ERR, 0, "Out of memory !");
+ addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
+ mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
+ subnet = addr & mask;
+
+ net = (struct SubnetList *)malloc(sizeof(struct SubnetList));
+ if(net == NULL) log(LOG_ERR, 0, "Out of memory !");
// Create the network address for the IF..
- IfDescEp->allowednets->next = NULL;
- IfDescEp->allowednets->subnet_mask = mask;
- IfDescEp->allowednets->subnet_addr = subnet;
-
- // Set the default params for the IF...
- IfDescEp->state = IF_STATE_DOWNSTREAM;
- IfDescEp->robustness = DEFAULT_ROBUSTNESS;
- IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */
- IfDescEp->ratelimit = DEFAULT_RATELIMIT;
+ net->next = ifp->allowednets;
+ net->subnet_mask = mask;
+ net->subnet_addr = subnet;
+ ifp->allowednets = net;
-
// Debug log the result...
IF_DEBUG log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s",
- IfDescEp->Name,
- fmtInAdr( FmtBu, IfDescEp->InAdr ),
- IfDescEp->Flags,
+ ifp->Name,
+ fmtInAdr( FmtBu, ifp->InAdr ),
+ ifp->Flags,
inetFmts(subnet,mask, s1));
- IfDescEp++;
}
- }
- close( Sock );
+ }
+ freeifaddrs(ifap);
}
/*

View File

@ -1,82 +0,0 @@
$OpenBSD: patch-igmp_c,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
--- igmp.c.orig Tue May 24 17:49:16 2005
+++ igmp.c Mon Aug 13 15:16:51 2007
@@ -41,8 +41,6 @@
uint32 allhosts_group; /* All hosts addr in net order */
uint32 allrouters_group; /* All hosts addr in net order */
-extern int MRouterFD;
-
/*
* Open and initialize the igmp socket, and fill in the non-changing
* IP header fields in the output packet buffer.
@@ -128,6 +126,7 @@ void acceptIgmp(int recvlen) {
}
else {
struct IfDesc *checkVIF;
+ int downIf = -1;
// Check if the source address matches a valid address on upstream vif.
checkVIF = getIfByIx( upStreamVif );
@@ -141,15 +140,30 @@ void acceptIgmp(int recvlen) {
return;
}
else if(!isAdressValidForIf(checkVIF, src)) {
- log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
- inetFmt(src, s1), inetFmt(dst, s2));
- return;
+ unsigned Ix;
+ struct IfDesc *Dp;
+
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if ((Dp->state == IF_STATE_DOWNSTREAM) &&isAdressValidForIf(Dp, src)) {
+ downIf = Ix;
+ break;
+ }
+ }
+
+ if (downIf == -1) {
+ log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
+ inetFmt(src, s1), inetFmt(dst, s2));
+ return;
+ } else {
+ log(LOG_NOTICE, 0, "The source address %s for group %s, is valid DOWNSTREAM VIF #%d.",
+ inetFmt(src, s1), inetFmt(dst, s2), downIf);
+ }
}
// Activate the route.
- IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to %s",
- inetFmt(src,s1), inetFmt(dst,s2));
- activateRoute(dst, src);
+ IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to %s, downIf %d",
+ inetFmt(src,s1), inetFmt(dst,s2), downIf);
+ activateRoute(dst, src, downIf);
}
@@ -176,9 +190,9 @@ void acceptIgmp(int recvlen) {
return;
}
- log(LOG_NOTICE, 0, "RECV %s from %-15s to %s",
+ log(LOG_NOTICE, 0, "RECV %s from %-15s to %s (ip_hl %d, data %d)",
igmpPacketKind(igmp->igmp_type, igmp->igmp_code),
- inetFmt(src, s1), inetFmt(dst, s2) );
+ inetFmt(src, s1), inetFmt(dst, s2), iphdrlen, ipdatalen);
switch (igmp->igmp_type) {
case IGMP_V1_MEMBERSHIP_REPORT:
@@ -190,12 +204,9 @@ void acceptIgmp(int recvlen) {
acceptLeaveMessage(src, group);
return;
- /*
case IGMP_MEMBERSHIP_QUERY:
//accept_membership_query(src, dst, group, igmp->igmp_code);
return;
-
- */
default:
log(LOG_INFO, 0,

View File

@ -1,86 +0,0 @@
$OpenBSD: patch-igmpproxy_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
--- igmpproxy.c.orig Thu Dec 15 19:50:24 2016
+++ igmpproxy.c Thu Dec 15 19:51:46 2016
@@ -41,8 +41,8 @@
#include "version.h"
#include "build.h"
+#include <sys/sysctl.h>
-
// Constants
static const char Version[] =
"igmpproxy, Version " VERSION ", Build" BUILD "\n"
@@ -80,7 +80,7 @@
* on commandline. The number of commandline arguments, and a
* pointer to the arguments are recieved on the line...
*/
-int main( int ArgCn, const char *ArgVc[] ) {
+int main( int ArgCn, char *ArgVc[] ) {
int debugMode = 0;
@@ -133,6 +133,24 @@
exit(1);
}
+ {
+ int ipmforwarding = 0;
+ int mib[4];
+ size_t len;
+
+ /* multicast IP forwarding must be enabled */
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET;
+ mib[2] = IPPROTO_IP;
+ mib[3] = IPCTL_MFORWARDING;
+ len = sizeof(ipmforwarding);
+ if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1)
+ log(LOG_ERR, 0, "sysctl");
+
+ if (!ipmforwarding)
+ log(LOG_ERR, 0, "multicast IP forwarding not enabled");
+ }
+
// Write debug notice with file path...
IF_DEBUG log(LOG_DEBUG, 0, "Searching for config file at '%s'" , configFilePath);
@@ -155,17 +173,8 @@
if ( ! debugMode ) {
IF_DEBUG log( LOG_DEBUG, 0, "Starting daemon mode.");
-
- // Only daemon goes past this line...
- if (fork()) exit(0);
-
- // Detach deamon from terminal
- if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0
- || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 0, 2 ) < 0
- || setpgrp() < 0
- ) {
+ if ( daemon(1, 0) < 0)
log( LOG_ERR, errno, "failed to detach deamon" );
- }
}
// Go to the main loop.
@@ -218,7 +227,9 @@
int vifcount = 0;
upStreamVif = -1;
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if (config_getinterface(Dp->Name) == NULL)
+ continue;
if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
if(Dp->state == IF_STATE_UPSTREAM) {
@@ -237,7 +248,7 @@
// If there is only one VIF, or no defined upstream VIF, we send an error.
if(vifcount < 2 || upStreamVif < 0) {
- log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream.");
+ log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream. (vifcount %d, upStreamVif %d)", vifcount, upStreamVif);
}
}

View File

@ -1,50 +0,0 @@
$OpenBSD: patch-igmpproxy_conf,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
--- igmpproxy.conf.orig Fri Apr 29 20:27:50 2005
+++ igmpproxy.conf Sat Jan 26 12:05:26 2008
@@ -9,11 +9,11 @@
# If multicast traffic originates outside the
# upstream subnet, the "altnet" option can be
# used in order to define legal multicast sources.
-# (Se example...)
+# (See example...)
#
# The "quickleave" should be used to avoid saturation
# of the upstream link. The option should only
-# be used if it's absolutely nessecary to
+# be used if it's absolutely necessary to
# accurately imitate just one Client.
#
########################################################
@@ -25,22 +25,23 @@ quickleave
##------------------------------------------------------
-## Configuration for eth0 (Upstream Interface)
+## Configuration for em0 (Upstream Interface)
##------------------------------------------------------
-phyint eth0 upstream ratelimit 0 threshold 1
- altnet 10.0.0.0/8
- altnet 192.168.0.0/24
+phyint em0 upstream ratelimit 0 threshold 1
+ altnet 10.0.0.0/8
+# altnet 132.185.0.0/16 # BBC multicast trial
+# altnet 217.0.119.0/24 # T-Home Entertain
+# altnet 193.158.35.0/24 # T-Home Entertain
-
##------------------------------------------------------
-## Configuration for eth1 (Downstream Interface)
+## Configuration for ipw0 (Downstream Interface)
##------------------------------------------------------
-phyint eth1 downstream ratelimit 0 threshold 1
+phyint ipw0 downstream ratelimit 0 threshold 1
##------------------------------------------------------
-## Configuration for eth2 (Disabled Interface)
+## Configuration for lo0 (Disabled Interface)
##------------------------------------------------------
-phyint eth2 disabled
+phyint lo0 disabled

View File

@ -1,37 +0,0 @@
$OpenBSD: patch-mcgroup_c,v 1.1 2016/12/23 13:44:31 rzalamena Exp $
--- mcgroup.c.orig Thu Dec 15 19:48:18 2016
+++ mcgroup.c Mon Dec 19 21:22:07 2016
@@ -49,7 +49,6 @@
CtlReq.imr_interface.s_addr = IfDp->InAdr.s_addr;
{
- char FmtBu[ 32 ];
log( LOG_NOTICE, 0, "%sMcGroup: %s on %s", CmdSt,
inetFmt( mcastaddr, s1 ), IfDp ? IfDp->Name : "<any>" );
}
@@ -58,7 +57,7 @@
Cmd == 'j' ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP,
(void *)&CtlReq, sizeof( CtlReq ) ) )
{
- log( LOG_WARNING, errno, "MRT_%s_MEMBERSHIP failed", Cmd == 'j' ? "ADD" : "DROP" );
+ log( LOG_WARNING, errno, "IP_%s_MEMBERSHIP failed", Cmd == 'j' ? "ADD" : "DROP" );
return 1;
}
@@ -73,6 +72,8 @@
* @return 0 if the function succeeds, 1 if parameters are wrong or the join fails
*/
int joinMcGroup( int UdpSock, struct IfDesc *IfDp, uint32 mcastaddr ) {
+ if (config_getinterface(IfDp->Name) == NULL)
+ return (1);
return joinleave( 'j', UdpSock, IfDp, mcastaddr );
}
@@ -82,5 +83,7 @@
* @return 0 if the function succeeds, 1 if parameters are wrong or the join fails
*/
int leaveMcGroup( int UdpSock, struct IfDesc *IfDp, uint32 mcastaddr ) {
+ if (config_getinterface(IfDp->Name) == NULL)
+ return (1);
return joinleave( 'l', UdpSock, IfDp, mcastaddr );
}

View File

@ -1,53 +0,0 @@
$OpenBSD: patch-mroute-api_c,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
--- mroute-api.c.orig Tue May 24 17:48:33 2005
+++ mroute-api.c Mon Aug 13 15:12:06 2007
@@ -37,7 +37,7 @@
*/
-#define USE_LINUX_IN_H
+//#define USE_LINUX_IN_H
#include "defs.h"
// MAX_MC_VIFS from mclab.h must have same value as MAXVIFS from mroute.h
@@ -47,7 +47,7 @@
// need an IGMP socket as interface for the mrouted API
// - receives the IGMP messages
-int MRouterFD; /* socket for all network I/O */
+int MRouterFD = -1; /* socket for all network I/O */
char *recv_buf; /* input packet buffer */
char *send_buf; /* output packet buffer */
@@ -177,13 +177,14 @@ int addMRoute( struct MRouteDesc *Dp )
log( LOG_NOTICE, 0, "Adding MFC: %s -> %s, InpVIf: %d",
fmtInAdr( FmtBuO, CtlReq.mfcc_origin ),
fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ),
- CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent
+ CtlReq.mfcc_parent
);
}
if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC,
(void *)&CtlReq, sizeof( CtlReq ) ) )
log( LOG_WARNING, errno, "MRT_ADD_MFC" );
+ return (0);
}
/*
@@ -210,13 +211,14 @@ int delMRoute( struct MRouteDesc *Dp )
log( LOG_NOTICE, 0, "Removing MFC: %s -> %s, InpVIf: %d",
fmtInAdr( FmtBuO, CtlReq.mfcc_origin ),
fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ),
- CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent
+ CtlReq.mfcc_parent
);
}
if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC,
(void *)&CtlReq, sizeof( CtlReq ) ) )
log( LOG_WARNING, errno, "MRT_DEL_MFC" );
+ return (0);
}
/*

View File

@ -1,34 +0,0 @@
$OpenBSD: patch-request_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
--- request.c.orig Thu Dec 15 19:50:24 2016
+++ request.c Mon Dec 19 21:06:50 2016
@@ -88,7 +88,7 @@
} else {
// Log the state of the interface the report was recieved on.
- log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.",
+ log(LOG_INFO, 0, "Membership report was recieved on %s. Ignoring.",
sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface");
}
@@ -136,7 +136,8 @@
} else {
// just ignore the leave request...
- IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request.");
+ IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request.",
+ inetFmt(src, s1));
}
}
@@ -184,8 +185,10 @@
int Ix;
// Loop through all downstream vifs...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
+ if (config_getinterface(Dp->Name) == NULL)
+ continue;
if(Dp->state == IF_STATE_DOWNSTREAM) {
// Send the membership query...
sendIgmp(Dp->InAdr.s_addr, allhosts_group,

View File

@ -1,549 +0,0 @@
$OpenBSD: patch-rttable_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
--- rttable.c.orig Thu Dec 15 19:50:24 2016
+++ rttable.c Mon Dec 19 21:22:11 2016
@@ -38,15 +38,22 @@
*/
#include "defs.h"
+#include <sys/queue.h>
+#include <sys/tree.h>
/**
* Routing table structure definition. Double linked list...
*/
+struct Origin {
+ TAILQ_ENTRY(Origin) next;
+ uint32 originAddr;
+ int flood;
+ uint32 pktcnt;
+};
+
struct RouteTable {
- struct RouteTable *nextroute; // Pointer to the next group in line.
- struct RouteTable *prevroute; // Pointer to the previous group in line.
+ RB_ENTRY(RouteTable) entry;
uint32 group; // The group to route
- uint32 originAddr; // The origin adress (only set on activated routes)
uint32 vifBits; // Bits representing recieving VIFs.
// Keeps the upstream membership state...
@@ -56,28 +63,58 @@
uint32 ageVifBits; // Bits representing aging VIFs.
int ageValue; // Downcounter for death.
int ageActivity; // Records any acitivity that notes there are still listeners.
+ TAILQ_HEAD(originhead, Origin) originList; // The origin adresses (non-empty on activated routes)
};
+RB_HEAD(rtabletree, RouteTable) routing_table =
+ RB_INITIALIZER(&routing_table);
-
-// Keeper for the routing table...
-static struct RouteTable *routing_table;
-
// Prototypes
void logRouteTable(char *header);
int internAgeRoute(struct RouteTable* croute);
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *o);
-// Socket for sending join or leave requests.
-int mcGroupSock = 0;
+int rtable_cmp(struct RouteTable *, struct RouteTable *);
+struct RouteTable *rtable_add(struct RouteTable *);
+void rtable_remove(struct RouteTable *);
+RB_GENERATE(rtabletree, RouteTable, entry, rtable_cmp);
+int
+rtable_cmp(struct RouteTable *rt, struct RouteTable *rtn)
+{
+ if (rt->group < rtn->group)
+ return (-1);
+ return (rt->group > rtn->group);
+}
+
+struct RouteTable *
+rtable_add(struct RouteTable *rt)
+{
+ return (RB_INSERT(rtabletree, &routing_table, rt));
+}
+
+void
+rtable_remove(struct RouteTable *rt)
+{
+ struct Origin *o;
+
+ while ((o = TAILQ_FIRST(&rt->originList))) {
+ TAILQ_REMOVE(&rt->originList, o, next);
+ free(o);
+ }
+
+ RB_REMOVE(rtabletree, &routing_table, rt);
+ free(rt);
+}
+
/**
* Function for retrieving the Multicast Group socket.
*/
int getMcGroupSock() {
- if( ! mcGroupSock ) {
- mcGroupSock = openUdpSocket( INADDR_ANY, 0 );;
+ if (MRouterFD < 0) {
+ log(LOG_ERR, errno, "no MRouterFD.");
}
- return mcGroupSock;
+ return MRouterFD;
}
/**
@@ -87,11 +124,8 @@
unsigned Ix;
struct IfDesc *Dp;
- // Clear routing table...
- routing_table = NULL;
-
// Join the all routers group on downstream vifs...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
// If this is a downstream vif, we should join the All routers group...
if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) {
IF_DEBUG log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s",
@@ -159,29 +193,24 @@
* Clear all routes from routing table, and alerts Leaves upstream.
*/
void clearAllRoutes() {
- struct RouteTable *croute, *remainroute;
+ struct RouteTable *croute;
// Loop through all routes...
- for(croute = routing_table; croute; croute = remainroute) {
-
- remainroute = croute->nextroute;
-
+ while ((croute = RB_ROOT(&routing_table)) != NULL) {
// Log the cleanup in debugmode...
IF_DEBUG log(LOG_DEBUG, 0, "Removing route entry for %s",
inetFmt(croute->group, s1));
// Uninstall current route
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
log(LOG_WARNING, 0, "The removal from Kernel failed.");
}
// Send Leave message upstream.
sendJoinLeaveUpstream(croute, 0);
- // Clear memory, and set pointer to next route...
- free(croute);
+ rtable_remove(croute);
}
- routing_table = NULL;
// Send a notice that the routing table is empty...
log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");
@@ -192,15 +221,10 @@
* Route Descriptor.
*/
struct RouteTable *findRoute(uint32 group) {
- struct RouteTable* croute;
+ struct RouteTable key;
- for(croute = routing_table; croute; croute = croute->nextroute) {
- if(croute->group == group) {
- return croute;
- }
- }
-
- return NULL;
+ key.group = group;
+ return (RB_FIND(rtabletree, &routing_table, &key));
}
/**
@@ -212,7 +236,6 @@
struct Config *conf = getCommonConfig();
struct RouteTable* croute;
- int result = 1;
// Sanitycheck the group adress...
if( ! IN_MULTICAST( ntohl(group) )) {
@@ -241,9 +264,7 @@
newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
// Insert the route desc and clear all pointers...
newroute->group = group;
- newroute->originAddr = 0;
- newroute->nextroute = NULL;
- newroute->prevroute = NULL;
+ TAILQ_INIT(&newroute->originList);
// The group is not joined initially.
newroute->upstrState = ROUTESTATE_NOTJOINED;
@@ -260,54 +281,13 @@
BIT_SET(newroute->vifBits, ifx);
}
- // Check if there is a table already....
- if(routing_table == NULL) {
- // No location set, so insert in on the table top.
- routing_table = newroute;
- IF_DEBUG log(LOG_DEBUG, 0, "No routes in table. Insert at beginning.");
- } else {
+ if ((croute = rtable_add(newroute)) != NULL)
+ free(newroute);
+ else {
+ // Set the new route as the current...
+ croute = newroute;
+ }
- IF_DEBUG log(LOG_DEBUG, 0, "Found existing routes. Find insert location.");
-
- // Check if the route could be inserted at the beginning...
- if(routing_table->group > group) {
- IF_DEBUG log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1));
-
- // Insert at beginning...
- newroute->nextroute = routing_table;
- newroute->prevroute = NULL;
- routing_table = newroute;
-
- // If the route has a next node, the previous pointer must be updated.
- if(newroute->nextroute != NULL) {
- newroute->nextroute->prevroute = newroute;
- }
-
- } else {
-
- // Find the location which is closest to the route.
- for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) {
- // Find insert position.
- if(croute->nextroute->group > group) {
- break;
- }
- }
-
- IF_DEBUG log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1));
-
- // Insert after current...
- newroute->nextroute = croute->nextroute;
- newroute->prevroute = croute;
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = newroute;
- }
- croute->nextroute = newroute;
- }
- }
-
- // Set the new route as the current...
- croute = newroute;
-
// Log the cleanup in debugmode...
log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
inetFmt(croute->group, s1),ifx);
@@ -325,10 +305,10 @@
inetFmt(croute->group, s1), ifx);
// If the route is active, it must be reloaded into the Kernel..
- if(croute->originAddr != 0) {
+ if(!TAILQ_EMPTY(&croute->originList)) {
// Update route in kernel...
- if(!internUpdateKernelRoute(croute, 1)) {
+ if(!internUpdateKernelRoute(croute, 1, NULL)) {
log(LOG_WARNING, 0, "The insertion into Kernel failed.");
return 0;
}
@@ -351,7 +331,7 @@
* activated, it's reinstalled in the kernel. If
* the route is activated, no originAddr is needed.
*/
-int activateRoute(uint32 group, uint32 originAddr) {
+int activateRoute(uint32 group, uint32 originAddr, int downIf) {
struct RouteTable* croute;
int result = 0;
@@ -369,21 +349,42 @@
}
if(croute != NULL) {
+ struct Origin *o = NULL;
+ int found = 0;
+
// If the origin address is set, update the route data.
- if(originAddr > 0) {
- if(croute->originAddr > 0 && croute->originAddr!=originAddr) {
- log(LOG_WARNING, 0, "The origin for route %s changed from %s to %s",
- inetFmt(croute->group, s1),
- inetFmt(croute->originAddr, s2),
- inetFmt(originAddr, s3));
- }
- croute->originAddr = originAddr;
- }
+ if(originAddr > 0) {
- // Only update kernel table if there are listeners !
- if(croute->vifBits > 0) {
- result = internUpdateKernelRoute(croute, 1);
- }
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ log(LOG_INFO, 0, "Origin for route %s have %s, new %s",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s2),
+ inetFmt(originAddr, s3));
+ if (o->originAddr==originAddr) {
+ found++;
+ break;
+ }
+ }
+ if (!found) {
+ log(LOG_NOTICE, 0, "New origin for route %s is %s, flood %d",
+ inetFmt(croute->group, s1),
+ inetFmt(originAddr, s3), downIf);
+ o = malloc(sizeof(*o));
+ o->originAddr = originAddr;
+ o->flood = downIf;
+ o->pktcnt = 0;
+ TAILQ_INSERT_TAIL(&croute->originList, o, next);
+ } else {
+ log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt %d",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s3),
+ o->pktcnt);
+ }
+ }
+
+ // Only update kernel table if there are listeners, but flood upstream!
+ if(croute->vifBits > 0 || downIf >= 0)
+ result = internUpdateKernelRoute(croute, 1, o);
}
IF_DEBUG logRouteTable("Activate Route");
@@ -401,11 +402,7 @@
IF_DEBUG log(LOG_DEBUG, 0, "Aging routes in table.");
// Scan all routes...
- for( croute = routing_table; croute != NULL; croute = nroute ) {
-
- // Keep the next route (since current route may be removed)...
- nroute = croute->nextroute;
-
+ RB_FOREACH_SAFE(croute, rtabletree, &routing_table, nroute) {
// Run the aging round algorithm.
if(croute->upstrState != ROUTESTATE_CHECK_LAST_MEMBER) {
// Only age routes if Last member probe is not active...
@@ -443,7 +440,6 @@
* route is not found, or not in this state, 0 is returned.
*/
int lastMemberGroupAge(uint32 group) {
- struct Config *conf = getCommonConfig();
struct RouteTable *croute;
croute = findRoute(group);
@@ -477,7 +473,7 @@
//BIT_ZERO(croute->vifBits);
// Uninstall current route from kernel
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
log(LOG_WARNING, 0, "The removal from Kernel failed.");
result = 0;
}
@@ -489,24 +485,8 @@
sendJoinLeaveUpstream(croute, 0);
}
- // Update pointers...
- if(croute->prevroute == NULL) {
- // Topmost node...
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = NULL;
- }
- routing_table = croute->nextroute;
+ rtable_remove(croute);
- } else {
- croute->prevroute->nextroute = croute->nextroute;
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = croute->prevroute;
- }
- }
- // Free the memory, and set the route to NULL...
- free(croute);
- croute = NULL;
-
IF_DEBUG logRouteTable("Remove route");
return result;
@@ -551,6 +531,36 @@
}
}
+ {
+ struct Origin *o, *nxt;
+ struct sioc_sg_req sg_req;
+
+ sg_req.grp.s_addr = croute->group;
+ for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) {
+ nxt = TAILQ_NEXT(o, next);
+ sg_req.src.s_addr = o->originAddr;
+ if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) {
+ log(LOG_WARNING, errno, "%s (%s %s)",
+ "age_table_entry: SIOCGETSGCNT failing for",
+ inetFmt(o->originAddr, s1),
+ inetFmt(croute->group, s2));
+ /* Make sure it gets deleted below */
+ sg_req.pktcnt = o->pktcnt;
+ }
+ log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d",
+ inetFmt(o->originAddr, s1), inetFmt(croute->group, s2),
+ o->pktcnt, sg_req.pktcnt);
+ if (sg_req.pktcnt == o->pktcnt) {
+ /* no traffic, remove from kernel cache */
+ internUpdateKernelRoute(croute, 0, o);
+ TAILQ_REMOVE(&croute->originList, o, next);
+ free(o);
+ } else {
+ o->pktcnt = sg_req.pktcnt;
+ }
+ }
+ }
+
// If the aging counter has reached zero, its time for updating...
if(croute->ageValue == 0) {
// Check for activity in the aging process,
@@ -560,7 +570,7 @@
inetFmt(croute->group,s1));
// Just update the routing settings in kernel...
- internUpdateKernelRoute(croute, 1);
+ internUpdateKernelRoute(croute, 1, NULL);
// We append the activity counter to the age, and continue...
croute->ageValue = croute->ageActivity;
@@ -586,34 +596,58 @@
/**
* Updates the Kernel routing table. If activate is 1, the route
* is (re-)activated. If activate is false, the route is removed.
+* if 'origin' is given, only the route with 'origin' will be
+* updated, otherwise all MFC routes for the group will updated.
*/
-int internUpdateKernelRoute(struct RouteTable *route, int activate) {
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *origin) {
struct MRouteDesc mrDesc;
struct IfDesc *Dp;
unsigned Ix;
+ struct Origin *o;
- if(route->originAddr>0) {
+ if (TAILQ_EMPTY(&route->originList)) {
+ log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
+ return 1;
+ }
+ TAILQ_FOREACH(o, &route->originList, next) {
+ if (origin && origin != o)
+ continue;
// Build route descriptor from table entry...
// Set the source address and group address...
mrDesc.McAdr.s_addr = route->group;
- mrDesc.OriginAdr.s_addr = route->originAddr;
+ mrDesc.OriginAdr.s_addr = o->originAddr;
// clear output interfaces
memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
- IF_DEBUG log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
+ IF_DEBUG log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", inetFmt(o->originAddr, s1), route->vifBits);
// Set the TTL's for the route descriptor...
- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
- if(Dp->state == IF_STATE_UPSTREAM) {
- //IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index);
- mrDesc.InVif = Dp->index;
- }
- else if(BIT_TST(route->vifBits, Dp->index)) {
- IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
- mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
- }
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if (o->flood >= 0) {
+ if(Ix == o->flood) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Identified Input VIF #%d as DOWNSTREAM.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(Dp->state == IF_STATE_UPSTREAM) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ } else {
+ if(Dp->state == IF_STATE_UPSTREAM) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ }
}
// Do the actual Kernel route update...
@@ -625,9 +659,6 @@
// Delete the route from Kernel...
delMRoute( &mrDesc );
}
-
- } else {
- log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
}
return 1;
@@ -639,29 +670,27 @@
*/
void logRouteTable(char *header) {
IF_DEBUG {
- struct RouteTable* croute = routing_table;
+ struct RouteTable* croute = RB_ROOT(&routing_table);
unsigned rcount = 0;
log(LOG_DEBUG, 0, "\nCurrent routing table (%s);\n-----------------------------------------------------\n", header);
if(croute==NULL) {
log(LOG_DEBUG, 0, "No routes in table...");
} else {
- do {
- /*
- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, Prev: 0x%08x, T: 0x%08x, Next: 0x%08x",
- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
- croute->ageValue,(croute->originAddr>0?"A":"I"),
- croute->prevroute, croute, croute->nextroute);
- */
- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x",
- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
- croute->ageValue,(croute->originAddr>0?"A":"I"),
- croute->vifBits);
-
- croute = croute->nextroute;
-
+ RB_FOREACH(croute, rtabletree, &routing_table) {
+ log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x",
+ rcount, inetFmt(croute->group, s2),
+ croute->ageValue,(TAILQ_EMPTY(&croute->originList)?"I":"A"),
+ croute->vifBits);
+ {
+ struct Origin *o;
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d pktcnt %d",
+ rcount, inetFmt(o->originAddr, s1), o->flood, o->pktcnt);
+ }
+ }
rcount++;
- } while ( croute != NULL );
+ }
}
log(LOG_DEBUG, 0, "\n-----------------------------------------------------\n");

View File

@ -0,0 +1,71 @@
$OpenBSD: patch-src_config_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/config.c
--- src/config.c.orig
+++ src/config.c
@@ -393,33 +393,19 @@ struct vifconfig *parsePhyintToken(void) {
*/
struct SubnetList *parseSubnetAddress(char *addrstr) {
struct SubnetList *tmpSubnet;
- char *tmpStr;
uint32_t addr = 0x00000000;
uint32_t mask = 0xFFFFFFFF;
+ int bitcnt;
- // First get the network part of the address...
- tmpStr = strtok(addrstr, "/");
- addr = inet_addr(tmpStr);
+ bitcnt = inet_net_pton(AF_INET, addrstr, &addr, sizeof(addr));
+ if(bitcnt<0) {
+ my_log(LOG_WARNING, 0, "Unable to parse address token '%s'.",addrstr);
+ return NULL;
+ } else if(bitcnt>0)
+ mask <<= (32 - bitcnt);
+ else
+ mask = 0;
- tmpStr = strtok(NULL, "/");
- if(tmpStr != NULL) {
- int bitcnt = atoi(tmpStr);
- if(bitcnt < 0 || bitcnt > 32) {
- my_log(LOG_WARNING, 0, "The bits part of the address is invalid : %d.",tmpStr);
- return NULL;
- }
-
- if (bitcnt == 0)
- mask = 0;
- else
- mask <<= (32 - bitcnt);
- }
-
- if(addr == (uint32_t)-1) {
- my_log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr);
- return NULL;
- }
-
tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList));
tmpSubnet->subnet_addr = addr;
tmpSubnet->subnet_mask = ntohl(mask);
@@ -429,4 +415,22 @@ struct SubnetList *parseSubnetAddress(char *addrstr) {
inetFmts(tmpSubnet->subnet_addr, tmpSubnet->subnet_mask,s1));
return tmpSubnet;
+}
+
+struct vifconfig *
+config_getinterface(const char *ifname)
+{
+ struct vifconfig *vc;
+
+ if (vifconf == NULL)
+ return (NULL);
+
+ for (vc = vifconf; vc; vc = vc->next) {
+ if (strcmp(vc->name, ifname))
+ continue;
+
+ return (vc);
+ }
+
+ return (NULL);
}

View File

@ -0,0 +1,199 @@
$OpenBSD: patch-src_ifvc_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/ifvc.c
--- src/ifvc.c.orig
+++ src/ifvc.c
@@ -33,6 +33,7 @@
*/
#include "igmpproxy.h"
+#include <ifaddrs.h>
/* We need a temporary copy to not break strict aliasing rules */
static inline uint32_t s_addr_from_sockaddr(const struct sockaddr *addr) {
@@ -201,129 +202,93 @@ void rebuildIfVc () {
**
*/
void buildIfVc(void) {
- struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] ) ];
- struct ifreq *IfEp;
- struct Config *config = getCommonConfig();
+ struct ifaddrs *ifap, *ifa;
+ struct IfDesc *ifp;
+ struct SubnetList *net;
- int Sock;
+ if (getifaddrs(&ifap) < 0)
+ my_log( LOG_ERR, errno, "getifaddrs" );
- if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
- my_log( LOG_ERR, errno, "RAW socket open" );
-
- /* get If vector
- */
- {
- struct ifconf IoCtlReq;
-
- IoCtlReq.ifc_buf = (void *)IfVc;
- IoCtlReq.ifc_len = sizeof( IfVc );
-
- if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
- my_log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );
-
- IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);
- }
-
/* loop over interfaces and copy interface info to IfDescVc
*/
{
- struct ifreq *IfPt, *IfNext;
-
// Temp keepers of interface params...
uint32_t addr, subnet, mask;
- for ( IfPt = IfVc; IfPt < IfEp; IfPt = IfNext ) {
- struct ifreq IfReq;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
char FmtBu[ 32 ];
- IfNext = (struct ifreq *)((char *)&IfPt->ifr_addr +
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- IfPt->ifr_addr.sa_len
-#else
- sizeof(struct sockaddr_in)
-#endif
- );
- if (IfNext < IfPt + 1)
- IfNext = IfPt + 1;
+ if (IfDescEp >= &IfDescVc[ MAX_IF ]) {
+ my_log(LOG_WARNING, 0, "Too many interfaces, skipping %d", ifa->ifa_name);
+ continue;
+ }
- strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name ) );
+ /* ignore non-IP interfaces
+ */
+ if ( ifa->ifa_addr->sa_family != AF_INET )
+ continue;
- // Currently don't set any allowed nets...
- //IfDescEp->allowednets = NULL;
+ if ((ifp = getIfByName(ifa->ifa_name)) == NULL) {
+ if (config_getinterface(ifa->ifa_name) == NULL)
+ continue;
- // Set the index to -1 by default.
- IfDescEp->index = (unsigned int)-1;
+ strlcpy( IfDescEp->Name, ifa->ifa_name, sizeof( IfDescEp->Name ) );
- /* don't retrieve more info for non-IP interfaces
- */
- if ( IfPt->ifr_addr.sa_family != AF_INET ) {
- IfDescEp->InAdr.s_addr = 0; /* mark as non-IP interface */
- IfDescEp++;
- continue;
- }
+ my_log(LOG_DEBUG, 0, "Adding physical index value of IF '%s': %d",
+ IfDescEp->Name, if_nametoindex(IfDescEp->Name));
- // Get the interface adress...
- IfDescEp->InAdr.s_addr = s_addr_from_sockaddr(&IfPt->ifr_addr);
- addr = IfDescEp->InAdr.s_addr;
+ // Set the index to -1 by default.
+ IfDescEp->index = -1;
- memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name ) );
+ // Get the interface adress...
+ IfDescEp->InAdr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
- // Get the subnet mask...
- if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
- my_log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", IfReq.ifr_name);
- mask = s_addr_from_sockaddr(&IfReq.ifr_addr); // Do not use ifr_netmask as it is not available on freebsd
- subnet = addr & mask;
+ /* get if flags
+ **
+ ** typical flags:
+ ** lo 0x0049 -> Running, Loopback, Up
+ ** ethx 0x1043 -> Multicast, Running, Broadcast, Up
+ ** ipppx 0x0091 -> NoArp, PointToPoint, Up
+ ** grex 0x00C1 -> NoArp, Running, Up
+ ** ipipx 0x00C1 -> NoArp, Running, Up
+ */
- /* get if flags
- **
- ** typical flags:
- ** lo 0x0049 -> Running, Loopback, Up
- ** ethx 0x1043 -> Multicast, Running, Broadcast, Up
- ** ipppx 0x0091 -> NoArp, PointToPoint, Up
- ** grex 0x00C1 -> NoArp, Running, Up
- ** ipipx 0x00C1 -> NoArp, Running, Up
- */
- if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
- my_log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );
+ IfDescEp->Flags = ifa->ifa_flags;
- IfDescEp->Flags = IfReq.ifr_flags;
+ // Set the default params for the IF...
+ IfDescEp->state = IF_STATE_DOWNSTREAM;
+ IfDescEp->robustness = DEFAULT_ROBUSTNESS;
+ IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */
+ IfDescEp->ratelimit = DEFAULT_RATELIMIT;
+ IfDescEp->allowednets = NULL;
+ ifp = IfDescEp++;
+ }
- // aimwang: when pppx get dstaddr for use
- if (0x10d1 == IfDescEp->Flags)
- {
- if ( ioctl( Sock, SIOCGIFDSTADDR, &IfReq ) < 0 )
- my_log(LOG_ERR, errno, "ioctl SIOCGIFDSTADDR for %s", IfReq.ifr_name);
- addr = s_addr_from_sockaddr(&IfReq.ifr_dstaddr);
- subnet = addr & mask;
- }
// Insert the verified subnet as an allowed net...
- IfDescEp->allowednets = (struct SubnetList *)malloc(sizeof(struct SubnetList));
- if(IfDescEp->allowednets == NULL) my_log(LOG_ERR, 0, "Out of memory !");
+ addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
+ mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr;
+ subnet = addr & mask;
- // Create the network address for the IF..
- IfDescEp->allowednets->next = NULL;
- IfDescEp->allowednets->subnet_mask = mask;
- IfDescEp->allowednets->subnet_addr = subnet;
+ net = (struct SubnetList *)malloc(sizeof(struct SubnetList));
+ if(net == NULL)
+ my_log(LOG_ERR, 0, "Out of memory !");
- // Set the default params for the IF...
- IfDescEp->state = config->defaultInterfaceState;
- IfDescEp->robustness = DEFAULT_ROBUSTNESS;
- IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */
- IfDescEp->ratelimit = DEFAULT_RATELIMIT;
+ net->next = ifp->allowednets;
+ net->subnet_mask = mask;
+ net->subnet_addr = subnet;
+ ifp->allowednets = net;
// Debug log the result...
my_log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s",
- IfDescEp->Name,
- fmtInAdr( FmtBu, IfDescEp->InAdr ),
- IfDescEp->Flags,
+ ifp->Name,
+ fmtInAdr( FmtBu, ifp->InAdr ),
+ ifp->Flags,
inetFmts(subnet,mask, s1));
- IfDescEp++;
}
}
-
- close( Sock );
+ freeifaddrs(ifap);
}
/*

View File

@ -0,0 +1,65 @@
$OpenBSD: patch-src_igmp_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/igmp.c
--- src/igmp.c.orig
+++ src/igmp.c
@@ -139,6 +139,7 @@ void acceptIgmp(int recvlen) {
}
else {
struct IfDesc *checkVIF;
+ int downIf = -1;
for(i=0; i<MAX_UPS_VIFS; i++)
{
@@ -156,20 +157,29 @@ void acceptIgmp(int recvlen) {
return;
}
else if(!isAdressValidForIf(checkVIF, src)) {
- struct IfDesc *downVIF = getIfByAddress(src);
- if (downVIF && downVIF->state & IF_STATE_DOWNSTREAM) {
- my_log(LOG_NOTICE, 0, "The source address %s for group %s is from downstream VIF[%d]. Ignoring.",
- inetFmt(src, s1), inetFmt(dst, s2), i);
+ unsigned Ix;
+ struct IfDesc *Dp;
+
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if ((Dp->state == IF_STATE_DOWNSTREAM) && isAdressValidForIf(Dp, src)) {
+ downIf = Ix;
+ break;
+ }
+ }
+
+ if (downIf == -1) {
+ my_log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.",
+ inetFmt(src, s1), inetFmt(dst, s2));
+ return;
} else {
- my_log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF[%d].",
- inetFmt(src, s1), inetFmt(dst, s2), i);
+ my_log(LOG_NOTICE, 0, "The source address %s for group %s, is valid DOWNSTREAM VIF #%d.",
+ inetFmt(src, s1), inetFmt(dst, s2), downIf);
}
} else {
// Activate the route.
- int vifindex = checkVIF->index;
- my_log(LOG_DEBUG, 0, "Route activate request from %s to %s on VIF[%d]",
- inetFmt(src,s1), inetFmt(dst,s2), vifindex);
- activateRoute(dst, src, vifindex);
+ my_log(LOG_DEBUG, 0, "Route activate request from %s to %s, downIf %d",
+ inetFmt(src,s1), inetFmt(dst,s2), downIf);
+ activateRoute(dst, src, downIf);
i = MAX_UPS_VIFS;
}
} else {
@@ -199,9 +209,9 @@ void acceptIgmp(int recvlen) {
return;
}
- my_log(LOG_NOTICE, 0, "RECV %s from %-15s to %s",
+ my_log(LOG_NOTICE, 0, "RECV %s from %-15s to %s (ip_hl %d, data %d)",
igmpPacketKind(igmp->igmp_type, igmp->igmp_code),
- inetFmt(src, s1), inetFmt(dst, s2) );
+ inetFmt(src, s1), inetFmt(dst, s2), iphdrlen, ipdatalen);
switch (igmp->igmp_type) {
case IGMP_V1_MEMBERSHIP_REPORT:

View File

@ -0,0 +1,74 @@
$OpenBSD: patch-src_igmpproxy_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/igmpproxy.c
--- src/igmpproxy.c.orig
+++ src/igmpproxy.c
@@ -37,13 +37,10 @@
* February 2005 - Johnny Egeland
*/
-/* getopt() and clock_getime() */
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200112L
-#endif
-
#include "igmpproxy.h"
+#include <sys/sysctl.h>
+
static const char Usage[] =
"Usage: igmpproxy [-h] [-n] [-d] [-v [-v]] <configfile>\n"
"\n"
@@ -123,6 +120,25 @@ int main( int ArgCn, char *ArgVc[] ) {
openlog("igmpproxy", LOG_PID, LOG_USER);
+ {
+ int ipmforwarding = 0;
+ int mib[4];
+ size_t len;
+
+ /* multicast IP forwarding must be enabled */
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET;
+ mib[2] = IPPROTO_IP;
+ mib[3] = IPCTL_MFORWARDING;
+ len = sizeof(ipmforwarding);
+ if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1)
+ my_log(LOG_ERR, 0, "sysctl");
+
+ if (!ipmforwarding)
+ my_log(LOG_ERR, 0, "multicast IP forwarding not enabled");
+ }
+
+
// Write debug notice with file path...
my_log(LOG_DEBUG, 0, "Searching for config file at '%s'" , configFilePath);
@@ -142,16 +158,8 @@ int main( int ArgCn, char *ArgVc[] ) {
if ( !NotAsDaemon ) {
- // Only daemon goes past this line...
- if (fork()) exit(0);
-
- // Detach daemon from terminal
- if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0
- || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 0, 2 ) < 0
- || setpgid( 0, 0 ) < 0
- ) {
+ if ( daemon(1, 0 ) < 0 )
my_log( LOG_ERR, errno, "failed to detach daemon" );
- }
}
// Go to the main loop.
@@ -207,6 +215,8 @@ int igmpProxyInit(void) {
}
for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
+ if (config_getinterface(Dp->Name) == NULL)
+ continue;
if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
if(Dp->state == IF_STATE_UPSTREAM) {

View File

@ -0,0 +1,30 @@
$OpenBSD: patch-src_igmpproxy_h,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/igmpproxy.h
--- src/igmpproxy.h.orig
+++ src/igmpproxy.h
@@ -36,7 +36,6 @@
*/
#include "config.h"
-#include "os.h"
#include <errno.h>
#include <stdarg.h>
@@ -60,6 +59,8 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include "os.h"
+
/*
* Limit on length of route data
*/
@@ -218,6 +219,7 @@ int getVifIx( struct IfDesc *IfDp );
int loadConfig(char *configFile);
void configureVifs(void);
struct Config *getCommonConfig(void);
+struct vifconfig *config_getinterface(const char *ifname);
/* igmp.c
*/

View File

@ -0,0 +1,25 @@
$OpenBSD: patch-src_kern_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/kern.c
--- src/kern.c.orig
+++ src/kern.c
@@ -114,6 +114,9 @@ void k_set_if(uint32_t ifa) {
void k_join(struct IfDesc *ifd, uint32_t grp) {
struct ip_mreq mreq;
+ if (config_getinterface(ifd->Name) == NULL)
+ return;
+
mreq.imr_multiaddr.s_addr = grp;
mreq.imr_interface.s_addr = ifd->InAdr.s_addr;
@@ -135,6 +138,9 @@ void k_join(struct IfDesc *ifd, uint32_t grp) {
void k_leave(struct IfDesc *ifd, uint32_t grp) {
struct ip_mreq mreq;
+
+ if (config_getinterface(ifd->Name) == NULL)
+ return;
mreq.imr_multiaddr.s_addr = grp;
mreq.imr_interface.s_addr = ifd->InAdr.s_addr;

View File

@ -0,0 +1,40 @@
$OpenBSD: patch-src_os-openbsd_h,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/os-openbsd.h
--- src/os-openbsd.h.orig
+++ src/os-openbsd.h
@@ -1,16 +1,34 @@
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
#include <netinet/in_systm.h>
#include <netinet/ip_mroute.h>
#include <netinet/ip.h>
#include <netinet/igmp.h>
+
+#ifndef IGMP_MEMBERSHIP_QUERY
#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
+#endif
+#ifndef IGMP_V1_MEMBERSHIP_REPORT
#define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT
+#endif
+#ifndef IGMP_V2_MEMBERSHIP_REPORT
#define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT
+#endif
+#ifndef IGMP_V3_MEMBERSHIP_REPORT
#define IGMP_V3_MEMBERSHIP_REPORT 0x22
+#endif
+#ifndef IGMP_V2_LEAVE_GROUP
#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
+#endif
+#ifndef INADDR_ALLRTRS_GROUP
#define INADDR_ALLRTRS_GROUP INADDR_ALLROUTERS_GROUP
+#endif
+#ifndef INADDR_ALLIGMPV3_GROUP
#define INADDR_ALLIGMPV3_GROUP ((in_addr_t) 0xe0000016)
+#endif
static inline unsigned short ip_data_len(const struct ip *ip)
{

View File

@ -0,0 +1,14 @@
$OpenBSD: patch-src_request_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/request.c
--- src/request.c.orig
+++ src/request.c
@@ -183,6 +183,8 @@ void sendGroupSpecificMemberQuery(void *argument) {
// Loop through all downstream interfaces
for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
+ if (config_getinterface(Dp->Name) == NULL)
+ continue;
if(Dp->state == IF_STATE_DOWNSTREAM) {
// Is that interface used in the group?
if (interfaceInRoute(gvDesc->group ,Dp->index)) {

View File

@ -0,0 +1,537 @@
$OpenBSD: patch-src_rttable_c,v 1.1 2021/01/12 17:59:49 sthen Exp $
Index: src/rttable.c
--- src/rttable.c.orig
+++ src/rttable.c
@@ -39,17 +39,23 @@
*/
#include "igmpproxy.h"
+#include <sys/queue.h>
+#include <sys/tree.h>
#define MAX_ORIGINS 4
/**
* Routing table structure definition. Double linked list...
*/
+struct Origin {
+ TAILQ_ENTRY(Origin) next;
+ uint32_t originAddr;
+ int flood;
+ uint32_t pktcnt;
+};
struct RouteTable {
- struct RouteTable *nextroute; // Pointer to the next group in line.
- struct RouteTable *prevroute; // Pointer to the previous group in line.
+ RB_ENTRY(RouteTable) entry;
uint32_t group; // The group to route
- uint32_t originAddrs[MAX_ORIGINS]; // The origin adresses (only set on activated routes)
uint32_t vifBits; // Bits representing recieving VIFs.
// Keeps the upstream membership state...
@@ -60,22 +66,54 @@ struct RouteTable {
uint32_t ageVifBits; // Bits representing aging VIFs.
int ageValue; // Downcounter for death.
int ageActivity; // Records any acitivity that notes there are still listeners.
+ TAILQ_HEAD(originhead, Origin) originList; // The origin adresses (non-empty on activated routes)
// Keeps downstream hosts information
uint32_t downstreamHostsHashSeed;
uint8_t downstreamHostsHashTable[];
};
+RB_HEAD(rtabletree, RouteTable) routing_table =
+ RB_INITIALIZER(&routing_table);
-
-// Keeper for the routing table...
-static struct RouteTable *routing_table;
-
// Prototypes
void logRouteTable(const char *header);
int internAgeRoute(struct RouteTable *croute);
-int internUpdateKernelRoute(struct RouteTable *route, int activate);
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *);
+int rtable_cmp(struct RouteTable *, struct RouteTable *);
+struct RouteTable *rtable_add(struct RouteTable *);
+void rtable_remove(struct RouteTable *);
+RB_GENERATE(rtabletree, RouteTable, entry, rtable_cmp);
+int
+rtable_cmp(struct RouteTable *rt, struct RouteTable *rtn)
+{
+ if (rt->group < rtn->group)
+ return (-1);
+
+ return (rt->group > rtn->group);
+}
+
+struct RouteTable *
+rtable_add(struct RouteTable *rt)
+{
+ return (RB_INSERT(rtabletree, &routing_table, rt));
+}
+
+void
+rtable_remove(struct RouteTable *rt)
+{
+ struct Origin *o;
+
+ while ((o = TAILQ_FIRST(&rt->originList))) {
+ TAILQ_REMOVE(&rt->originList, o, next);
+ free(o);
+ }
+
+ RB_REMOVE(rtabletree, &routing_table, rt);
+ free(rt);
+}
+
/**
* Functions for downstream hosts hash table
*/
@@ -120,9 +158,6 @@ void initRouteTable(void) {
unsigned Ix;
struct IfDesc *Dp;
- // Clear routing table...
- routing_table = NULL;
-
// Join the all routers group on downstream vifs...
for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
// If this is a downstream vif, we should join the All routers group...
@@ -213,29 +248,24 @@ static void sendJoinLeaveUpstream(struct RouteTable* r
* Clear all routes from routing table, and alerts Leaves upstream.
*/
void clearAllRoutes(void) {
- struct RouteTable *croute, *remainroute;
+ struct RouteTable *croute;
// Loop through all routes...
- for(croute = routing_table; croute; croute = remainroute) {
-
- remainroute = croute->nextroute;
-
+ while ((croute = RB_ROOT(&routing_table)) != NULL) {
// Log the cleanup in debugmode...
my_log(LOG_DEBUG, 0, "Removing route entry for %s",
inetFmt(croute->group, s1));
// Uninstall current route
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
}
// Send Leave message upstream.
sendJoinLeaveUpstream(croute, 0);
- // Clear memory, and set pointer to next route...
- free(croute);
+ rtable_remove(croute);
}
- routing_table = NULL;
// Send a notice that the routing table is empty...
my_log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");
@@ -246,15 +276,10 @@ void clearAllRoutes(void) {
* Route Descriptor.
*/
static struct RouteTable *findRoute(uint32_t group) {
- struct RouteTable* croute;
+ struct RouteTable key;
- for(croute = routing_table; croute; croute = croute->nextroute) {
- if(croute->group == group) {
- return croute;
- }
- }
-
- return NULL;
+ key.group = group;
+ return (RB_FIND(rtabletree, &routing_table, &key));
}
/**
@@ -293,10 +318,8 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable) + (conf->fastUpstreamLeave ? conf->downstreamHostsHashTableSize : 0));
// Insert the route desc and clear all pointers...
newroute->group = group;
- memset(newroute->originAddrs, 0, MAX_ORIGINS * sizeof(newroute->originAddrs[0]));
- newroute->nextroute = NULL;
- newroute->prevroute = NULL;
newroute->upstrVif = -1;
+ TAILQ_INIT(&newroute->originList);
if(conf->fastUpstreamLeave) {
// Init downstream hosts bit hash table
@@ -321,54 +344,13 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
BIT_SET(newroute->vifBits, ifx);
}
- // Check if there is a table already....
- if(routing_table == NULL) {
- // No location set, so insert in on the table top.
- routing_table = newroute;
- my_log(LOG_DEBUG, 0, "No routes in table. Insert at beginning.");
- } else {
-
- my_log(LOG_DEBUG, 0, "Found existing routes. Find insert location.");
-
- // Check if the route could be inserted at the beginning...
- if(routing_table->group > group) {
- my_log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1));
-
- // Insert at beginning...
- newroute->nextroute = routing_table;
- newroute->prevroute = NULL;
- routing_table = newroute;
-
- // If the route has a next node, the previous pointer must be updated.
- if(newroute->nextroute != NULL) {
- newroute->nextroute->prevroute = newroute;
- }
-
- } else {
-
- // Find the location which is closest to the route.
- for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) {
- // Find insert position.
- if(croute->nextroute->group > group) {
- break;
- }
- }
-
- my_log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1));
-
- // Insert after current...
- newroute->nextroute = croute->nextroute;
- newroute->prevroute = croute;
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = newroute;
- }
- croute->nextroute = newroute;
- }
+ if ((croute = rtable_add(newroute)) != NULL)
+ free(newroute);
+ else {
+ // Set the new route as the current...
+ croute = newroute;
}
- // Set the new route as the current...
- croute = newroute;
-
// Log the cleanup in debugmode...
my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
inetFmt(croute->group, s1),ifx);
@@ -391,7 +373,7 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
inetFmt(croute->group, s1), ifx);
// Update route in kernel...
- if(!internUpdateKernelRoute(croute, 1)) {
+ if(!internUpdateKernelRoute(croute, 1, NULL)) {
my_log(LOG_WARNING, 0, "The insertion into Kernel failed.");
return 0;
}
@@ -413,7 +395,7 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
* activated, it's reinstalled in the kernel. If
* the route is activated, no originAddr is needed.
*/
-int activateRoute(uint32_t group, uint32_t originAddr, int upstrVif) {
+int activateRoute(uint32_t group, uint32_t originAddr, int downIf) {
struct RouteTable* croute;
int result = 0;
@@ -432,43 +414,37 @@ int activateRoute(uint32_t group, uint32_t originAddr,
}
if(croute != NULL) {
+ struct Origin *o = NULL;
+ int found = 0;
+
// If the origin address is set, update the route data.
if(originAddr > 0) {
- // find this origin, or an unused slot
- int i;
- for (i = 0; i < MAX_ORIGINS; i++) {
- // unused slots are at the bottom, so we can't miss this origin
- if (croute->originAddrs[i] == originAddr || croute->originAddrs[i] == 0) {
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ my_log(LOG_INFO, 0, "Origin for route %s have %s, new %s",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s2),
+ inetFmt(originAddr, s3));
+ if (o->originAddr==originAddr) {
+ found++;
break;
}
}
-
- if (i == MAX_ORIGINS) {
- i = MAX_ORIGINS - 1;
-
- my_log(LOG_WARNING, 0, "Too many origins for route %s; replacing %s with %s",
+ if (!found) {
+ my_log(LOG_NOTICE, 0, "New origin for route %s is %s, flood %d",
inetFmt(croute->group, s1),
- inetFmt(croute->originAddrs[i], s2),
- inetFmt(originAddr, s3));
+ inetFmt(originAddr, s3), downIf);
+ o = malloc(sizeof(*o));
+ o->originAddr = originAddr;
+ o->flood = downIf;
+ o->pktcnt = 0;
+ TAILQ_INSERT_TAIL(&croute->originList, o, next);
+ } else {
+ my_log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt %d",
+ inetFmt(croute->group, s1),
+ inetFmt(o->originAddr, s3),
+ o->pktcnt);
}
-
- // set origin
- croute->originAddrs[i] = originAddr;
-
- // move it to the top
- while (i > 0) {
- uint32_t t = croute->originAddrs[i - 1];
- croute->originAddrs[i - 1] = croute->originAddrs[i];
- croute->originAddrs[i] = t;
- i--;
- }
}
- croute->upstrVif = upstrVif;
-
- // Only update kernel table if there are listeners !
- if(croute->vifBits > 0) {
- result = internUpdateKernelRoute(croute, 1);
- }
}
logRouteTable("Activate Route");
@@ -485,12 +461,7 @@ void ageActiveRoutes(void) {
my_log(LOG_DEBUG, 0, "Aging routes in table.");
- // Scan all routes...
- for( croute = routing_table; croute != NULL; croute = nroute ) {
-
- // Keep the next route (since current route may be removed)...
- nroute = croute->nextroute;
-
+ RB_FOREACH_SAFE(croute, rtabletree, &routing_table, nroute) {
// Run the aging round algorithm.
if(croute->upstrState != ROUTESTATE_CHECK_LAST_MEMBER) {
// Only age routes if Last member probe is not active...
@@ -602,7 +573,7 @@ static int removeRoute(struct RouteTable* croute) {
//BIT_ZERO(croute->vifBits);
// Uninstall current route from kernel
- if(!internUpdateKernelRoute(croute, 0)) {
+ if(!internUpdateKernelRoute(croute, 0, NULL)) {
my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
result = 0;
}
@@ -614,24 +585,8 @@ static int removeRoute(struct RouteTable* croute) {
sendJoinLeaveUpstream(croute, 0);
}
- // Update pointers...
- if(croute->prevroute == NULL) {
- // Topmost node...
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = NULL;
- }
- routing_table = croute->nextroute;
+ rtable_remove(croute);
- } else {
- croute->prevroute->nextroute = croute->nextroute;
- if(croute->nextroute != NULL) {
- croute->nextroute->prevroute = croute->prevroute;
- }
- }
- // Free the memory, and set the route to NULL...
- free(croute);
- croute = NULL;
-
logRouteTable("Remove route");
return result;
@@ -676,6 +631,37 @@ int internAgeRoute(struct RouteTable* croute) {
}
}
+ {
+ struct Origin *o, *nxt;
+ struct sioc_sg_req sg_req;
+
+ sg_req.grp.s_addr = croute->group;
+ for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) {
+ nxt = TAILQ_NEXT(o, next);
+ sg_req.src.s_addr = o->originAddr;
+ if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) {
+ my_log(LOG_WARNING, errno, "%s (%s %s)",
+ "age_table_entry: SIOCGETSGCNT failing for",
+ inetFmt(o->originAddr, s1),
+ inetFmt(croute->group, s2));
+ /* Make sure it gets deleted below */
+ sg_req.pktcnt = o->pktcnt;
+ }
+ my_log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d",
+ inetFmt(o->originAddr, s1), inetFmt(croute->group, s2),
+ o->pktcnt, sg_req.pktcnt);
+ if (sg_req.pktcnt == o->pktcnt) {
+ /* no traffic, remove from kernel cache */
+ internUpdateKernelRoute(croute, 0, o);
+ TAILQ_REMOVE(&croute->originList, o, next);
+ free(o);
+ } else {
+ o->pktcnt = sg_req.pktcnt;
+ }
+ }
+ }
+
+
// If the aging counter has reached zero, its time for updating...
if(croute->ageValue == 0) {
// Check for activity in the aging process,
@@ -685,7 +671,7 @@ int internAgeRoute(struct RouteTable* croute) {
inetFmt(croute->group,s1));
// Just update the routing settings in kernel...
- internUpdateKernelRoute(croute, 1);
+ internUpdateKernelRoute(croute, 1, NULL);
// We append the activity counter to the age, and continue...
croute->ageValue = croute->ageActivity;
@@ -711,39 +697,61 @@ int internAgeRoute(struct RouteTable* croute) {
/**
* Updates the Kernel routing table. If activate is 1, the route
* is (re-)activated. If activate is false, the route is removed.
+* if 'origin' is given, only the route with 'origin' will be
+* updated, otherwise all MFC routes for the group will updated.
*/
-int internUpdateKernelRoute(struct RouteTable *route, int activate) {
+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *origin) {
struct MRouteDesc mrDesc;
struct IfDesc *Dp;
unsigned Ix;
- int i;
+ struct Origin *o;
- for (i = 0; i < MAX_ORIGINS; i++) {
- if (route->originAddrs[i] == 0 || route->upstrVif == -1) {
+ if (TAILQ_EMPTY(&route->originList)) {
+ my_log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
+ return 1;
+ }
+
+ TAILQ_FOREACH(o, &route->originList, next) {
+ if (origin && origin != o)
continue;
- }
// Build route descriptor from table entry...
// Set the source address and group address...
mrDesc.McAdr.s_addr = route->group;
- mrDesc.OriginAdr.s_addr = route->originAddrs[i];
+ mrDesc.OriginAdr.s_addr = o->originAddr;
// clear output interfaces
memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
- my_log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
+ my_log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", inetFmt(o->originAddr, s1), route->vifBits);
mrDesc.InVif = route->upstrVif;
// Set the TTL's for the route descriptor...
- for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
- if(Dp->state == IF_STATE_UPSTREAM) {
- continue;
+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
+ if (o->flood >= 0) {
+ if(Ix == o->flood) {
+ my_log(LOG_DEBUG, 0, "Identified Input VIF #%d as DOWNSTREAM.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(Dp->state == IF_STATE_UPSTREAM) {
+ my_log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ my_log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
+ } else {
+ if(Dp->state == IF_STATE_UPSTREAM) {
+ my_log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index);
+ mrDesc.InVif = Dp->index;
+ }
+ else if(BIT_TST(route->vifBits, Dp->index)) {
+ my_log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
+ }
}
- else if(BIT_TST(route->vifBits, Dp->index)) {
- my_log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
- mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
- }
}
// Do the actual Kernel route update...
@@ -765,7 +773,7 @@ int internUpdateKernelRoute(struct RouteTable *route,
*/
void logRouteTable(const char *header) {
struct Config *conf = getCommonConfig();
- struct RouteTable *croute = routing_table;
+ struct RouteTable *croute = RB_ROOT(&routing_table);
unsigned rcount = 0;
my_log(LOG_DEBUG, 0, "");
@@ -774,30 +782,22 @@ void logRouteTable(const char *header) {
if(croute==NULL) {
my_log(LOG_DEBUG, 0, "No routes in table...");
} else {
- do {
- char st = 'I';
- char src[MAX_ORIGINS * 30 + 1];
- src[0] = '\0';
- int i;
-
- for (i = 0; i < MAX_ORIGINS; i++) {
- if (croute->originAddrs[i] == 0) {
- continue;
- }
- st = 'A';
- sprintf(src + strlen(src), "Src%d: %s, ", i, inetFmt(croute->originAddrs[i], s1));
- }
-
- my_log(LOG_DEBUG, 0, "#%d: %sDst: %s, Age:%d, St: %c, OutVifs: 0x%08x, dHosts: %s",
- rcount, src, inetFmt(croute->group, s2),
- croute->ageValue, st,
+ RB_FOREACH(croute, rtabletree, &routing_table) {
+ my_log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x, dHosts: %s",
+ rcount, inetFmt(croute->group, s2),
+ croute->ageValue,
+ (TAILQ_EMPTY(&croute->originList) ? "I":"A"),
croute->vifBits,
!conf->fastUpstreamLeave ? "not tracked" : testNoDownstreamHost(conf, croute) ? "no" : "yes");
-
- croute = croute->nextroute;
-
+ {
+ struct Origin *o;
+ TAILQ_FOREACH(o, &croute->originList, next) {
+ my_log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d pktcnt %d",
+ rcount, inetFmt(o->originAddr, s1), o->flood, o->pktcnt);
+ }
+ }
rcount++;
- } while ( croute != NULL );
+ }
}
my_log(LOG_DEBUG, 0, "-----------------------------------------------------");

View File

@ -1,12 +0,0 @@
$OpenBSD: patch-udpsock_c,v 1.1.1.1 2008/02/08 19:30:51 sthen Exp $
--- udpsock.c.orig Sat Aug 20 13:35:00 2005
+++ udpsock.c Mon Nov 19 12:56:50 2007
@@ -58,7 +58,7 @@ int openUdpSocket( uint32 PeerInAdr, uint16 PeerPort )
memset( &SockAdr.sin_zero, 0, sizeof( SockAdr.sin_zero ) );
if( connect( Sock, (struct sockaddr *)&SockAdr, sizeof( SockAdr ) ) )
- log( LOG_ERR, errno, "UDP socket connect" );
+ log( LOG_ERR, errno, "UDP socket connect (port %d)", PeerPort);
return Sock;
}

View File

@ -1,4 +1,5 @@
@comment $OpenBSD: PLIST,v 1.4 2018/09/04 12:46:17 espie Exp $
@comment $OpenBSD: PLIST,v 1.5 2021/01/12 17:59:50 sthen Exp $
@rcscript ${RCDIR}/igmpproxy
@man man/man5/igmpproxy.conf.5
@man man/man8/igmpproxy.8
@bin sbin/igmpproxy
@ -6,4 +7,3 @@ share/doc/pkg-readmes/${PKGSTEM}
share/examples/igmpproxy/
share/examples/igmpproxy/igmpproxy.conf
@sample ${SYSCONFDIR}/igmpproxy.conf
@rcscript ${RCDIR}/igmpproxy