On 2021/01/11 21:32, Joel Knight wrote:
> 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.


> (https://www.packetmischief.ca/files/patches/igmpproxy-0.3.diff if
> gmail mangles the diff below)

gmail's web client always mangles sending inline diffs, it's not
worth trying to send them that way. AFAIK attachments work.

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.

Anyone else want to test or should I just commit it?

It is probably not worth arguing with upstream about cdefs ;)


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

Reply via email to