On Tue, Jan 12, 2021 at 4:22 AM Stuart Henderson <[email protected]> wrote:
>
> I don't get multicast from my ISP any more so can't test runtime.
> ports-wise the hardcoded CFLAGS should go and plist regenerated,
> otherwise looks good. I've added DEBUG_PACKAGES while there.

Oops, thanks for catching the plist update. I brought CFLAGS over
because it was in the existing patch-Makefile, but maybe the way I did
it should've been conditional? Having -Wall was nice because it caught
some fallout while updating the patches. I couldn't find any guidance
for things like CFLAGS in the porting docs.

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

I've been running it myself just between two local VLANs without any
regression compared to v0.1-beta2 in ports.

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

Yeah, I saw where it was headed and backed away slowly :)




.joel

>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/Makefile,v
> retrieving revision 1.19
> diff -u -p -r1.19 Makefile
> --- Makefile    12 Jul 2019 20:48:28 -0000      1.19
> +++ Makefile    12 Jan 2021 10:59:19 -0000
> @@ -2,16 +2,14 @@
>
>  COMMENT =      multicast router utilizing IGMP forwarding
>
> -VERSION =      0.1-beta2
> -DISTNAME =     igmpproxy-src-${VERSION}
> -PKGNAME =      igmpproxy-${VERSION:S/-beta/b/}
> -REVISION =     12
> +VERSION =      0.3
> +DISTNAME =     igmpproxy-${VERSION}
>  CATEGORIES =   net
> -MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=igmpproxy/}
> +MASTER_SITES = 
> https://github.com/pali/igmpproxy/releases/download/${VERSION}/
>
> -HOMEPAGE =     http://igmpproxy.sourceforge.net/
> +HOMEPAGE =     https://github.com/pali/igmpproxy/
>
> -# GPLv2+ + mrouted license in igmpproxy/doc/mrouted-LICENSE
> +# GPLv2+ + mrouted license in igmpproxy/COPYING
>  PERMIT_PACKAGE =       Yes
>
>  WANTLIB =      c
> @@ -19,15 +17,16 @@ WANTLIB =   c
>  USE_GMAKE =    Yes
>
>  MAKE_FLAGS =   LDFLAGS="${LDFLAGS}"
> +DEBUG_PACKAGES = ${BUILD_PACKAGES}
>
>  NO_TEST =      Yes
>
> -WRKDIST =      ${WRKDIR}/igmpproxy/src
> +CONFIGURE_STYLE =      gnu
>
>  do-install:
> -       ${INSTALL_PROGRAM} ${WRKSRC}/igmpproxy ${PREFIX}/sbin
> -       ${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.8 ${PREFIX}/man/man8
> -       ${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.conf.5 ${PREFIX}/man/man5
> +       ${INSTALL_PROGRAM} ${WRKSRC}/src/igmpproxy ${PREFIX}/sbin
> +       ${INSTALL_MAN} ${WRKSRC}/doc/igmpproxy.8 ${PREFIX}/man/man8
> +       ${INSTALL_MAN} ${WRKSRC}/doc/igmpproxy.conf.5 ${PREFIX}/man/man5
>         ${INSTALL_DATA_DIR} ${PREFIX}/share/examples/igmpproxy
>         ${INSTALL_DATA} ${WRKSRC}/igmpproxy.conf \
>             ${PREFIX}/share/examples/igmpproxy
> Index: distinfo
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/distinfo,v
> retrieving revision 1.2
> diff -u -p -r1.2 distinfo
> --- distinfo    18 Jan 2015 03:14:40 -0000      1.2
> +++ distinfo    12 Jan 2021 10:59:19 -0000
> @@ -1,2 +1,2 @@
> -SHA256 (igmpproxy-src-0.1-beta2.tar.gz) = 
> f25UhuhIJxUMjKQClnyWM0u9Yrn3hRlcTuhNoSGKu0A=
> -SIZE (igmpproxy-src-0.1-beta2.tar.gz) = 35103
> +SHA256 (igmpproxy-0.3.tar.gz) = 0fwkTLL7v5n3IL2j6EH+WezptpGQc3kLS4knObG4ROs=
> +SIZE (igmpproxy-0.3.tar.gz) = 168403
> Index: patches/patch-Makefile
> ===================================================================
> RCS file: patches/patch-Makefile
> diff -N patches/patch-Makefile
> --- patches/patch-Makefile      8 Feb 2008 19:30:52 -0000       1.1.1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,28 +0,0 @@
> -$OpenBSD: patch-Makefile,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
> ---- Makefile.orig      Sat Aug 20 13:34:18 2005
> -+++ Makefile   Sat Jan 26 13:16:23 2008
> -@@ -6,12 +6,11 @@ MANDIR=/usr/share/man
> -
> -
> - # CFLAGS=-g
> --CFLAGS=-O
> -+CFLAGS?=-O
> -+CFLAGS+=-Wall
> -
> --default : build.h igmpproxy
> -+all   : build.h igmpproxy
> -
> --all   : igmpproxy
> --
> - clean :
> -       rm -f *.o *.asm build.h igmpproxy
> -
> -@@ -21,7 +20,7 @@ install :
> -       cp ../doc/igmpproxy.conf.5 ${MANDIR}/man5
> -       if [ ! -e ${ETCDIR}/igmpproxy.conf ]; then cp igmpproxy.conf 
> ${ETCDIR}; fi
> -
> --igmpproxy : igmpproxy.o config.o confread.o request.o udpsock.o mcgroup.o 
> rttable.o \
> -+igmpproxy : igmpproxy.o config.o confread.o request.o mcgroup.o rttable.o \
> -                       igmp.o ifvc.o callout.o kern.o syslog.o lib.o 
> mroute-api.o
> -
> - build.h       :
> Index: patches/patch-config_c
> ===================================================================
> RCS file: patches/patch-config_c
> diff -N patches/patch-config_c
> --- patches/patch-config_c      23 Dec 2016 13:44:31 -0000      1.3
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,93 +0,0 @@
> -$OpenBSD: patch-config_c,v 1.3 2016/12/23 13:44:31 rzalamena Exp $
> ---- config.c.orig      Thu Dec 15 19:50:23 2016
> -+++ config.c   Mon Dec 19 21:02:00 2016
> -@@ -177,7 +177,7 @@
> -     }
> -
> -     // Loop through all VIFs...
> --    for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
> -+    for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -         if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
> -
> -             // Now try to find a matching config...
> -@@ -241,11 +241,10 @@
> -     tmpPtr->allowednets = NULL;
> -
> -     // Make a copy of the token to store the IF name
> --    tmpPtr->name = (char *)malloc( sizeof(char) * strlen(token) );
> -+    tmpPtr->name = strdup(token);
> -     if(tmpPtr->name == NULL) {
> -         log(LOG_ERR, 0, "Out of memory.");
> -     }
> --    strcpy(tmpPtr->name, token);
> -
> -     // Set the altnet pointer to the allowednets pointer.
> -     anetPtr = &tmpPtr->allowednets;
> -@@ -255,8 +254,6 @@
> -     while(token != NULL) {
> -         if(strcmp("altnet", token)==0) {
> -             // Altnet...
> --            struct in_addr  networkAddr;
> --
> -             token = nextConfigToken();
> -             IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Got altnet token 
> %s.",token);
> -
> -@@ -328,29 +325,18 @@
> - */
> - struct SubnetList *parseSubnetAddress(char *addrstr) {
> -     struct SubnetList *tmpSubnet;
> --    char        *tmpStr;
> -     uint32      addr = 0x00000000;
> -     uint32      mask = 0xFFFFFFFF;
> -+    int               bitcnt;
> -
> --    // First get the network part of the address...
> --    tmpStr = strtok(addrstr, "/");
> --    addr = inet_addr(tmpStr);
> --
> --    tmpStr = strtok(NULL, "/");
> --    if(tmpStr != NULL) {
> --        int bitcnt = atoi(tmpStr);
> --        if(bitcnt <= 0 || bitcnt > 32) {
> --            log(LOG_WARNING, 0, "The bits part of the address is invalid : 
> %d.",tmpStr);
> --            return NULL;
> --        }
> --
> --        mask <<= (32 - bitcnt);
> --    }
> --
> --    if(addr == -1 || addr == 0) {
> --        log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr);
> -+    bitcnt = inet_net_pton(AF_INET, addrstr, &addr, sizeof(addr));
> -+    if(bitcnt<0) {
> -+        log(LOG_WARNING, 0, "Unable to parse address token '%s'.",addrstr);
> -         return NULL;
> --    }
> -+    } else if(bitcnt>0)
> -+      mask <<= (32 - bitcnt);
> -+    else
> -+      mask = 0;
> -
> -     tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList));
> -     tmpSubnet->subnet_addr = addr;
> -@@ -363,3 +349,20 @@
> -     return tmpSubnet;
> - }
> -
> -+struct vifconfig *
> -+config_getinterface(const char *ifname)
> -+{
> -+      struct vifconfig *vc;
> -+
> -+      if (vifconf == NULL)
> -+              return (NULL);
> -+
> -+      for (vc = vifconf; vc; vc = vc->next) {
> -+              if (strcmp(vc->name, ifname))
> -+                      continue;
> -+
> -+              return (vc);
> -+      }
> -+
> -+      return (NULL);
> -+}
> Index: patches/patch-defs_h
> ===================================================================
> RCS file: patches/patch-defs_h
> diff -N patches/patch-defs_h
> --- patches/patch-defs_h        23 Dec 2016 13:44:31 -0000      1.4
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,107 +0,0 @@
> -$OpenBSD: patch-defs_h,v 1.4 2016/12/23 13:44:31 rzalamena Exp $
> ---- defs.h.orig        Thu Dec 15 19:50:23 2016
> -+++ defs.h     Mon Dec 19 21:20:06 2016
> -@@ -40,10 +40,13 @@
> - #include <stdlib.h>
> - #include <syslog.h>
> - #include <signal.h>
> -+#include <string.h>
> -+#include <unistd.h>
> -
> -+#include <sys/errno.h>
> -+#include <sys/types.h>
> - #include <sys/socket.h>
> --#include <sys/un.h>
> --#include <sys/time.h>
> -+#include <sys/ioctl.h>
> -
> - #include <net/if.h>
> -
> -@@ -52,13 +55,32 @@
> -     #include <linux/in.h>
> -     #include <linux/mroute.h>
> - #else
> -+    #include <netinet/in_systm.h>
> -     #include <netinet/in.h>
> -     #include <netinet/ip.h>
> -     #include <netinet/igmp.h>
> -+    #include <netinet/ip_mroute.h>
> -     #include <arpa/inet.h>
> - #endif
> -
> -+#ifndef IGMP_MEMBERSHIP_QUERY
> -+#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
> -+#endif
> -+#ifndef IGMP_V1_MEMBERSHIP_REPORT
> -+#define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT
> -+#endif
> -+#ifndef IGMP_V2_MEMBERSHIP_REPORT
> -+#define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT
> -+#endif
> -+#ifndef IGMP_V2_LEAVE_GROUP
> -+#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
> -+#endif
> -
> -+#ifndef INADDR_ALLRTRS_GROUP
> -+/* address for multicast mtrace msg */
> -+#define INADDR_ALLRTRS_GROUP    (u_int32_t)0xe0000002   /* 224.0.0.2 */
> -+#endif
> -+
> - // The default path for the config file...
> - #define     IGMPPROXY_CONFIG_FILEPATH     "/etc/igmpproxy.conf"
> - #define     ENABLE_DEBUG    1
> -@@ -73,8 +95,12 @@
> - #define MAX_MC_VIFS    32     // !!! check this const in the specific 
> includes
> -
> - // Useful macros..
> -+#ifndef MIN
> - #define MIN( a, b ) ((a) < (b) ? (a) : (b))
> -+#endif
> -+#ifndef MAX
> - #define MAX( a, b ) ((a) < (b) ? (b) : (a))
> -+#endif
> - #define VCMC( Vc )  (sizeof( Vc ) / sizeof( (Vc)[ 0 ] ))
> - #define VCEP( Vc )  (&(Vc)[ VCMC( Vc ) ])
> -
> -@@ -126,6 +152,7 @@
> -
> - #define           IF_DEBUG    if(Log2Stderr & LOG_DEBUG)
> -
> -+#define log logit
> - void log( int Serverity, int Errno, const char *FmtSt, ... );
> -
> - /* ifvc.c
> -@@ -196,6 +223,7 @@
> - struct IfDesc *getIfByName( const char *IfName );
> - struct IfDesc *getIfByIx( unsigned Ix );
> - struct IfDesc *getIfByAddress( uint32 Ix );
> -+int isAdressValidForIf( struct IfDesc* intrface, uint32 ipaddr );
> -
> - /* mroute-api.c
> -  */
> -@@ -221,6 +249,7 @@
> - int loadConfig(char *configFile);
> - void configureVifs();
> - struct Config *getCommonConfig();
> -+struct vifconfig *config_getinterface(const char *ifname);
> -
> - /* igmp.c
> - */
> -@@ -235,7 +264,7 @@
> - char   *fmtInAdr( char *St, struct in_addr InAdr );
> - char   *inetFmt(uint32 addr, char *s);
> - char   *inetFmts(uint32 addr, uint32 mask, char *s);
> --int     inetCksum(u_short *addr, u_int len);
> -+int     inetChksum(u_short *addr, u_int len);
> -
> - /* kern.c
> -  */
> -@@ -264,7 +293,7 @@
> - void initRouteTable();
> - void clearAllRoutes();
> - int insertRoute(uint32 group, int ifx);
> --int activateRoute(uint32 group, uint32 originAddr);
> -+int activateRoute(uint32 group, uint32 originAddr, int downIf);
> - void ageActiveRoutes();
> - void setRouteLastMemberMode(uint32 group);
> - int lastMemberGroupAge(uint32 group);
> Index: patches/patch-ifvc_c
> ===================================================================
> RCS file: patches/patch-ifvc_c
> diff -N patches/patch-ifvc_c
> --- patches/patch-ifvc_c        23 Dec 2016 13:44:31 -0000      1.2
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,189 +0,0 @@
> -$OpenBSD: patch-ifvc_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
> ---- ifvc.c.orig        Thu Dec 15 19:50:23 2016
> -+++ ifvc.c     Mon Dec 19 21:22:11 2016
> -@@ -32,7 +32,8 @@
> - */
> -
> - #include "defs.h"
> --#include <linux/sockios.h>
> -+//#include <linux/sockios.h>
> -+#include <ifaddrs.h>
> -
> - struct IfDesc IfDescVc[ MAX_IF ], *IfDescEp = IfDescVc;
> -
> -@@ -42,119 +43,93 @@
> - **
> - */
> - void buildIfVc() {
> --    struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] )  ];
> --    struct ifreq *IfEp;
> -+    struct ifaddrs *ifap, *ifa;
> -+    struct IfDesc *ifp;
> -+    struct SubnetList *net;
> -
> --    int Sock;
> -+    if (getifaddrs(&ifap) < 0)
> -+      log( LOG_ERR, errno, "getifaddrs" );
> -
> --    if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
> --        log( LOG_ERR, errno, "RAW socket open" );
> --
> --    /* get If vector
> --     */
> --    {
> --        struct ifconf IoCtlReq;
> --
> --        IoCtlReq.ifc_buf = (void *)IfVc;
> --        IoCtlReq.ifc_len = sizeof( IfVc );
> --
> --        if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
> --            log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );
> --
> --        IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);
> --    }
> --
> -     /* loop over interfaces and copy interface info to IfDescVc
> -      */
> -     {
> --        struct ifreq  *IfPt;
> --        struct IfDesc *IfDp;
> --
> -         // Temp keepers of interface params...
> -         uint32 addr, subnet, mask;
> -
> --        for ( IfPt = IfVc; IfPt < IfEp; IfPt++ ) {
> --            struct ifreq IfReq;
> -+        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> -             char FmtBu[ 32 ];
> -
> --            strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name 
> ) );
> -+          if (IfDescEp >= &IfDescVc[ MAX_IF ]) {
> -+              log(LOG_WARNING, 0, "Too many interfaces, skipping %d", 
> ifa->ifa_name);
> -+                continue;
> -+          }
> -
> --            // Currently don't set any allowed nets...
> --            //IfDescEp->allowednets = NULL;
> --
> --            // Set the index to -1 by default.
> --            IfDescEp->index = -1;
> --
> --            /* don't retrieve more info for non-IP interfaces
> -+            /* ignore non-IP interfaces
> -              */
> --            if ( IfPt->ifr_addr.sa_family != AF_INET ) {
> --                IfDescEp->InAdr.s_addr = 0;  /* mark as non-IP interface */
> --                IfDescEp++;
> -+            if ( ifa->ifa_addr->sa_family != AF_INET )
> -                 continue;
> --            }
> -
> --            // Get the interface adress...
> --            IfDescEp->InAdr = ((struct sockaddr_in 
> *)&IfPt->ifr_addr)->sin_addr;
> --            addr = IfDescEp->InAdr.s_addr;
> -+          if ((ifp = getIfByName(ifa->ifa_name)) == NULL) {
> -+                if (config_getinterface(ifa->ifa_name) == NULL)
> -+                    continue;
> -
> --            memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name 
> ) );
> -+              strlcpy( IfDescEp->Name, ifa->ifa_name, sizeof( 
> IfDescEp->Name ) );
> -
> --            // Get the subnet mask...
> --            if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
> --                log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", 
> IfReq.ifr_name);
> --            mask = ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr;
> --            subnet = addr & mask;
> -+              log(LOG_DEBUG, 0, "Adding Physical Index value of IF '%s' is 
> %d",
> -+                  IfDescEp->Name, if_nametoindex(IfDescEp->Name));
> -
> --            // Get the physical index of the Interface
> --            if (ioctl(Sock, SIOCGIFINDEX, &IfReq ) < 0)
> --                log(LOG_ERR, errno, "ioctl SIOCGIFINDEX for %s", 
> IfReq.ifr_name);
> --
> --            log(LOG_DEBUG, 0, "Physical Index value of IF '%s' is %d",
> --                IfDescEp->Name, IfReq.ifr_ifindex);
> -+              // Set the index to -1 by default.
> -+              IfDescEp->index = -1;
> -
> -+              // Get the interface adress...
> -+              IfDescEp->InAdr = ((struct sockaddr_in 
> *)ifa->ifa_addr)->sin_addr;
> -
> --            /* get if flags
> --            **
> --            ** typical flags:
> --            ** lo    0x0049 -> Running, Loopback, Up
> --            ** ethx  0x1043 -> Multicast, Running, Broadcast, Up
> --            ** ipppx 0x0091 -> NoArp, PointToPoint, Up
> --            ** grex  0x00C1 -> NoArp, Running, Up
> --            ** ipipx 0x00C1 -> NoArp, Running, Up
> --            */
> --            if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
> --                log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );
> -+              /* get if flags
> -+              **
> -+              ** typical flags:
> -+              ** lo    0x0049 -> Running, Loopback, Up
> -+              ** ethx  0x1043 -> Multicast, Running, Broadcast, Up
> -+              ** ipppx 0x0091 -> NoArp, PointToPoint, Up
> -+              ** grex  0x00C1 -> NoArp, Running, Up
> -+              ** ipipx 0x00C1 -> NoArp, Running, Up
> -+              */
> -
> --            IfDescEp->Flags = IfReq.ifr_flags;
> -+              IfDescEp->Flags = ifa->ifa_flags;
> -
> -+              // Set the default params for the IF...
> -+              IfDescEp->state         = IF_STATE_DOWNSTREAM;
> -+              IfDescEp->robustness    = DEFAULT_ROBUSTNESS;
> -+              IfDescEp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit */
> -+              IfDescEp->ratelimit     = DEFAULT_RATELIMIT;
> -+              IfDescEp->allowednets   = NULL;
> -+              ifp = IfDescEp++;
> -+          }
> -+
> -             // Insert the verified subnet as an allowed net...
> --            IfDescEp->allowednets = (struct SubnetList 
> *)malloc(sizeof(struct SubnetList));
> --            if(IfDescEp->allowednets == NULL) log(LOG_ERR, 0, "Out of 
> memory !");
> -+            addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
> -+            mask = ((struct sockaddr_in 
> *)ifa->ifa_netmask)->sin_addr.s_addr;
> -+            subnet = addr & mask;
> -+
> -+            net = (struct SubnetList *)malloc(sizeof(struct SubnetList));
> -+            if(net == NULL) log(LOG_ERR, 0, "Out of memory !");
> -
> -             // Create the network address for the IF..
> --            IfDescEp->allowednets->next = NULL;
> --            IfDescEp->allowednets->subnet_mask = mask;
> --            IfDescEp->allowednets->subnet_addr = subnet;
> --
> --            // Set the default params for the IF...
> --            IfDescEp->state         = IF_STATE_DOWNSTREAM;
> --            IfDescEp->robustness    = DEFAULT_ROBUSTNESS;
> --            IfDescEp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit */
> --            IfDescEp->ratelimit     = DEFAULT_RATELIMIT;
> -+            net->next = ifp->allowednets;
> -+            net->subnet_mask = mask;
> -+            net->subnet_addr = subnet;
> -+            ifp->allowednets = net;
> -
> --
> -             // Debug log the result...
> -             IF_DEBUG log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, 
> Flags: 0x%04x, Network: %s",
> --                 IfDescEp->Name,
> --                 fmtInAdr( FmtBu, IfDescEp->InAdr ),
> --                 IfDescEp->Flags,
> -+                 ifp->Name,
> -+                 fmtInAdr( FmtBu, ifp->InAdr ),
> -+                 ifp->Flags,
> -                  inetFmts(subnet,mask, s1));
> -
> --            IfDescEp++;
> -         }
> --    }
> -
> --    close( Sock );
> -+    }
> -+    freeifaddrs(ifap);
> - }
> -
> - /*
> Index: patches/patch-igmp_c
> ===================================================================
> RCS file: patches/patch-igmp_c
> diff -N patches/patch-igmp_c
> --- patches/patch-igmp_c        8 Feb 2008 19:30:52 -0000       1.1.1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,82 +0,0 @@
> -$OpenBSD: patch-igmp_c,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
> ---- igmp.c.orig        Tue May 24 17:49:16 2005
> -+++ igmp.c     Mon Aug 13 15:16:51 2007
> -@@ -41,8 +41,6 @@
> - uint32     allhosts_group;          /* All hosts addr in net order */
> - uint32     allrouters_group;          /* All hosts addr in net order */
> -
> --extern int MRouterFD;
> --
> - /*
> -  * Open and initialize the igmp socket, and fill in the non-changing
> -  * IP header fields in the output packet buffer.
> -@@ -128,6 +126,7 @@ void acceptIgmp(int recvlen) {
> -         }
> -         else {
> -             struct IfDesc *checkVIF;
> -+          int downIf = -1;
> -
> -             // Check if the source address matches a valid address on 
> upstream vif.
> -             checkVIF = getIfByIx( upStreamVif );
> -@@ -141,15 +140,30 @@ void acceptIgmp(int recvlen) {
> -                 return;
> -             }
> -             else if(!isAdressValidForIf(checkVIF, src)) {
> --                log(LOG_WARNING, 0, "The source address %s for group %s, is 
> not in any valid net for upstream VIF.",
> --                    inetFmt(src, s1), inetFmt(dst, s2));
> --                return;
> -+              unsigned Ix;
> -+              struct IfDesc *Dp;
> -+
> -+              for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -+                  if ((Dp->state == IF_STATE_DOWNSTREAM) 
> &&isAdressValidForIf(Dp, src)) {
> -+                      downIf = Ix;
> -+                      break;
> -+                  }
> -+              }
> -+
> -+              if (downIf == -1) {
> -+                   log(LOG_WARNING, 0, "The source address %s for group %s, 
> is not in any valid net for upstream VIF.",
> -+                       inetFmt(src, s1), inetFmt(dst, s2));
> -+                   return;
> -+              } else {
> -+                  log(LOG_NOTICE, 0, "The source address %s for group %s, 
> is valid DOWNSTREAM VIF #%d.",
> -+                      inetFmt(src, s1), inetFmt(dst, s2), downIf);
> -+              }
> -             }
> -
> -             // Activate the route.
> --            IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to 
> %s",
> --                         inetFmt(src,s1), inetFmt(dst,s2));
> --            activateRoute(dst, src);
> -+            IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to 
> %s, downIf %d",
> -+                         inetFmt(src,s1), inetFmt(dst,s2), downIf);
> -+            activateRoute(dst, src, downIf);
> -
> -
> -         }
> -@@ -176,9 +190,9 @@ void acceptIgmp(int recvlen) {
> -         return;
> -     }
> -
> --    log(LOG_NOTICE, 0, "RECV %s from %-15s to %s",
> -+    log(LOG_NOTICE, 0, "RECV %s from %-15s to %s (ip_hl %d, data %d)",
> -         igmpPacketKind(igmp->igmp_type, igmp->igmp_code),
> --        inetFmt(src, s1), inetFmt(dst, s2) );
> -+        inetFmt(src, s1), inetFmt(dst, s2), iphdrlen, ipdatalen);
> -
> -     switch (igmp->igmp_type) {
> -     case IGMP_V1_MEMBERSHIP_REPORT:
> -@@ -190,12 +204,9 @@ void acceptIgmp(int recvlen) {
> -         acceptLeaveMessage(src, group);
> -         return;
> -
> --        /*
> -     case IGMP_MEMBERSHIP_QUERY:
> -         //accept_membership_query(src, dst, group, igmp->igmp_code);
> -         return;
> --
> --    */
> -
> -     default:
> -         log(LOG_INFO, 0,
> Index: patches/patch-igmpproxy_c
> ===================================================================
> RCS file: patches/patch-igmpproxy_c
> diff -N patches/patch-igmpproxy_c
> --- patches/patch-igmpproxy_c   23 Dec 2016 13:44:31 -0000      1.2
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,86 +0,0 @@
> -$OpenBSD: patch-igmpproxy_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
> ---- igmpproxy.c.orig   Thu Dec 15 19:50:24 2016
> -+++ igmpproxy.c        Thu Dec 15 19:51:46 2016
> -@@ -41,8 +41,8 @@
> - #include "version.h"
> - #include "build.h"
> -
> -+#include <sys/sysctl.h>
> -
> --
> - // Constants
> - static const char Version[] =
> - "igmpproxy, Version " VERSION ", Build" BUILD "\n"
> -@@ -80,7 +80,7 @@
> - *   on commandline. The number of commandline arguments, and a
> - *   pointer to the arguments are recieved on the line...
> - */
> --int main( int ArgCn, const char *ArgVc[] ) {
> -+int main( int ArgCn, char *ArgVc[] ) {
> -
> -     int debugMode = 0;
> -
> -@@ -133,6 +133,24 @@
> -       exit(1);
> -     }
> -
> -+    {
> -+      int ipmforwarding = 0;
> -+      int mib[4];
> -+      size_t len;
> -+
> -+        /* multicast IP forwarding must be enabled */
> -+        mib[0] = CTL_NET;
> -+        mib[1] = PF_INET;
> -+        mib[2] = IPPROTO_IP;
> -+        mib[3] = IPCTL_MFORWARDING;
> -+        len = sizeof(ipmforwarding);
> -+        if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1)
> -+          log(LOG_ERR, 0, "sysctl");
> -+
> -+        if (!ipmforwarding)
> -+          log(LOG_ERR, 0, "multicast IP forwarding not enabled");
> -+    }
> -+
> -     // Write debug notice with file path...
> -     IF_DEBUG log(LOG_DEBUG, 0, "Searching for config file at '%s'" , 
> configFilePath);
> -
> -@@ -155,17 +173,8 @@
> -         if ( ! debugMode ) {
> -
> -             IF_DEBUG log( LOG_DEBUG, 0, "Starting daemon mode.");
> --
> --            // Only daemon goes past this line...
> --            if (fork()) exit(0);
> --
> --            // Detach deamon from terminal
> --            if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0
> --                 || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || 
> dup2( 0, 2 ) < 0
> --                 || setpgrp() < 0
> --               ) {
> -+            if ( daemon(1, 0) < 0)
> -                 log( LOG_ERR, errno, "failed to detach deamon" );
> --            }
> -         }
> -
> -         // Go to the main loop.
> -@@ -218,7 +227,9 @@
> -         int     vifcount = 0;
> -         upStreamVif = -1;
> -
> --        for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
> -+        for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -+              if (config_getinterface(Dp->Name) == NULL)
> -+                      continue;
> -
> -             if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
> -                 if(Dp->state == IF_STATE_UPSTREAM) {
> -@@ -237,7 +248,7 @@
> -
> -         // If there is only one VIF, or no defined upstream VIF, we send an 
> error.
> -         if(vifcount < 2 || upStreamVif < 0) {
> --            log(LOG_ERR, 0, "There must be at least 2 Vif's where one is 
> upstream.");
> -+            log(LOG_ERR, 0, "There must be at least 2 Vif's where one is 
> upstream. (vifcount %d, upStreamVif %d)", vifcount, upStreamVif);
> -         }
> -     }
> -
> Index: patches/patch-igmpproxy_conf
> ===================================================================
> RCS file: patches/patch-igmpproxy_conf
> diff -N patches/patch-igmpproxy_conf
> --- patches/patch-igmpproxy_conf        8 Feb 2008 19:30:52 -0000       
> 1.1.1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,50 +0,0 @@
> -$OpenBSD: patch-igmpproxy_conf,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
> ---- igmpproxy.conf.orig        Fri Apr 29 20:27:50 2005
> -+++ igmpproxy.conf     Sat Jan 26 12:05:26 2008
> -@@ -9,11 +9,11 @@
> - #   If multicast traffic originates outside the
> - #   upstream subnet, the "altnet" option can be
> - #   used in order to define legal multicast sources.
> --#   (Se example...)
> -+#   (See example...)
> - #
> - #   The "quickleave" should be used to avoid saturation
> - #   of the upstream link. The option should only
> --#   be used if it's absolutely nessecary to
> -+#   be used if it's absolutely necessary to
> - #   accurately imitate just one Client.
> - #
> - ########################################################
> -@@ -25,22 +25,23 @@ quickleave
> -
> -
> - ##------------------------------------------------------
> --## Configuration for eth0 (Upstream Interface)
> -+## Configuration for em0 (Upstream Interface)
> - ##------------------------------------------------------
> --phyint eth0 upstream  ratelimit 0  threshold 1
> --        altnet 10.0.0.0/8
> --        altnet 192.168.0.0/24
> -+phyint em0 upstream  ratelimit 0  threshold 1
> -+        altnet 10.0.0.0/8
> -+#     altnet 132.185.0.0/16   # BBC multicast trial
> -+#     altnet 217.0.119.0/24   # T-Home Entertain
> -+#     altnet 193.158.35.0/24  # T-Home Entertain
> -
> --
> - ##------------------------------------------------------
> --## Configuration for eth1 (Downstream Interface)
> -+## Configuration for ipw0 (Downstream Interface)
> - ##------------------------------------------------------
> --phyint eth1 downstream  ratelimit 0  threshold 1
> -+phyint ipw0 downstream  ratelimit 0  threshold 1
> -
> -
> - ##------------------------------------------------------
> --## Configuration for eth2 (Disabled Interface)
> -+## Configuration for lo0 (Disabled Interface)
> - ##------------------------------------------------------
> --phyint eth2 disabled
> -+phyint lo0 disabled
> -
> -
> Index: patches/patch-mcgroup_c
> ===================================================================
> RCS file: patches/patch-mcgroup_c
> diff -N patches/patch-mcgroup_c
> --- patches/patch-mcgroup_c     23 Dec 2016 13:44:31 -0000      1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,37 +0,0 @@
> -$OpenBSD: patch-mcgroup_c,v 1.1 2016/12/23 13:44:31 rzalamena Exp $
> ---- mcgroup.c.orig     Thu Dec 15 19:48:18 2016
> -+++ mcgroup.c  Mon Dec 19 21:22:07 2016
> -@@ -49,7 +49,6 @@
> -     CtlReq.imr_interface.s_addr = IfDp->InAdr.s_addr;
> -
> -     {
> --        char FmtBu[ 32 ];
> -         log( LOG_NOTICE, 0, "%sMcGroup: %s on %s", CmdSt,
> -             inetFmt( mcastaddr, s1 ), IfDp ? IfDp->Name : "<any>" );
> -     }
> -@@ -58,7 +57,7 @@
> -           Cmd == 'j' ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP,
> -           (void *)&CtlReq, sizeof( CtlReq ) ) )
> -     {
> --        log( LOG_WARNING, errno, "MRT_%s_MEMBERSHIP failed", Cmd == 'j' ? 
> "ADD" : "DROP" );
> -+        log( LOG_WARNING, errno, "IP_%s_MEMBERSHIP failed", Cmd == 'j' ? 
> "ADD" : "DROP" );
> -         return 1;
> -     }
> -
> -@@ -73,6 +72,8 @@
> - *   @return 0 if the function succeeds, 1 if parameters are wrong or the 
> join fails
> - */
> - int joinMcGroup( int UdpSock, struct IfDesc *IfDp, uint32 mcastaddr ) {
> -+      if (config_getinterface(IfDp->Name) == NULL)
> -+              return (1);
> -     return joinleave( 'j', UdpSock, IfDp, mcastaddr );
> - }
> -
> -@@ -82,5 +83,7 @@
> - *   @return 0 if the function succeeds, 1 if parameters are wrong or the 
> join fails
> - */
> - int leaveMcGroup( int UdpSock, struct IfDesc *IfDp, uint32 mcastaddr ) {
> -+      if (config_getinterface(IfDp->Name) == NULL)
> -+              return (1);
> -     return joinleave( 'l', UdpSock, IfDp, mcastaddr );
> - }
> Index: patches/patch-mroute-api_c
> ===================================================================
> RCS file: patches/patch-mroute-api_c
> diff -N patches/patch-mroute-api_c
> --- patches/patch-mroute-api_c  8 Feb 2008 19:30:52 -0000       1.1.1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,53 +0,0 @@
> -$OpenBSD: patch-mroute-api_c,v 1.1.1.1 2008/02/08 19:30:52 sthen Exp $
> ---- mroute-api.c.orig  Tue May 24 17:48:33 2005
> -+++ mroute-api.c       Mon Aug 13 15:12:06 2007
> -@@ -37,7 +37,7 @@
> - */
> -
> -
> --#define USE_LINUX_IN_H
> -+//#define USE_LINUX_IN_H
> - #include "defs.h"
> -
> - // MAX_MC_VIFS from mclab.h must have same value as MAXVIFS from mroute.h
> -@@ -47,7 +47,7 @@
> -
> - // need an IGMP socket as interface for the mrouted API
> - // - receives the IGMP messages
> --int         MRouterFD;        /* socket for all network I/O  */
> -+int         MRouterFD = -1;        /* socket for all network I/O  */
> - char        *recv_buf;           /* input packet buffer         */
> - char        *send_buf;           /* output packet buffer        */
> -
> -@@ -177,13 +177,14 @@ int addMRoute( struct MRouteDesc *Dp )
> -         log( LOG_NOTICE, 0, "Adding MFC: %s -> %s, InpVIf: %d",
> -              fmtInAdr( FmtBuO, CtlReq.mfcc_origin ),
> -              fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ),
> --             CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent
> -+             CtlReq.mfcc_parent
> -            );
> -     }
> -
> -     if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC,
> -                      (void *)&CtlReq, sizeof( CtlReq ) ) )
> -         log( LOG_WARNING, errno, "MRT_ADD_MFC" );
> -+    return (0);
> - }
> -
> - /*
> -@@ -210,13 +211,14 @@ int delMRoute( struct MRouteDesc *Dp )
> -         log( LOG_NOTICE, 0, "Removing MFC: %s -> %s, InpVIf: %d",
> -              fmtInAdr( FmtBuO, CtlReq.mfcc_origin ),
> -              fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ),
> --             CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent
> -+             CtlReq.mfcc_parent
> -            );
> -     }
> -
> -     if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC,
> -                      (void *)&CtlReq, sizeof( CtlReq ) ) )
> -         log( LOG_WARNING, errno, "MRT_DEL_MFC" );
> -+    return (0);
> - }
> -
> - /*
> Index: patches/patch-request_c
> ===================================================================
> RCS file: patches/patch-request_c
> diff -N patches/patch-request_c
> --- patches/patch-request_c     23 Dec 2016 13:44:31 -0000      1.2
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,34 +0,0 @@
> -$OpenBSD: patch-request_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
> ---- request.c.orig     Thu Dec 15 19:50:24 2016
> -+++ request.c  Mon Dec 19 21:06:50 2016
> -@@ -88,7 +88,7 @@
> -
> -     } else {
> -         // Log the state of the interface the report was recieved on.
> --        log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.",
> -+        log(LOG_INFO, 0, "Membership report was recieved on %s. Ignoring.",
> -             sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a 
> disabled interface");
> -     }
> -
> -@@ -136,7 +136,8 @@
> -
> -     } else {
> -         // just ignore the leave request...
> --        IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. 
> Ignoring leave request.");
> -+        IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. 
> Ignoring leave request.",
> -+          inetFmt(src, s1));
> -     }
> - }
> -
> -@@ -184,8 +185,10 @@
> -     int             Ix;
> -
> -     // Loop through all downstream vifs...
> --    for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
> -+    for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -         if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
> -+              if (config_getinterface(Dp->Name) == NULL)
> -+                      continue;
> -             if(Dp->state == IF_STATE_DOWNSTREAM) {
> -                 // Send the membership query...
> -                 sendIgmp(Dp->InAdr.s_addr, allhosts_group,
> Index: patches/patch-rttable_c
> ===================================================================
> RCS file: patches/patch-rttable_c
> diff -N patches/patch-rttable_c
> --- patches/patch-rttable_c     23 Dec 2016 13:44:31 -0000      1.2
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,549 +0,0 @@
> -$OpenBSD: patch-rttable_c,v 1.2 2016/12/23 13:44:31 rzalamena Exp $
> ---- rttable.c.orig     Thu Dec 15 19:50:24 2016
> -+++ rttable.c  Mon Dec 19 21:22:11 2016
> -@@ -38,15 +38,22 @@
> - */
> -
> - #include "defs.h"
> -+#include <sys/queue.h>
> -+#include <sys/tree.h>
> -
> - /**
> - *   Routing table structure definition. Double linked list...
> - */
> -+struct Origin {
> -+    TAILQ_ENTRY(Origin) next;
> -+    uint32            originAddr;
> -+    int                       flood;
> -+    uint32            pktcnt;
> -+};
> -+
> - struct RouteTable {
> --    struct RouteTable   *nextroute;     // Pointer to the next group in 
> line.
> --    struct RouteTable   *prevroute;     // Pointer to the previous group in 
> line.
> -+    RB_ENTRY(RouteTable) entry;
> -     uint32              group;          // The group to route
> --    uint32              originAddr;     // The origin adress (only set on 
> activated routes)
> -     uint32              vifBits;        // Bits representing recieving VIFs.
> -
> -     // Keeps the upstream membership state...
> -@@ -56,28 +63,58 @@
> -     uint32              ageVifBits;     // Bits representing aging VIFs.
> -     int                 ageValue;       // Downcounter for death.
> -     int                 ageActivity;    // Records any acitivity that notes 
> there are still listeners.
> -+    TAILQ_HEAD(originhead, Origin) originList; // The origin adresses 
> (non-empty on activated routes)
> - };
> -+RB_HEAD(rtabletree, RouteTable) routing_table =
> -+    RB_INITIALIZER(&routing_table);
> -
> --
> --// Keeper for the routing table...
> --static struct RouteTable   *routing_table;
> --
> - // Prototypes
> - void logRouteTable(char *header);
> - int  internAgeRoute(struct RouteTable*  croute);
> -+int  internUpdateKernelRoute(struct RouteTable *route, int activate, struct 
> Origin *o);
> -
> --// Socket for sending join or leave requests.
> --int mcGroupSock = 0;
> -+int                    rtable_cmp(struct RouteTable *, struct RouteTable *);
> -+struct RouteTable     *rtable_add(struct RouteTable *);
> -+void                   rtable_remove(struct RouteTable *);
> -+RB_GENERATE(rtabletree, RouteTable, entry, rtable_cmp);
> -
> -+int
> -+rtable_cmp(struct RouteTable *rt, struct RouteTable *rtn)
> -+{
> -+      if (rt->group < rtn->group)
> -+              return (-1);
> -
> -+      return (rt->group > rtn->group);
> -+}
> -+
> -+struct RouteTable *
> -+rtable_add(struct RouteTable *rt)
> -+{
> -+      return (RB_INSERT(rtabletree, &routing_table, rt));
> -+}
> -+
> -+void
> -+rtable_remove(struct RouteTable *rt)
> -+{
> -+      struct Origin           *o;
> -+
> -+        while ((o = TAILQ_FIRST(&rt->originList))) {
> -+              TAILQ_REMOVE(&rt->originList, o, next);
> -+              free(o);
> -+        }
> -+
> -+      RB_REMOVE(rtabletree, &routing_table, rt);
> -+      free(rt);
> -+}
> -+
> - /**
> - *   Function for retrieving the Multicast Group socket.
> - */
> - int getMcGroupSock() {
> --    if( ! mcGroupSock ) {
> --        mcGroupSock = openUdpSocket( INADDR_ANY, 0 );;
> -+    if (MRouterFD < 0) {
> -+        log(LOG_ERR, errno, "no MRouterFD.");
> -     }
> --    return mcGroupSock;
> -+    return MRouterFD;
> - }
> -
> - /**
> -@@ -87,11 +124,8 @@
> -     unsigned Ix;
> -     struct IfDesc *Dp;
> -
> --    // Clear routing table...
> --    routing_table = NULL;
> --
> -     // Join the all routers group on downstream vifs...
> --    for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
> -+    for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -         // If this is a downstream vif, we should join the All routers 
> group...
> -         if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state 
> == IF_STATE_DOWNSTREAM) {
> -             IF_DEBUG log(LOG_DEBUG, 0, "Joining all-routers group %s on vif 
> %s",
> -@@ -159,29 +193,24 @@
> - *   Clear all routes from routing table, and alerts Leaves upstream.
> - */
> - void clearAllRoutes() {
> --    struct RouteTable   *croute, *remainroute;
> -+    struct RouteTable   *croute;
> -
> -     // Loop through all routes...
> --    for(croute = routing_table; croute; croute = remainroute) {
> --
> --        remainroute = croute->nextroute;
> --
> -+    while ((croute = RB_ROOT(&routing_table)) != NULL) {
> -         // Log the cleanup in debugmode...
> -         IF_DEBUG log(LOG_DEBUG, 0, "Removing route entry for %s",
> -                      inetFmt(croute->group, s1));
> -
> -         // Uninstall current route
> --        if(!internUpdateKernelRoute(croute, 0)) {
> -+        if(!internUpdateKernelRoute(croute, 0, NULL)) {
> -             log(LOG_WARNING, 0, "The removal from Kernel failed.");
> -         }
> -
> -         // Send Leave message upstream.
> -         sendJoinLeaveUpstream(croute, 0);
> -
> --        // Clear memory, and set pointer to next route...
> --        free(croute);
> -+      rtable_remove(croute);
> -     }
> --    routing_table = NULL;
> -
> -     // Send a notice that the routing table is empty...
> -     log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");
> -@@ -192,15 +221,10 @@
> - *   Route Descriptor.
> - */
> - struct RouteTable *findRoute(uint32 group) {
> --    struct RouteTable*  croute;
> -+      struct RouteTable        key;
> -
> --    for(croute = routing_table; croute; croute = croute->nextroute) {
> --        if(croute->group == group) {
> --            return croute;
> --        }
> --    }
> --
> --    return NULL;
> -+      key.group = group;
> -+      return (RB_FIND(rtabletree, &routing_table, &key));
> - }
> -
> - /**
> -@@ -212,7 +236,6 @@
> -
> -     struct Config *conf = getCommonConfig();
> -     struct RouteTable*  croute;
> --    int result = 1;
> -
> -     // Sanitycheck the group adress...
> -     if( ! IN_MULTICAST( ntohl(group) )) {
> -@@ -241,9 +264,7 @@
> -         newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
> -         // Insert the route desc and clear all pointers...
> -         newroute->group      = group;
> --        newroute->originAddr = 0;
> --        newroute->nextroute  = NULL;
> --        newroute->prevroute  = NULL;
> -+        TAILQ_INIT(&newroute->originList);
> -
> -         // The group is not joined initially.
> -         newroute->upstrState = ROUTESTATE_NOTJOINED;
> -@@ -260,54 +281,13 @@
> -             BIT_SET(newroute->vifBits, ifx);
> -         }
> -
> --        // Check if there is a table already....
> --        if(routing_table == NULL) {
> --            // No location set, so insert in on the table top.
> --            routing_table = newroute;
> --            IF_DEBUG log(LOG_DEBUG, 0, "No routes in table. Insert at 
> beginning.");
> --        } else {
> -+        if ((croute = rtable_add(newroute)) != NULL)
> -+            free(newroute);
> -+      else {
> -+            // Set the new route as the current...
> -+            croute = newroute;
> -+      }
> -
> --            IF_DEBUG log(LOG_DEBUG, 0, "Found existing routes. Find insert 
> location.");
> --
> --            // Check if the route could be inserted at the beginning...
> --            if(routing_table->group > group) {
> --                IF_DEBUG log(LOG_DEBUG, 0, "Inserting at beginning, before 
> route %s",inetFmt(routing_table->group,s1));
> --
> --                // Insert at beginning...
> --                newroute->nextroute = routing_table;
> --                newroute->prevroute = NULL;
> --                routing_table = newroute;
> --
> --                // If the route has a next node, the previous pointer must 
> be updated.
> --                if(newroute->nextroute != NULL) {
> --                    newroute->nextroute->prevroute = newroute;
> --                }
> --
> --            } else {
> --
> --                // Find the location which is closest to the route.
> --                for( croute = routing_table; croute->nextroute != NULL; 
> croute = croute->nextroute ) {
> --                    // Find insert position.
> --                    if(croute->nextroute->group > group) {
> --                        break;
> --                    }
> --                }
> --
> --                IF_DEBUG log(LOG_DEBUG, 0, "Inserting after route 
> %s",inetFmt(croute->group,s1));
> --
> --                // Insert after current...
> --                newroute->nextroute = croute->nextroute;
> --                newroute->prevroute = croute;
> --                if(croute->nextroute != NULL) {
> --                    croute->nextroute->prevroute = newroute;
> --                }
> --                croute->nextroute = newroute;
> --            }
> --        }
> --
> --        // Set the new route as the current...
> --        croute = newroute;
> --
> -         // Log the cleanup in debugmode...
> -         log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
> -             inetFmt(croute->group, s1),ifx);
> -@@ -325,10 +305,10 @@
> -             inetFmt(croute->group, s1), ifx);
> -
> -         // If the route is active, it must be reloaded into the Kernel..
> --        if(croute->originAddr != 0) {
> -+        if(!TAILQ_EMPTY(&croute->originList)) {
> -
> -             // Update route in kernel...
> --            if(!internUpdateKernelRoute(croute, 1)) {
> -+            if(!internUpdateKernelRoute(croute, 1, NULL)) {
> -                 log(LOG_WARNING, 0, "The insertion into Kernel failed.");
> -                 return 0;
> -             }
> -@@ -351,7 +331,7 @@
> - *   activated, it's reinstalled in the kernel. If
> - *   the route is activated, no originAddr is needed.
> - */
> --int activateRoute(uint32 group, uint32 originAddr) {
> -+int activateRoute(uint32 group, uint32 originAddr, int downIf) {
> -     struct RouteTable*  croute;
> -     int result = 0;
> -
> -@@ -369,21 +349,42 @@
> -     }
> -
> -     if(croute != NULL) {
> -+      struct Origin *o = NULL;
> -+      int found = 0;
> -+
> -         // If the origin address is set, update the route data.
> --        if(originAddr > 0) {
> --            if(croute->originAddr > 0 && croute->originAddr!=originAddr) {
> --                log(LOG_WARNING, 0, "The origin for route %s changed from 
> %s to %s",
> --                    inetFmt(croute->group, s1),
> --                    inetFmt(croute->originAddr, s2),
> --                    inetFmt(originAddr, s3));
> --            }
> --            croute->originAddr = originAddr;
> --        }
> -+      if(originAddr > 0) {
> -
> --        // Only update kernel table if there are listeners !
> --        if(croute->vifBits > 0) {
> --            result = internUpdateKernelRoute(croute, 1);
> --        }
> -+          TAILQ_FOREACH(o, &croute->originList, next) {
> -+              log(LOG_INFO, 0, "Origin for route %s have %s, new %s",
> -+                  inetFmt(croute->group, s1),
> -+                  inetFmt(o->originAddr, s2),
> -+                  inetFmt(originAddr, s3));
> -+              if (o->originAddr==originAddr) {
> -+                  found++;
> -+                  break;
> -+              }
> -+          }
> -+          if (!found) {
> -+              log(LOG_NOTICE, 0, "New origin for route %s is %s, flood %d",
> -+                  inetFmt(croute->group, s1),
> -+                  inetFmt(originAddr, s3), downIf);
> -+              o = malloc(sizeof(*o));
> -+              o->originAddr = originAddr;
> -+              o->flood = downIf;
> -+              o->pktcnt = 0;
> -+              TAILQ_INSERT_TAIL(&croute->originList, o, next);
> -+          } else {
> -+              log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt %d",
> -+                  inetFmt(croute->group, s1),
> -+                  inetFmt(o->originAddr, s3),
> -+                  o->pktcnt);
> -+          }
> -+      }
> -+
> -+        // Only update kernel table if there are listeners, but flood 
> upstream!
> -+        if(croute->vifBits > 0 || downIf >= 0)
> -+            result = internUpdateKernelRoute(croute, 1, o);
> -     }
> -     IF_DEBUG logRouteTable("Activate Route");
> -
> -@@ -401,11 +402,7 @@
> -     IF_DEBUG log(LOG_DEBUG, 0, "Aging routes in table.");
> -
> -     // Scan all routes...
> --    for( croute = routing_table; croute != NULL; croute = nroute ) {
> --
> --        // Keep the next route (since current route may be removed)...
> --        nroute = croute->nextroute;
> --
> -+    RB_FOREACH_SAFE(croute, rtabletree, &routing_table, nroute) {
> -         // Run the aging round algorithm.
> -         if(croute->upstrState != ROUTESTATE_CHECK_LAST_MEMBER) {
> -             // Only age routes if Last member probe is not active...
> -@@ -443,7 +440,6 @@
> - *   route is not found, or not in this state, 0 is returned.
> - */
> - int lastMemberGroupAge(uint32 group) {
> --    struct Config       *conf = getCommonConfig();
> -     struct RouteTable   *croute;
> -
> -     croute = findRoute(group);
> -@@ -477,7 +473,7 @@
> -     //BIT_ZERO(croute->vifBits);
> -
> -     // Uninstall current route from kernel
> --    if(!internUpdateKernelRoute(croute, 0)) {
> -+    if(!internUpdateKernelRoute(croute, 0, NULL)) {
> -         log(LOG_WARNING, 0, "The removal from Kernel failed.");
> -         result = 0;
> -     }
> -@@ -489,24 +485,8 @@
> -         sendJoinLeaveUpstream(croute, 0);
> -     }
> -
> --    // Update pointers...
> --    if(croute->prevroute == NULL) {
> --        // Topmost node...
> --        if(croute->nextroute != NULL) {
> --            croute->nextroute->prevroute = NULL;
> --        }
> --        routing_table = croute->nextroute;
> -+    rtable_remove(croute);
> -
> --    } else {
> --        croute->prevroute->nextroute = croute->nextroute;
> --        if(croute->nextroute != NULL) {
> --            croute->nextroute->prevroute = croute->prevroute;
> --        }
> --    }
> --    // Free the memory, and set the route to NULL...
> --    free(croute);
> --    croute = NULL;
> --
> -     IF_DEBUG logRouteTable("Remove route");
> -
> -     return result;
> -@@ -551,6 +531,36 @@
> -         }
> -     }
> -
> -+    {
> -+      struct Origin *o, *nxt;
> -+      struct sioc_sg_req sg_req;
> -+
> -+      sg_req.grp.s_addr = croute->group;
> -+      for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) {
> -+          nxt = TAILQ_NEXT(o, next);
> -+          sg_req.src.s_addr = o->originAddr;
> -+          if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) {
> -+              log(LOG_WARNING, errno, "%s (%s %s)",
> -+                  "age_table_entry: SIOCGETSGCNT failing for",
> -+                  inetFmt(o->originAddr, s1),
> -+                  inetFmt(croute->group, s2));
> -+              /* Make sure it gets deleted below */
> -+              sg_req.pktcnt = o->pktcnt;
> -+          }
> -+          log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d",
> -+              inetFmt(o->originAddr, s1), inetFmt(croute->group, s2),
> -+              o->pktcnt, sg_req.pktcnt);
> -+          if (sg_req.pktcnt == o->pktcnt) {
> -+              /* no traffic, remove from kernel cache */
> -+              internUpdateKernelRoute(croute, 0, o);
> -+              TAILQ_REMOVE(&croute->originList, o, next);
> -+              free(o);
> -+          } else {
> -+              o->pktcnt = sg_req.pktcnt;
> -+          }
> -+      }
> -+    }
> -+
> -     // If the aging counter has reached zero, its time for updating...
> -     if(croute->ageValue == 0) {
> -         // Check for activity in the aging process,
> -@@ -560,7 +570,7 @@
> -                          inetFmt(croute->group,s1));
> -
> -             // Just update the routing settings in kernel...
> --            internUpdateKernelRoute(croute, 1);
> -+            internUpdateKernelRoute(croute, 1, NULL);
> -
> -             // We append the activity counter to the age, and continue...
> -             croute->ageValue = croute->ageActivity;
> -@@ -586,34 +596,58 @@
> - /**
> - *   Updates the Kernel routing table. If activate is 1, the route
> - *   is (re-)activated. If activate is false, the route is removed.
> -+*   if 'origin' is given, only the route with 'origin' will be
> -+*   updated, otherwise all MFC routes for the group will updated.
> - */
> --int internUpdateKernelRoute(struct RouteTable *route, int activate) {
> -+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct 
> Origin *origin) {
> -     struct   MRouteDesc     mrDesc;
> -     struct   IfDesc         *Dp;
> -     unsigned                Ix;
> -+    struct Origin *o;
> -
> --    if(route->originAddr>0) {
> -+    if (TAILQ_EMPTY(&route->originList)) {
> -+        log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
> -+        return 1;
> -+    }
> -+    TAILQ_FOREACH(o, &route->originList, next) {
> -+      if (origin && origin != o)
> -+              continue;
> -
> -         // Build route descriptor from table entry...
> -         // Set the source address and group address...
> -         mrDesc.McAdr.s_addr     = route->group;
> --        mrDesc.OriginAdr.s_addr = route->originAddr;
> -+        mrDesc.OriginAdr.s_addr = o->originAddr;
> -
> -         // clear output interfaces
> -         memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
> -
> --        IF_DEBUG log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
> -+        IF_DEBUG log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", 
> inetFmt(o->originAddr, s1), route->vifBits);
> -
> -         // Set the TTL's for the route descriptor...
> --        for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) {
> --            if(Dp->state == IF_STATE_UPSTREAM) {
> --                //IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as 
> upstream.", Dp->index);
> --                mrDesc.InVif = Dp->index;
> --            }
> --            else if(BIT_TST(route->vifBits, Dp->index)) {
> --                IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", 
> Dp->index, Dp->threshold);
> --                mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> --            }
> -+        for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> -+          if (o->flood >= 0) {
> -+              if(Ix == o->flood) {
> -+                  IF_DEBUG log(LOG_DEBUG, 0, "Identified Input VIF #%d as 
> DOWNSTREAM.", Dp->index);
> -+                  mrDesc.InVif = Dp->index;
> -+              }
> -+              else if(Dp->state == IF_STATE_UPSTREAM) {
> -+                  IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif 
> %d to %d", Dp->index, Dp->threshold);
> -+                  mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> -+              }
> -+              else if(BIT_TST(route->vifBits, Dp->index)) {
> -+                  IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM 
> Vif %d to %d", Dp->index, Dp->threshold);
> -+                  mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> -+              }
> -+          } else {
> -+              if(Dp->state == IF_STATE_UPSTREAM) {
> -+                  IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as 
> upstream.", Dp->index);
> -+                  mrDesc.InVif = Dp->index;
> -+              }
> -+              else if(BIT_TST(route->vifBits, Dp->index)) {
> -+                  IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to 
> %d", Dp->index, Dp->threshold);
> -+                  mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> -+              }
> -+          }
> -         }
> -
> -         // Do the actual Kernel route update...
> -@@ -625,9 +659,6 @@
> -             // Delete the route from Kernel...
> -             delMRoute( &mrDesc );
> -         }
> --
> --    } else {
> --        log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
> -     }
> -
> -     return 1;
> -@@ -639,29 +670,27 @@
> - */
> - void logRouteTable(char *header) {
> -     IF_DEBUG  {
> --        struct RouteTable*  croute = routing_table;
> -+        struct RouteTable*  croute = RB_ROOT(&routing_table);
> -         unsigned            rcount = 0;
> -
> -         log(LOG_DEBUG, 0, "\nCurrent routing table 
> (%s);\n-----------------------------------------------------\n", header);
> -         if(croute==NULL) {
> -             log(LOG_DEBUG, 0, "No routes in table...");
> -         } else {
> --            do {
> --                /*
> --                log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, 
> Prev: 0x%08x, T: 0x%08x, Next: 0x%08x",
> --                    rcount, inetFmt(croute->originAddr, s1), 
> inetFmt(croute->group, s2),
> --                    croute->ageValue,(croute->originAddr>0?"A":"I"),
> --                    croute->prevroute, croute, croute->nextroute);
> --                */
> --                log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, 
> OutVifs: 0x%08x",
> --                    rcount, inetFmt(croute->originAddr, s1), 
> inetFmt(croute->group, s2),
> --                    croute->ageValue,(croute->originAddr>0?"A":"I"),
> --                    croute->vifBits);
> --
> --                croute = croute->nextroute;
> --
> -+            RB_FOREACH(croute, rtabletree, &routing_table) {
> -+              log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, OutVifs: 
> 0x%08x",
> -+                  rcount, inetFmt(croute->group, s2),
> -+                  
> croute->ageValue,(TAILQ_EMPTY(&croute->originList)?"I":"A"),
> -+                  croute->vifBits);
> -+              {
> -+                  struct Origin *o;
> -+                  TAILQ_FOREACH(o, &croute->originList, next) {
> -+                      log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d pktcnt 
> %d",
> -+                          rcount, inetFmt(o->originAddr, s1), o->flood, 
> o->pktcnt);
> -+                  }
> -+              }
> -                 rcount++;
> --            } while ( croute != NULL );
> -+          }
> -         }
> -
> -         log(LOG_DEBUG, 0, 
> "\n-----------------------------------------------------\n");
> Index: patches/patch-src_config_c
> ===================================================================
> RCS file: patches/patch-src_config_c
> diff -N patches/patch-src_config_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_config_c  12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,71 @@
> +$OpenBSD$
> +
> +Index: src/config.c
> +--- src/config.c.orig
> ++++ src/config.c
> +@@ -393,33 +393,19 @@ struct vifconfig *parsePhyintToken(void) {
> + */
> + struct SubnetList *parseSubnetAddress(char *addrstr) {
> +     struct SubnetList   *tmpSubnet;
> +-    char                *tmpStr;
> +     uint32_t            addr = 0x00000000;
> +     uint32_t            mask = 0xFFFFFFFF;
> ++    int                       bitcnt;
> +
> +-    // First get the network part of the address...
> +-    tmpStr = strtok(addrstr, "/");
> +-    addr = inet_addr(tmpStr);
> ++    bitcnt = inet_net_pton(AF_INET, addrstr, &addr, sizeof(addr));
> ++    if(bitcnt<0) {
> ++        my_log(LOG_WARNING, 0, "Unable to parse address token 
> '%s'.",addrstr);
> ++         return NULL;
> ++    } else if(bitcnt>0)
> ++      mask <<= (32 - bitcnt);
> ++    else
> ++      mask = 0;
> +
> +-    tmpStr = strtok(NULL, "/");
> +-    if(tmpStr != NULL) {
> +-        int bitcnt = atoi(tmpStr);
> +-        if(bitcnt < 0 || bitcnt > 32) {
> +-            my_log(LOG_WARNING, 0, "The bits part of the address is invalid 
> : %d.",tmpStr);
> +-            return NULL;
> +-        }
> +-
> +-        if (bitcnt == 0)
> +-            mask = 0;
> +-        else
> +-            mask <<= (32 - bitcnt);
> +-    }
> +-
> +-    if(addr == (uint32_t)-1) {
> +-        my_log(LOG_WARNING, 0, "Unable to parse address token '%s'.", 
> addrstr);
> +-        return NULL;
> +-    }
> +-
> +     tmpSubnet = (struct SubnetList*) malloc(sizeof(struct SubnetList));
> +     tmpSubnet->subnet_addr = addr;
> +     tmpSubnet->subnet_mask = ntohl(mask);
> +@@ -429,4 +415,22 @@ struct SubnetList *parseSubnetAddress(char *addrstr) {
> +             inetFmts(tmpSubnet->subnet_addr, tmpSubnet->subnet_mask,s1));
> +
> +     return tmpSubnet;
> ++}
> ++
> ++struct vifconfig *
> ++config_getinterface(const char *ifname)
> ++{
> ++      struct vifconfig *vc;
> ++
> ++      if (vifconf == NULL)
> ++              return (NULL);
> ++
> ++      for (vc = vifconf; vc; vc = vc->next) {
> ++              if (strcmp(vc->name, ifname))
> ++                      continue;
> ++
> ++              return (vc);
> ++      }
> ++
> ++      return (NULL);
> + }
> Index: patches/patch-src_ifvc_c
> ===================================================================
> RCS file: patches/patch-src_ifvc_c
> diff -N patches/patch-src_ifvc_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_ifvc_c    12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,199 @@
> +$OpenBSD$
> +
> +Index: src/ifvc.c
> +--- src/ifvc.c.orig
> ++++ src/ifvc.c
> +@@ -33,6 +33,7 @@
> + */
> +
> + #include "igmpproxy.h"
> ++#include <ifaddrs.h>
> +
> + /* We need a temporary copy to not break strict aliasing rules */
> + static inline uint32_t s_addr_from_sockaddr(const struct sockaddr *addr) {
> +@@ -201,129 +202,93 @@ void rebuildIfVc () {
> + **
> + */
> + void buildIfVc(void) {
> +-    struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] )  ];
> +-    struct ifreq *IfEp;
> +-    struct Config *config = getCommonConfig();
> ++    struct ifaddrs *ifap, *ifa;
> ++    struct IfDesc *ifp;
> ++    struct SubnetList *net;
> +
> +-    int Sock;
> ++    if (getifaddrs(&ifap) < 0)
> ++        my_log( LOG_ERR, errno, "getifaddrs" );
> +
> +-    if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
> +-        my_log( LOG_ERR, errno, "RAW socket open" );
> +-
> +-    /* get If vector
> +-     */
> +-    {
> +-        struct ifconf IoCtlReq;
> +-
> +-        IoCtlReq.ifc_buf = (void *)IfVc;
> +-        IoCtlReq.ifc_len = sizeof( IfVc );
> +-
> +-        if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 )
> +-            my_log( LOG_ERR, errno, "ioctl SIOCGIFCONF" );
> +-
> +-        IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len);
> +-    }
> +-
> +     /* loop over interfaces and copy interface info to IfDescVc
> +      */
> +     {
> +-        struct ifreq  *IfPt, *IfNext;
> +-
> +         // Temp keepers of interface params...
> +         uint32_t addr, subnet, mask;
> +
> +-        for ( IfPt = IfVc; IfPt < IfEp; IfPt = IfNext ) {
> +-            struct ifreq IfReq;
> ++        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> +             char FmtBu[ 32 ];
> +
> +-            IfNext = (struct ifreq *)((char *)&IfPt->ifr_addr +
> +-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
> +-                    IfPt->ifr_addr.sa_len
> +-#else
> +-                    sizeof(struct sockaddr_in)
> +-#endif
> +-            );
> +-            if (IfNext < IfPt + 1)
> +-                IfNext = IfPt + 1;
> ++            if (IfDescEp >= &IfDescVc[ MAX_IF ]) {
> ++                my_log(LOG_WARNING, 0, "Too many interfaces, skipping %d", 
> ifa->ifa_name);
> ++                continue;
> ++            }
> +
> +-            strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name 
> ) );
> ++            /* ignore non-IP interfaces
> ++             */
> ++            if ( ifa->ifa_addr->sa_family != AF_INET )
> ++                continue;
> +
> +-            // Currently don't set any allowed nets...
> +-            //IfDescEp->allowednets = NULL;
> ++            if ((ifp = getIfByName(ifa->ifa_name)) == NULL) {
> ++                if (config_getinterface(ifa->ifa_name) == NULL)
> ++                    continue;
> +
> +-            // Set the index to -1 by default.
> +-            IfDescEp->index = (unsigned int)-1;
> ++                strlcpy( IfDescEp->Name, ifa->ifa_name, sizeof( 
> IfDescEp->Name ) );
> +
> +-            /* don't retrieve more info for non-IP interfaces
> +-             */
> +-            if ( IfPt->ifr_addr.sa_family != AF_INET ) {
> +-                IfDescEp->InAdr.s_addr = 0;  /* mark as non-IP interface */
> +-                IfDescEp++;
> +-                continue;
> +-            }
> ++                my_log(LOG_DEBUG, 0, "Adding physical index value of IF 
> '%s': %d",
> ++                IfDescEp->Name, if_nametoindex(IfDescEp->Name));
> +
> +-            // Get the interface adress...
> +-            IfDescEp->InAdr.s_addr = s_addr_from_sockaddr(&IfPt->ifr_addr);
> +-            addr = IfDescEp->InAdr.s_addr;
> ++                // Set the index to -1 by default.
> ++                IfDescEp->index = -1;
> +
> +-            memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name 
> ) );
> ++                // Get the interface adress...
> ++                IfDescEp->InAdr = ((struct sockaddr_in 
> *)ifa->ifa_addr)->sin_addr;
> +
> +-            // Get the subnet mask...
> +-            if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0)
> +-                my_log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", 
> IfReq.ifr_name);
> +-            mask = s_addr_from_sockaddr(&IfReq.ifr_addr); // Do not use 
> ifr_netmask as it is not available on freebsd
> +-            subnet = addr & mask;
> ++                /* get if flags
> ++                **
> ++                ** typical flags:
> ++                ** lo    0x0049 -> Running, Loopback, Up
> ++                ** ethx  0x1043 -> Multicast, Running, Broadcast, Up
> ++                ** ipppx 0x0091 -> NoArp, PointToPoint, Up
> ++                ** grex  0x00C1 -> NoArp, Running, Up
> ++                ** ipipx 0x00C1 -> NoArp, Running, Up
> ++                */
> +
> +-            /* get if flags
> +-            **
> +-            ** typical flags:
> +-            ** lo    0x0049 -> Running, Loopback, Up
> +-            ** ethx  0x1043 -> Multicast, Running, Broadcast, Up
> +-            ** ipppx 0x0091 -> NoArp, PointToPoint, Up
> +-            ** grex  0x00C1 -> NoArp, Running, Up
> +-            ** ipipx 0x00C1 -> NoArp, Running, Up
> +-            */
> +-            if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 )
> +-                my_log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" );
> ++                IfDescEp->Flags = ifa->ifa_flags;
> +
> +-            IfDescEp->Flags = IfReq.ifr_flags;
> ++                // Set the default params for the IF...
> ++                IfDescEp->state         = IF_STATE_DOWNSTREAM;
> ++                IfDescEp->robustness    = DEFAULT_ROBUSTNESS;
> ++                IfDescEp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit 
> */
> ++                IfDescEp->ratelimit     = DEFAULT_RATELIMIT;
> ++                IfDescEp->allowednets   = NULL;
> ++                ifp = IfDescEp++;
> ++           }
> +
> +-            // aimwang: when pppx get dstaddr for use
> +-            if (0x10d1 == IfDescEp->Flags)
> +-            {
> +-                if ( ioctl( Sock, SIOCGIFDSTADDR, &IfReq ) < 0 )
> +-                    my_log(LOG_ERR, errno, "ioctl SIOCGIFDSTADDR for %s", 
> IfReq.ifr_name);
> +-                addr = s_addr_from_sockaddr(&IfReq.ifr_dstaddr);
> +-                subnet = addr & mask;
> +-            }
> +
> +             // Insert the verified subnet as an allowed net...
> +-            IfDescEp->allowednets = (struct SubnetList 
> *)malloc(sizeof(struct SubnetList));
> +-            if(IfDescEp->allowednets == NULL) my_log(LOG_ERR, 0, "Out of 
> memory !");
> ++            addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
> ++            mask = ((struct sockaddr_in 
> *)ifa->ifa_netmask)->sin_addr.s_addr;
> ++            subnet = addr & mask;
> +
> +-            // Create the network address for the IF..
> +-            IfDescEp->allowednets->next = NULL;
> +-            IfDescEp->allowednets->subnet_mask = mask;
> +-            IfDescEp->allowednets->subnet_addr = subnet;
> ++            net = (struct SubnetList *)malloc(sizeof(struct SubnetList));
> ++            if(net == NULL)
> ++                my_log(LOG_ERR, 0, "Out of memory !");
> +
> +-            // Set the default params for the IF...
> +-            IfDescEp->state         = config->defaultInterfaceState;
> +-            IfDescEp->robustness    = DEFAULT_ROBUSTNESS;
> +-            IfDescEp->threshold     = DEFAULT_THRESHOLD;   /* ttl limit */
> +-            IfDescEp->ratelimit     = DEFAULT_RATELIMIT;
> ++            net->next = ifp->allowednets;
> ++            net->subnet_mask = mask;
> ++            net->subnet_addr = subnet;
> ++            ifp->allowednets = net;
> +
> +             // Debug log the result...
> +             my_log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, Flags: 
> 0x%04x, Network: %s",
> +-                 IfDescEp->Name,
> +-                 fmtInAdr( FmtBu, IfDescEp->InAdr ),
> +-                 IfDescEp->Flags,
> ++                 ifp->Name,
> ++                 fmtInAdr( FmtBu, ifp->InAdr ),
> ++                 ifp->Flags,
> +                  inetFmts(subnet,mask, s1));
> +
> +-            IfDescEp++;
> +         }
> +     }
> +-
> +-    close( Sock );
> ++    freeifaddrs(ifap);
> + }
> +
> + /*
> Index: patches/patch-src_igmp_c
> ===================================================================
> RCS file: patches/patch-src_igmp_c
> diff -N patches/patch-src_igmp_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_igmp_c    12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,65 @@
> +$OpenBSD$
> +
> +Index: src/igmp.c
> +--- src/igmp.c.orig
> ++++ src/igmp.c
> +@@ -139,6 +139,7 @@ void acceptIgmp(int recvlen) {
> +         }
> +         else {
> +             struct IfDesc *checkVIF;
> ++            int downIf = -1;
> +
> +             for(i=0; i<MAX_UPS_VIFS; i++)
> +             {
> +@@ -156,20 +157,29 @@ void acceptIgmp(int recvlen) {
> +                         return;
> +                     }
> +                     else if(!isAdressValidForIf(checkVIF, src)) {
> +-                        struct IfDesc *downVIF = getIfByAddress(src);
> +-                        if (downVIF && downVIF->state & 
> IF_STATE_DOWNSTREAM) {
> +-                            my_log(LOG_NOTICE, 0, "The source address %s 
> for group %s is from downstream VIF[%d]. Ignoring.",
> +-                                inetFmt(src, s1), inetFmt(dst, s2), i);
> ++                        unsigned Ix;
> ++                        struct IfDesc *Dp;
> ++
> ++                        for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> ++                            if ((Dp->state == IF_STATE_DOWNSTREAM) && 
> isAdressValidForIf(Dp, src)) {
> ++                                downIf = Ix;
> ++                                break;
> ++                            }
> ++                        }
> ++
> ++                        if (downIf == -1) {
> ++                            my_log(LOG_WARNING, 0, "The source address %s 
> for group %s, is not in any valid net for upstream VIF.",
> ++                               inetFmt(src, s1), inetFmt(dst, s2));
> ++                            return;
> +                         } else {
> +-                            my_log(LOG_WARNING, 0, "The source address %s 
> for group %s, is not in any valid net for upstream VIF[%d].",
> +-                                inetFmt(src, s1), inetFmt(dst, s2), i);
> ++                            my_log(LOG_NOTICE, 0, "The source address %s 
> for group %s, is valid DOWNSTREAM VIF #%d.",
> ++                            inetFmt(src, s1), inetFmt(dst, s2), downIf);
> +                         }
> +                     } else {
> +                         // Activate the route.
> +-                        int vifindex = checkVIF->index;
> +-                        my_log(LOG_DEBUG, 0, "Route activate request from 
> %s to %s on VIF[%d]",
> +-                            inetFmt(src,s1), inetFmt(dst,s2), vifindex);
> +-                        activateRoute(dst, src, vifindex);
> ++                        my_log(LOG_DEBUG, 0, "Route activate request from 
> %s to %s, downIf %d",
> ++                            inetFmt(src,s1), inetFmt(dst,s2), downIf);
> ++                        activateRoute(dst, src, downIf);
> +                         i = MAX_UPS_VIFS;
> +                     }
> +                 } else {
> +@@ -199,9 +209,9 @@ void acceptIgmp(int recvlen) {
> +         return;
> +     }
> +
> +-    my_log(LOG_NOTICE, 0, "RECV %s from %-15s to %s",
> ++    my_log(LOG_NOTICE, 0, "RECV %s from %-15s to %s (ip_hl %d, data %d)",
> +         igmpPacketKind(igmp->igmp_type, igmp->igmp_code),
> +-        inetFmt(src, s1), inetFmt(dst, s2) );
> ++        inetFmt(src, s1), inetFmt(dst, s2), iphdrlen, ipdatalen);
> +
> +     switch (igmp->igmp_type) {
> +     case IGMP_V1_MEMBERSHIP_REPORT:
> Index: patches/patch-src_igmpproxy_c
> ===================================================================
> RCS file: patches/patch-src_igmpproxy_c
> diff -N patches/patch-src_igmpproxy_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_igmpproxy_c       12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,74 @@
> +$OpenBSD$
> +
> +Index: src/igmpproxy.c
> +--- src/igmpproxy.c.orig
> ++++ src/igmpproxy.c
> +@@ -37,13 +37,10 @@
> + *   February 2005 - Johnny Egeland
> + */
> +
> +-/* getopt() and clock_getime() */
> +-#ifndef _POSIX_C_SOURCE
> +-#define _POSIX_C_SOURCE 200112L
> +-#endif
> +-
> + #include "igmpproxy.h"
> +
> ++#include <sys/sysctl.h>
> ++
> + static const char Usage[] =
> + "Usage: igmpproxy [-h] [-n] [-d] [-v [-v]] <configfile>\n"
> + "\n"
> +@@ -123,6 +120,25 @@ int main( int ArgCn, char *ArgVc[] ) {
> +
> +     openlog("igmpproxy", LOG_PID, LOG_USER);
> +
> ++    {
> ++       int ipmforwarding = 0;
> ++       int mib[4];
> ++       size_t len;
> ++
> ++        /* multicast IP forwarding must be enabled */
> ++        mib[0] = CTL_NET;
> ++        mib[1] = PF_INET;
> ++        mib[2] = IPPROTO_IP;
> ++        mib[3] = IPCTL_MFORWARDING;
> ++        len = sizeof(ipmforwarding);
> ++        if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1)
> ++           my_log(LOG_ERR, 0, "sysctl");
> ++
> ++        if (!ipmforwarding)
> ++           my_log(LOG_ERR, 0, "multicast IP forwarding not enabled");
> ++    }
> ++
> ++
> +     // Write debug notice with file path...
> +     my_log(LOG_DEBUG, 0, "Searching for config file at '%s'" , 
> configFilePath);
> +
> +@@ -142,16 +158,8 @@ int main( int ArgCn, char *ArgVc[] ) {
> +
> +         if ( !NotAsDaemon ) {
> +
> +-            // Only daemon goes past this line...
> +-            if (fork()) exit(0);
> +-
> +-            // Detach daemon from terminal
> +-            if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0
> +-                || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 
> 0, 2 ) < 0
> +-                || setpgid( 0, 0 ) < 0
> +-            ) {
> ++            if ( daemon(1, 0 ) < 0 )
> +                 my_log( LOG_ERR, errno, "failed to detach daemon" );
> +-            }
> +         }
> +
> +         // Go to the main loop.
> +@@ -207,6 +215,8 @@ int igmpProxyInit(void) {
> +         }
> +
> +         for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
> ++            if (config_getinterface(Dp->Name) == NULL)
> ++               continue;
> +
> +             if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
> +                 if(Dp->state == IF_STATE_UPSTREAM) {
> Index: patches/patch-src_igmpproxy_h
> ===================================================================
> RCS file: patches/patch-src_igmpproxy_h
> diff -N patches/patch-src_igmpproxy_h
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_igmpproxy_h       12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,30 @@
> +$OpenBSD$
> +
> +Index: src/igmpproxy.h
> +--- src/igmpproxy.h.orig
> ++++ src/igmpproxy.h
> +@@ -36,7 +36,6 @@
> + */
> +
> + #include "config.h"
> +-#include "os.h"
> +
> + #include <errno.h>
> + #include <stdarg.h>
> +@@ -60,6 +59,8 @@
> + #include <netinet/in.h>
> + #include <arpa/inet.h>
> +
> ++#include "os.h"
> ++
> + /*
> +  * Limit on length of route data
> +  */
> +@@ -218,6 +219,7 @@ int getVifIx( struct IfDesc *IfDp );
> + int loadConfig(char *configFile);
> + void configureVifs(void);
> + struct Config *getCommonConfig(void);
> ++struct vifconfig *config_getinterface(const char *ifname);
> +
> + /* igmp.c
> + */
> Index: patches/patch-src_kern_c
> ===================================================================
> RCS file: patches/patch-src_kern_c
> diff -N patches/patch-src_kern_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_kern_c    12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,25 @@
> +$OpenBSD$
> +
> +Index: src/kern.c
> +--- src/kern.c.orig
> ++++ src/kern.c
> +@@ -114,6 +114,9 @@ void k_set_if(uint32_t ifa) {
> + void k_join(struct IfDesc *ifd, uint32_t grp) {
> +     struct ip_mreq mreq;
> +
> ++    if (config_getinterface(ifd->Name) == NULL)
> ++        return;
> ++
> +     mreq.imr_multiaddr.s_addr = grp;
> +     mreq.imr_interface.s_addr = ifd->InAdr.s_addr;
> +
> +@@ -135,6 +138,9 @@ void k_join(struct IfDesc *ifd, uint32_t grp) {
> +
> + void k_leave(struct IfDesc *ifd, uint32_t grp) {
> +     struct ip_mreq mreq;
> ++
> ++    if (config_getinterface(ifd->Name) == NULL)
> ++        return;
> +
> +     mreq.imr_multiaddr.s_addr = grp;
> +     mreq.imr_interface.s_addr = ifd->InAdr.s_addr;
> Index: patches/patch-src_os-openbsd_h
> ===================================================================
> RCS file: patches/patch-src_os-openbsd_h
> diff -N patches/patch-src_os-openbsd_h
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_os-openbsd_h      12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,40 @@
> +$OpenBSD$
> +
> +Index: src/os-openbsd.h
> +--- src/os-openbsd.h.orig
> ++++ src/os-openbsd.h
> +@@ -1,16 +1,34 @@
> ++#include <sys/cdefs.h>
> ++#include <sys/types.h>
> ++#include <sys/ioctl.h>
> + #include <netinet/in_systm.h>
> + #include <netinet/ip_mroute.h>
> + #include <netinet/ip.h>
> + #include <netinet/igmp.h>
> +
> ++
> ++#ifndef IGMP_MEMBERSHIP_QUERY
> + #define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY
> ++#endif
> ++#ifndef IGMP_V1_MEMBERSHIP_REPORT
> + #define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT
> ++#endif
> ++#ifndef IGMP_V2_MEMBERSHIP_REPORT
> + #define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT
> ++#endif
> ++#ifndef IGMP_V3_MEMBERSHIP_REPORT
> + #define IGMP_V3_MEMBERSHIP_REPORT 0x22
> ++#endif
> ++#ifndef IGMP_V2_LEAVE_GROUP
> + #define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE
> ++#endif
> +
> ++#ifndef INADDR_ALLRTRS_GROUP
> + #define INADDR_ALLRTRS_GROUP INADDR_ALLROUTERS_GROUP
> ++#endif
> ++#ifndef INADDR_ALLIGMPV3_GROUP
> + #define INADDR_ALLIGMPV3_GROUP ((in_addr_t) 0xe0000016)
> ++#endif
> +
> + static inline unsigned short ip_data_len(const struct ip *ip)
> + {
> Index: patches/patch-src_request_c
> ===================================================================
> RCS file: patches/patch-src_request_c
> diff -N patches/patch-src_request_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_request_c 12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,14 @@
> +$OpenBSD$
> +
> +Index: src/request.c
> +--- src/request.c.orig
> ++++ src/request.c
> +@@ -183,6 +183,8 @@ void sendGroupSpecificMemberQuery(void *argument) {
> +     // Loop through all downstream interfaces
> +     for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
> +         if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) {
> ++            if (config_getinterface(Dp->Name) == NULL)
> ++                continue;
> +             if(Dp->state == IF_STATE_DOWNSTREAM) {
> +                 // Is that interface used in the group?
> +                 if (interfaceInRoute(gvDesc->group ,Dp->index)) {
> Index: patches/patch-src_rttable_c
> ===================================================================
> RCS file: patches/patch-src_rttable_c
> diff -N patches/patch-src_rttable_c
> --- /dev/null   1 Jan 1970 00:00:00 -0000
> +++ patches/patch-src_rttable_c 12 Jan 2021 10:59:19 -0000
> @@ -0,0 +1,537 @@
> +$OpenBSD$
> +
> +Index: src/rttable.c
> +--- src/rttable.c.orig
> ++++ src/rttable.c
> +@@ -39,17 +39,23 @@
> + */
> +
> + #include "igmpproxy.h"
> ++#include <sys/queue.h>
> ++#include <sys/tree.h>
> +
> + #define MAX_ORIGINS 4
> +
> + /**
> + *   Routing table structure definition. Double linked list...
> + */
> ++struct Origin {
> ++    TAILQ_ENTRY(Origin) next;
> ++    uint32_t        originAddr;
> ++    int             flood;
> ++    uint32_t        pktcnt;
> ++};
> + struct RouteTable {
> +-    struct RouteTable   *nextroute;     // Pointer to the next group in 
> line.
> +-    struct RouteTable   *prevroute;     // Pointer to the previous group in 
> line.
> ++    RB_ENTRY(RouteTable) entry;
> +     uint32_t            group;          // The group to route
> +-    uint32_t            originAddrs[MAX_ORIGINS]; // The origin adresses 
> (only set on activated routes)
> +     uint32_t            vifBits;        // Bits representing recieving VIFs.
> +
> +     // Keeps the upstream membership state...
> +@@ -60,22 +66,54 @@ struct RouteTable {
> +     uint32_t            ageVifBits;     // Bits representing aging VIFs.
> +     int                 ageValue;       // Downcounter for death.
> +     int                 ageActivity;    // Records any acitivity that notes 
> there are still listeners.
> ++    TAILQ_HEAD(originhead, Origin) originList; // The origin adresses 
> (non-empty on activated routes)
> +
> +     // Keeps downstream hosts information
> +     uint32_t            downstreamHostsHashSeed;
> +     uint8_t             downstreamHostsHashTable[];
> + };
> ++RB_HEAD(rtabletree, RouteTable) routing_table =
> ++    RB_INITIALIZER(&routing_table);
> +
> +-
> +-// Keeper for the routing table...
> +-static struct RouteTable   *routing_table;
> +-
> + // Prototypes
> + void logRouteTable(const char *header);
> + int internAgeRoute(struct RouteTable *croute);
> +-int internUpdateKernelRoute(struct RouteTable *route, int activate);
> ++int internUpdateKernelRoute(struct RouteTable *route, int activate, struct 
> Origin *);
> +
> ++int                   rtable_cmp(struct RouteTable *, struct RouteTable *);
> ++struct RouteTable    *rtable_add(struct RouteTable *);
> ++void                  rtable_remove(struct RouteTable *);
> ++RB_GENERATE(rtabletree, RouteTable, entry, rtable_cmp);
> +
> ++int
> ++rtable_cmp(struct RouteTable *rt, struct RouteTable *rtn)
> ++{
> ++    if (rt->group < rtn->group)
> ++        return (-1);
> ++
> ++    return (rt->group > rtn->group);
> ++}
> ++
> ++struct RouteTable *
> ++rtable_add(struct RouteTable *rt)
> ++{
> ++    return (RB_INSERT(rtabletree, &routing_table, rt));
> ++}
> ++
> ++void
> ++rtable_remove(struct RouteTable *rt)
> ++{
> ++    struct Origin        *o;
> ++
> ++        while ((o = TAILQ_FIRST(&rt->originList))) {
> ++        TAILQ_REMOVE(&rt->originList, o, next);
> ++        free(o);
> ++        }
> ++
> ++    RB_REMOVE(rtabletree, &routing_table, rt);
> ++    free(rt);
> ++}
> ++
> + /**
> + *   Functions for downstream hosts hash table
> + */
> +@@ -120,9 +158,6 @@ void initRouteTable(void) {
> +     unsigned Ix;
> +     struct IfDesc *Dp;
> +
> +-    // Clear routing table...
> +-    routing_table = NULL;
> +-
> +     // Join the all routers group on downstream vifs...
> +     for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
> +         // If this is a downstream vif, we should join the All routers 
> group...
> +@@ -213,29 +248,24 @@ static void sendJoinLeaveUpstream(struct RouteTable* r
> + *   Clear all routes from routing table, and alerts Leaves upstream.
> + */
> + void clearAllRoutes(void) {
> +-    struct RouteTable   *croute, *remainroute;
> ++    struct RouteTable   *croute;
> +
> +     // Loop through all routes...
> +-    for(croute = routing_table; croute; croute = remainroute) {
> +-
> +-        remainroute = croute->nextroute;
> +-
> ++    while ((croute = RB_ROOT(&routing_table)) != NULL) {
> +         // Log the cleanup in debugmode...
> +         my_log(LOG_DEBUG, 0, "Removing route entry for %s",
> +                      inetFmt(croute->group, s1));
> +
> +         // Uninstall current route
> +-        if(!internUpdateKernelRoute(croute, 0)) {
> ++        if(!internUpdateKernelRoute(croute, 0, NULL)) {
> +             my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
> +         }
> +
> +         // Send Leave message upstream.
> +         sendJoinLeaveUpstream(croute, 0);
> +
> +-        // Clear memory, and set pointer to next route...
> +-        free(croute);
> ++        rtable_remove(croute);
> +     }
> +-    routing_table = NULL;
> +
> +     // Send a notice that the routing table is empty...
> +     my_log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");
> +@@ -246,15 +276,10 @@ void clearAllRoutes(void) {
> + *   Route Descriptor.
> + */
> + static struct RouteTable *findRoute(uint32_t group) {
> +-    struct RouteTable*  croute;
> ++    struct RouteTable       key;
> +
> +-    for(croute = routing_table; croute; croute = croute->nextroute) {
> +-        if(croute->group == group) {
> +-            return croute;
> +-        }
> +-    }
> +-
> +-    return NULL;
> ++    key.group = group;
> ++    return (RB_FIND(rtabletree, &routing_table, &key));
> + }
> +
> + /**
> +@@ -293,10 +318,8 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
> +         newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable) + 
> (conf->fastUpstreamLeave ? conf->downstreamHostsHashTableSize : 0));
> +         // Insert the route desc and clear all pointers...
> +         newroute->group      = group;
> +-        memset(newroute->originAddrs, 0, MAX_ORIGINS * 
> sizeof(newroute->originAddrs[0]));
> +-        newroute->nextroute  = NULL;
> +-        newroute->prevroute  = NULL;
> +         newroute->upstrVif   = -1;
> ++        TAILQ_INIT(&newroute->originList);
> +
> +         if(conf->fastUpstreamLeave) {
> +             // Init downstream hosts bit hash table
> +@@ -321,54 +344,13 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
> +             BIT_SET(newroute->vifBits, ifx);
> +         }
> +
> +-        // Check if there is a table already....
> +-        if(routing_table == NULL) {
> +-            // No location set, so insert in on the table top.
> +-            routing_table = newroute;
> +-            my_log(LOG_DEBUG, 0, "No routes in table. Insert at 
> beginning.");
> +-        } else {
> +-
> +-            my_log(LOG_DEBUG, 0, "Found existing routes. Find insert 
> location.");
> +-
> +-            // Check if the route could be inserted at the beginning...
> +-            if(routing_table->group > group) {
> +-                my_log(LOG_DEBUG, 0, "Inserting at beginning, before route 
> %s",inetFmt(routing_table->group,s1));
> +-
> +-                // Insert at beginning...
> +-                newroute->nextroute = routing_table;
> +-                newroute->prevroute = NULL;
> +-                routing_table = newroute;
> +-
> +-                // If the route has a next node, the previous pointer must 
> be updated.
> +-                if(newroute->nextroute != NULL) {
> +-                    newroute->nextroute->prevroute = newroute;
> +-                }
> +-
> +-            } else {
> +-
> +-                // Find the location which is closest to the route.
> +-                for( croute = routing_table; croute->nextroute != NULL; 
> croute = croute->nextroute ) {
> +-                    // Find insert position.
> +-                    if(croute->nextroute->group > group) {
> +-                        break;
> +-                    }
> +-                }
> +-
> +-                my_log(LOG_DEBUG, 0, "Inserting after route 
> %s",inetFmt(croute->group,s1));
> +-
> +-                // Insert after current...
> +-                newroute->nextroute = croute->nextroute;
> +-                newroute->prevroute = croute;
> +-                if(croute->nextroute != NULL) {
> +-                    croute->nextroute->prevroute = newroute;
> +-                }
> +-                croute->nextroute = newroute;
> +-            }
> ++        if ((croute = rtable_add(newroute)) != NULL)
> ++            free(newroute);
> ++        else {
> ++            // Set the new route as the current...
> ++            croute = newroute;
> +         }
> +
> +-        // Set the new route as the current...
> +-        croute = newroute;
> +-
> +         // Log the cleanup in debugmode...
> +         my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
> +             inetFmt(croute->group, s1),ifx);
> +@@ -391,7 +373,7 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
> +             inetFmt(croute->group, s1), ifx);
> +
> +         // Update route in kernel...
> +-        if(!internUpdateKernelRoute(croute, 1)) {
> ++        if(!internUpdateKernelRoute(croute, 1, NULL)) {
> +             my_log(LOG_WARNING, 0, "The insertion into Kernel failed.");
> +             return 0;
> +         }
> +@@ -413,7 +395,7 @@ int insertRoute(uint32_t group, int ifx, uint32_t src)
> + *   activated, it's reinstalled in the kernel. If
> + *   the route is activated, no originAddr is needed.
> + */
> +-int activateRoute(uint32_t group, uint32_t originAddr, int upstrVif) {
> ++int activateRoute(uint32_t group, uint32_t originAddr, int downIf) {
> +     struct RouteTable*  croute;
> +     int result = 0;
> +
> +@@ -432,43 +414,37 @@ int activateRoute(uint32_t group, uint32_t originAddr,
> +     }
> +
> +     if(croute != NULL) {
> ++        struct Origin *o = NULL;
> ++        int found = 0;
> ++
> +         // If the origin address is set, update the route data.
> +         if(originAddr > 0) {
> +-            // find this origin, or an unused slot
> +-            int i;
> +-            for (i = 0; i < MAX_ORIGINS; i++) {
> +-                // unused slots are at the bottom, so we can't miss this 
> origin
> +-                if (croute->originAddrs[i] == originAddr || 
> croute->originAddrs[i] == 0) {
> ++            TAILQ_FOREACH(o, &croute->originList, next) {
> ++                my_log(LOG_INFO, 0, "Origin for route %s have %s, new %s",
> ++                    inetFmt(croute->group, s1),
> ++                    inetFmt(o->originAddr, s2),
> ++                    inetFmt(originAddr, s3));
> ++                if (o->originAddr==originAddr) {
> ++                    found++;
> +                     break;
> +                 }
> +             }
> +-
> +-            if (i == MAX_ORIGINS) {
> +-                i = MAX_ORIGINS - 1;
> +-
> +-                my_log(LOG_WARNING, 0, "Too many origins for route %s; 
> replacing %s with %s",
> ++            if (!found) {
> ++                my_log(LOG_NOTICE, 0, "New origin for route %s is %s, flood 
> %d",
> +                     inetFmt(croute->group, s1),
> +-                    inetFmt(croute->originAddrs[i], s2),
> +-                    inetFmt(originAddr, s3));
> ++                    inetFmt(originAddr, s3), downIf);
> ++                o = malloc(sizeof(*o));
> ++                o->originAddr = originAddr;
> ++                o->flood = downIf;
> ++                o->pktcnt = 0;
> ++                TAILQ_INSERT_TAIL(&croute->originList, o, next);
> ++            } else {
> ++                my_log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt 
> %d",
> ++                    inetFmt(croute->group, s1),
> ++                    inetFmt(o->originAddr, s3),
> ++                    o->pktcnt);
> +             }
> +-
> +-            // set origin
> +-            croute->originAddrs[i] = originAddr;
> +-
> +-            // move it to the top
> +-            while (i > 0) {
> +-                uint32_t t = croute->originAddrs[i - 1];
> +-                croute->originAddrs[i - 1] = croute->originAddrs[i];
> +-                croute->originAddrs[i] = t;
> +-                i--;
> +-            }
> +         }
> +-        croute->upstrVif = upstrVif;
> +-
> +-        // Only update kernel table if there are listeners !
> +-        if(croute->vifBits > 0) {
> +-            result = internUpdateKernelRoute(croute, 1);
> +-        }
> +     }
> +     logRouteTable("Activate Route");
> +
> +@@ -485,12 +461,7 @@ void ageActiveRoutes(void) {
> +
> +     my_log(LOG_DEBUG, 0, "Aging routes in table.");
> +
> +-    // Scan all routes...
> +-    for( croute = routing_table; croute != NULL; croute = nroute ) {
> +-
> +-        // Keep the next route (since current route may be removed)...
> +-        nroute = croute->nextroute;
> +-
> ++    RB_FOREACH_SAFE(croute, rtabletree, &routing_table, nroute) {
> +         // Run the aging round algorithm.
> +         if(croute->upstrState != ROUTESTATE_CHECK_LAST_MEMBER) {
> +             // Only age routes if Last member probe is not active...
> +@@ -602,7 +573,7 @@ static int removeRoute(struct RouteTable*  croute) {
> +     //BIT_ZERO(croute->vifBits);
> +
> +     // Uninstall current route from kernel
> +-    if(!internUpdateKernelRoute(croute, 0)) {
> ++    if(!internUpdateKernelRoute(croute, 0, NULL)) {
> +         my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
> +         result = 0;
> +     }
> +@@ -614,24 +585,8 @@ static int removeRoute(struct RouteTable*  croute) {
> +         sendJoinLeaveUpstream(croute, 0);
> +     }
> +
> +-    // Update pointers...
> +-    if(croute->prevroute == NULL) {
> +-        // Topmost node...
> +-        if(croute->nextroute != NULL) {
> +-            croute->nextroute->prevroute = NULL;
> +-        }
> +-        routing_table = croute->nextroute;
> ++    rtable_remove(croute);
> +
> +-    } else {
> +-        croute->prevroute->nextroute = croute->nextroute;
> +-        if(croute->nextroute != NULL) {
> +-            croute->nextroute->prevroute = croute->prevroute;
> +-        }
> +-    }
> +-    // Free the memory, and set the route to NULL...
> +-    free(croute);
> +-    croute = NULL;
> +-
> +     logRouteTable("Remove route");
> +
> +     return result;
> +@@ -676,6 +631,37 @@ int internAgeRoute(struct RouteTable*  croute) {
> +         }
> +     }
> +
> ++    {
> ++        struct Origin *o, *nxt;
> ++        struct sioc_sg_req sg_req;
> ++
> ++        sg_req.grp.s_addr = croute->group;
> ++        for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) {
> ++            nxt = TAILQ_NEXT(o, next);
> ++            sg_req.src.s_addr = o->originAddr;
> ++            if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) {
> ++                my_log(LOG_WARNING, errno, "%s (%s %s)",
> ++                        "age_table_entry: SIOCGETSGCNT failing for",
> ++                        inetFmt(o->originAddr, s1),
> ++                        inetFmt(croute->group, s2));
> ++                /* Make sure it gets deleted below */
> ++                sg_req.pktcnt = o->pktcnt;
> ++            }
> ++            my_log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d",
> ++                    inetFmt(o->originAddr, s1), inetFmt(croute->group, s2),
> ++            o->pktcnt, sg_req.pktcnt);
> ++            if (sg_req.pktcnt == o->pktcnt) {
> ++                /* no traffic, remove from kernel cache */
> ++                internUpdateKernelRoute(croute, 0, o);
> ++                TAILQ_REMOVE(&croute->originList, o, next);
> ++                free(o);
> ++            } else {
> ++                o->pktcnt = sg_req.pktcnt;
> ++            }
> ++        }
> ++    }
> ++
> ++
> +     // If the aging counter has reached zero, its time for updating...
> +     if(croute->ageValue == 0) {
> +         // Check for activity in the aging process,
> +@@ -685,7 +671,7 @@ int internAgeRoute(struct RouteTable*  croute) {
> +                          inetFmt(croute->group,s1));
> +
> +             // Just update the routing settings in kernel...
> +-            internUpdateKernelRoute(croute, 1);
> ++            internUpdateKernelRoute(croute, 1, NULL);
> +
> +             // We append the activity counter to the age, and continue...
> +             croute->ageValue = croute->ageActivity;
> +@@ -711,39 +697,61 @@ int internAgeRoute(struct RouteTable*  croute) {
> + /**
> + *   Updates the Kernel routing table. If activate is 1, the route
> + *   is (re-)activated. If activate is false, the route is removed.
> ++*   if 'origin' is given, only the route with 'origin' will be
> ++*   updated, otherwise all MFC routes for the group will updated.
> + */
> +-int internUpdateKernelRoute(struct RouteTable *route, int activate) {
> ++int internUpdateKernelRoute(struct RouteTable *route, int activate, struct 
> Origin *origin) {
> +     struct   MRouteDesc mrDesc;
> +     struct   IfDesc     *Dp;
> +     unsigned            Ix;
> +-    int i;
> ++    struct Origin *o;
> +
> +-    for (i = 0; i < MAX_ORIGINS; i++) {
> +-        if (route->originAddrs[i] == 0 || route->upstrVif == -1) {
> ++    if (TAILQ_EMPTY(&route->originList)) {
> ++        my_log(LOG_NOTICE, 0, "Route is not active. No kernel updates 
> done.");
> ++        return 1;
> ++    }
> ++
> ++    TAILQ_FOREACH(o, &route->originList, next) {
> ++        if (origin && origin != o)
> +             continue;
> +-        }
> +
> +         // Build route descriptor from table entry...
> +         // Set the source address and group address...
> +         mrDesc.McAdr.s_addr     = route->group;
> +-        mrDesc.OriginAdr.s_addr = route->originAddrs[i];
> ++        mrDesc.OriginAdr.s_addr = o->originAddr;
> +
> +         // clear output interfaces
> +         memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
> +
> +-        my_log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
> ++        my_log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", 
> inetFmt(o->originAddr, s1), route->vifBits);
> +
> +         mrDesc.InVif = route->upstrVif;
> +
> +         // Set the TTL's for the route descriptor...
> +-        for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
> +-            if(Dp->state == IF_STATE_UPSTREAM) {
> +-                continue;
> ++        for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) {
> ++            if (o->flood >= 0) {
> ++                if(Ix == o->flood) {
> ++                    my_log(LOG_DEBUG, 0, "Identified Input VIF #%d as 
> DOWNSTREAM.", Dp->index);
> ++                    mrDesc.InVif = Dp->index;
> ++                }
> ++                else if(Dp->state == IF_STATE_UPSTREAM) {
> ++                    my_log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif %d 
> to %d", Dp->index, Dp->threshold);
> ++                    mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> ++                }
> ++                else if(BIT_TST(route->vifBits, Dp->index)) {
> ++                    my_log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM Vif %d 
> to %d", Dp->index, Dp->threshold);
> ++                    mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> ++                }
> ++                } else {
> ++                if(Dp->state == IF_STATE_UPSTREAM) {
> ++                    my_log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", 
> Dp->index);
> ++                    mrDesc.InVif = Dp->index;
> ++                }
> ++                else if(BIT_TST(route->vifBits, Dp->index)) {
> ++                    my_log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", 
> Dp->index, Dp->threshold);
> ++                    mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> ++                }
> +             }
> +-            else if(BIT_TST(route->vifBits, Dp->index)) {
> +-                my_log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", 
> Dp->index, Dp->threshold);
> +-                mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
> +-            }
> +         }
> +
> +         // Do the actual Kernel route update...
> +@@ -765,7 +773,7 @@ int internUpdateKernelRoute(struct RouteTable *route,
> + */
> + void logRouteTable(const char *header) {
> +         struct Config       *conf = getCommonConfig();
> +-        struct RouteTable   *croute = routing_table;
> ++        struct RouteTable   *croute = RB_ROOT(&routing_table);
> +         unsigned            rcount = 0;
> +
> +         my_log(LOG_DEBUG, 0, "");
> +@@ -774,30 +782,22 @@ void logRouteTable(const char *header) {
> +         if(croute==NULL) {
> +             my_log(LOG_DEBUG, 0, "No routes in table...");
> +         } else {
> +-            do {
> +-                char st = 'I';
> +-                char src[MAX_ORIGINS * 30 + 1];
> +-                src[0] = '\0';
> +-                int i;
> +-
> +-                for (i = 0; i < MAX_ORIGINS; i++) {
> +-                    if (croute->originAddrs[i] == 0) {
> +-                        continue;
> +-                    }
> +-                    st = 'A';
> +-                    sprintf(src + strlen(src), "Src%d: %s, ", i, 
> inetFmt(croute->originAddrs[i], s1));
> +-                }
> +-
> +-                my_log(LOG_DEBUG, 0, "#%d: %sDst: %s, Age:%d, St: %c, 
> OutVifs: 0x%08x, dHosts: %s",
> +-                    rcount, src, inetFmt(croute->group, s2),
> +-                    croute->ageValue, st,
> ++            RB_FOREACH(croute, rtabletree, &routing_table) {
> ++                my_log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, 
> OutVifs: 0x%08x, dHosts: %s",
> ++                    rcount, inetFmt(croute->group, s2),
> ++                    croute->ageValue,
> ++                    (TAILQ_EMPTY(&croute->originList) ? "I":"A"),
> +                     croute->vifBits,
> +                     !conf->fastUpstreamLeave ? "not tracked" : 
> testNoDownstreamHost(conf, croute) ? "no" : "yes");
> +-
> +-                croute = croute->nextroute;
> +-
> ++                {
> ++                    struct Origin *o;
> ++                    TAILQ_FOREACH(o, &croute->originList, next) {
> ++                        my_log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d 
> pktcnt %d",
> ++                            rcount, inetFmt(o->originAddr, s1), o->flood, 
> o->pktcnt);
> ++                    }
> ++                }
> +                 rcount++;
> +-            } while ( croute != NULL );
> ++            }
> +         }
> +
> +         my_log(LOG_DEBUG, 0, 
> "-----------------------------------------------------");
> Index: patches/patch-udpsock_c
> ===================================================================
> RCS file: patches/patch-udpsock_c
> diff -N patches/patch-udpsock_c
> --- patches/patch-udpsock_c     8 Feb 2008 19:30:51 -0000       1.1.1.1
> +++ /dev/null   1 Jan 1970 00:00:00 -0000
> @@ -1,12 +0,0 @@
> -$OpenBSD: patch-udpsock_c,v 1.1.1.1 2008/02/08 19:30:51 sthen Exp $
> ---- udpsock.c.orig     Sat Aug 20 13:35:00 2005
> -+++ udpsock.c  Mon Nov 19 12:56:50 2007
> -@@ -58,7 +58,7 @@ int openUdpSocket( uint32 PeerInAdr, uint16 PeerPort )
> -     memset( &SockAdr.sin_zero, 0, sizeof( SockAdr.sin_zero ) );
> -
> -     if( connect( Sock, (struct sockaddr *)&SockAdr, sizeof( SockAdr ) ) )
> --        log( LOG_ERR, errno, "UDP socket connect" );
> -+        log( LOG_ERR, errno, "UDP socket connect (port %d)", PeerPort);
> -
> -     return Sock;
> - }
> Index: pkg/PLIST
> ===================================================================
> RCS file: /cvs/ports/net/igmpproxy/pkg/PLIST,v
> retrieving revision 1.4
> diff -u -p -r1.4 PLIST
> --- pkg/PLIST   4 Sep 2018 12:46:17 -0000       1.4
> +++ pkg/PLIST   12 Jan 2021 10:59:19 -0000
> @@ -1,4 +1,5 @@
>  @comment $OpenBSD: PLIST,v 1.4 2018/09/04 12:46:17 espie Exp $
> +@rcscript ${RCDIR}/igmpproxy
>  @man man/man5/igmpproxy.conf.5
>  @man man/man8/igmpproxy.8
>  @bin sbin/igmpproxy
> @@ -6,4 +7,3 @@ share/doc/pkg-readmes/${PKGSTEM}
>  share/examples/igmpproxy/
>  share/examples/igmpproxy/igmpproxy.conf
>  @sample ${SYSCONFDIR}/igmpproxy.conf
> -@rcscript ${RCDIR}/igmpproxy
>

Reply via email to