On Tue, Jan 12, 2021 at 4:22 AM Stuart Henderson <[email protected]> wrote:
>
> I don't get multicast from my ISP any more so can't test runtime.
> ports-wise the hardcoded CFLAGS should go and plist regenerated,
> otherwise looks good. I've added DEBUG_PACKAGES while there.
Oops, thanks for catching the plist update. I brought CFLAGS over
because it was in the existing patch-Makefile, but maybe the way I did
it should've been conditional? Having -Wall was nice because it caught
some fallout while updating the patches. I couldn't find any guidance
for things like CFLAGS in the porting docs.
> Anyone else want to test or should I just commit it?
I've been running it myself just between two local VLANs without any
regression compared to v0.1-beta2 in ports.
> It is probably not worth arguing with upstream about cdefs ;)
Yeah, I saw where it was headed and backed away slowly :)
.joel
>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/Makefile,v
> retrieving revision 1.19
> diff -u -p -r1.19 Makefile
> --- Makefile 12 Jul 2019 20:48:28 -0000 1.19
> +++ Makefile 12 Jan 2021 10:59:19 -0000
> @@ -2,16 +2,14 @@
>
> 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
> @@ -19,15 +17,16 @@ WANTLIB = c
> USE_GMAKE = Yes
>
> 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
> Index: distinfo
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/distinfo,v
> retrieving revision 1.2
> diff -u -p -r1.2 distinfo
> --- distinfo 18 Jan 2015 03:14:40 -0000 1.2
> +++ distinfo 12 Jan 2021 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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 10:59:19 -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;
> - }
> Index: pkg/PLIST
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/pkg/PLIST,v
> retrieving revision 1.4
> diff -u -p -r1.4 PLIST
> --- pkg/PLIST 4 Sep 2018 12:46:17 -0000 1.4
> +++ pkg/PLIST 12 Jan 2021 10:59:19 -0000
> @@ -1,4 +1,5 @@
> @comment $OpenBSD: PLIST,v 1.4 2018/09/04 12:46:17 espie 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
>