Hi. This diff brings net/igmpproxy up to v0.3 which is the latest at this time. The diff is rather intrusive due to the path to source files having changed upstream. Upstream also appears to have integrated random chunks of patches from the current version of the port.
I did try to start a dialog with upstream about taking some of these patches but that was rejected for reasons that defy logic. Note this port does not have an assigned maintainer. Please cc me on any replies. .joel (https://www.packetmischief.ca/files/patches/igmpproxy-0.3.diff if gmail mangles the diff below) Index: Makefile =================================================================== RCS file: /cvs/ports/net/igmpproxy/Makefile,v retrieving revision 1.19 diff -p -u -r1.19 Makefile --- Makefile 12 Jul 2019 20:48:28 -0000 1.19 +++ Makefile 12 Jan 2021 04:09:48 -0000 @@ -2,32 +2,31 @@ 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} +PKGNAME = 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 -MAKE_FLAGS = LDFLAGS="${LDFLAGS}" +MAKE_FLAGS = LDFLAGS="${LDFLAGS}" CFLAGS="-O -Wall" 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 Index: distinfo =================================================================== RCS file: /cvs/ports/net/igmpproxy/distinfo,v retrieving revision 1.2 diff -p -u -r1.2 distinfo --- distinfo 18 Jan 2015 03:14:40 -0000 1.2 +++ distinfo 12 Jan 2021 04:09:48 -0000 @@ -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 Index: patches/patch-Makefile =================================================================== RCS file: patches/patch-Makefile diff -N patches/patch-Makefile --- patches/patch-Makefile 8 Feb 2008 19:30:52 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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 : Index: patches/patch-config_c =================================================================== RCS file: patches/patch-config_c diff -N patches/patch-config_c --- patches/patch-config_c 23 Dec 2016 13:44:31 -0000 1.3 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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); -+} Index: patches/patch-defs_h =================================================================== RCS file: patches/patch-defs_h diff -N patches/patch-defs_h --- patches/patch-defs_h 23 Dec 2016 13:44:31 -0000 1.4 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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); Index: patches/patch-ifvc_c =================================================================== RCS file: patches/patch-ifvc_c diff -N patches/patch-ifvc_c --- patches/patch-ifvc_c 23 Dec 2016 13:44:31 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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); - } - - /* Index: patches/patch-igmp_c =================================================================== RCS file: patches/patch-igmp_c diff -N patches/patch-igmp_c --- patches/patch-igmp_c 8 Feb 2008 19:30:52 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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, Index: patches/patch-igmpproxy_c =================================================================== RCS file: patches/patch-igmpproxy_c diff -N patches/patch-igmpproxy_c --- patches/patch-igmpproxy_c 23 Dec 2016 13:44:31 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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); - } - } - Index: patches/patch-igmpproxy_conf =================================================================== RCS file: patches/patch-igmpproxy_conf diff -N patches/patch-igmpproxy_conf --- patches/patch-igmpproxy_conf 8 Feb 2008 19:30:52 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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 - - Index: patches/patch-mcgroup_c =================================================================== RCS file: patches/patch-mcgroup_c diff -N patches/patch-mcgroup_c --- patches/patch-mcgroup_c 23 Dec 2016 13:44:31 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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 ); - } Index: patches/patch-mroute-api_c =================================================================== RCS file: patches/patch-mroute-api_c diff -N patches/patch-mroute-api_c --- patches/patch-mroute-api_c 8 Feb 2008 19:30:52 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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); - } - - /* Index: patches/patch-request_c =================================================================== RCS file: patches/patch-request_c diff -N patches/patch-request_c --- patches/patch-request_c 23 Dec 2016 13:44:31 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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, Index: patches/patch-rttable_c =================================================================== RCS file: patches/patch-rttable_c diff -N patches/patch-rttable_c --- patches/patch-rttable_c 23 Dec 2016 13:44:31 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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"); Index: patches/patch-src_config_c =================================================================== RCS file: patches/patch-src_config_c diff -N patches/patch-src_config_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_config_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,71 @@ +$OpenBSD$ + +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); + } Index: patches/patch-src_ifvc_c =================================================================== RCS file: patches/patch-src_ifvc_c diff -N patches/patch-src_ifvc_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_ifvc_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,199 @@ +$OpenBSD$ + +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); + } + + /* Index: patches/patch-src_igmp_c =================================================================== RCS file: patches/patch-src_igmp_c diff -N patches/patch-src_igmp_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_igmp_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,65 @@ +$OpenBSD$ + +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: Index: patches/patch-src_igmpproxy_c =================================================================== RCS file: patches/patch-src_igmpproxy_c diff -N patches/patch-src_igmpproxy_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_igmpproxy_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,74 @@ +$OpenBSD$ + +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) { Index: patches/patch-src_igmpproxy_h =================================================================== RCS file: patches/patch-src_igmpproxy_h diff -N patches/patch-src_igmpproxy_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_igmpproxy_h 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,30 @@ +$OpenBSD$ + +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 + */ Index: patches/patch-src_kern_c =================================================================== RCS file: patches/patch-src_kern_c diff -N patches/patch-src_kern_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_kern_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,25 @@ +$OpenBSD$ + +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; Index: patches/patch-src_os-openbsd_h =================================================================== RCS file: patches/patch-src_os-openbsd_h diff -N patches/patch-src_os-openbsd_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_os-openbsd_h 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,40 @@ +$OpenBSD$ + +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) + { Index: patches/patch-src_request_c =================================================================== RCS file: patches/patch-src_request_c diff -N patches/patch-src_request_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_request_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,14 @@ +$OpenBSD$ + +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)) { Index: patches/patch-src_rttable_c =================================================================== RCS file: patches/patch-src_rttable_c diff -N patches/patch-src_rttable_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_rttable_c 12 Jan 2021 04:09:48 -0000 @@ -0,0 +1,537 @@ +$OpenBSD$ + +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, "-----------------------------------------------------"); Index: patches/patch-udpsock_c =================================================================== RCS file: patches/patch-udpsock_c diff -N patches/patch-udpsock_c --- patches/patch-udpsock_c 8 Feb 2008 19:30:51 -0000 1.1.1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -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; - }