# This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # igmpproxy # igmpproxy/Makefile # igmpproxy/pkg-descr # igmpproxy/distinfo # igmpproxy/files # igmpproxy/files/patch-fbsd # igmpproxy/files/igmpproxy # echo c - igmpproxy mkdir -p igmpproxy > /dev/null 2>&1 echo x - igmpproxy/Makefile sed 's/^X//' >igmpproxy/Makefile << 'END-of-igmpproxy/Makefile' X# New ports collection makefile for: igmpproxy X# Date created: 5 January 2009 X# Whom: asami X# X# $FreeBSD$ X# X XPORTNAME= igmpproxy XPORTVERSION= 0.1 X#PORTREVISION= 2 XCATEGORIES= net XMASTER_SITES= ${MASTER_SITE_SOURCEFORGE} XMASTER_SITE_SUBDIR= ${PORTNAME} XDISTNAME= ${PORTNAME}-src-${PORTVERSION}-beta2 X XMAINTAINER= melifaro@ipfw.ru XCOMMENT= Multicast router utilizing IGMP forwarding X XHOMEPAGE = http://igmpproxy.sourceforge.net/ XWRKSRC= ${WRKDIR}/igmpproxy/src X XMAN5= igmpproxy.conf.5 XMAN8= igmpproxy.8 X XPLIST_FILES= sbin/igmpproxy \ X etc/igmpproxy.conf.sample \ X etc/rc.d/igmpproxy X Xdo-install: X ${INSTALL_PROGRAM} ${WRKSRC}/igmpproxy ${PREFIX}/sbin X ${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.8 ${PREFIX}/man/man8 X ${INSTALL_MAN} ${WRKSRC}/../doc/igmpproxy.conf.5 ${PREFIX}/man/man5 X ${INSTALL_DATA} ${WRKSRC}/igmpproxy.conf ${PREFIX}/etc/igmpproxy.conf.sample X ${INSTALL_SCRIPT} ${FILESDIR}/igmpproxy ${PREFIX}/etc/rc.d X X.include END-of-igmpproxy/Makefile echo x - igmpproxy/pkg-descr sed 's/^X//' >igmpproxy/pkg-descr << 'END-of-igmpproxy/pkg-descr' Xigmpproxy is a simple multicast routing daemon based on mrouted. It uses IGMP Xforwarding to dynamically route multicast traffic. XReqiures multicast forwarding enabled X XWWW: http://igmpproxy.sourceforge.net/ END-of-igmpproxy/pkg-descr echo x - igmpproxy/distinfo sed 's/^X//' >igmpproxy/distinfo << 'END-of-igmpproxy/distinfo' XMD5 (igmpproxy-src-0.1-beta2.tar.gz) = 2a5a59480f44d4b14077a6b5319e9940 XSHA256 (igmpproxy-src-0.1-beta2.tar.gz) = 7f6e5486e84827150c8ca402967c96334bbd62b9f785195c4ee84da1218abb40 XSIZE (igmpproxy-src-0.1-beta2.tar.gz) = 35103 END-of-igmpproxy/distinfo echo c - igmpproxy/files mkdir -p igmpproxy/files > /dev/null 2>&1 echo x - igmpproxy/files/patch-fbsd sed 's/^X//' >igmpproxy/files/patch-fbsd << 'END-of-igmpproxy/files/patch-fbsd' Xdiff -urN Makefile igmpproxy.new/src/Makefile X--- Makefile 2005-08-20 16:34:18.000000000 +0400 X+++ igmpproxy.new/src/Makefile 2009-01-05 02:35:56.000000000 +0300 X@@ -1,12 +1,12 @@ X X #BINDIR=../bin X BINDIR=/usr/local/bin X-ETCDIR=/etc X-MANDIR=/usr/share/man X+ETCDIR=/usr/local/etc X+MANDIR=/usr/local/man X X X # CFLAGS=-g X-CFLAGS=-O X+CFLAGS+=-O2 -Wall -Wextra -fno-builtin-log X X default : build.h igmpproxy X X@@ -21,8 +21,11 @@ X cp ../doc/igmpproxy.conf.5 ${MANDIR}/man5 X if [ ! -e ${ETCDIR}/igmpproxy.conf ]; then cp igmpproxy.conf ${ETCDIR}; fi X X-igmpproxy : igmpproxy.o config.o confread.o request.o udpsock.o mcgroup.o rttable.o \ X- igmp.o ifvc.o callout.o kern.o syslog.o lib.o mroute-api.o X+SRC = igmpproxy.c config.c confread.c request.c mcgroup.c rttable.c \ X+ igmp.c ifvc.c callout.c kern.c syslog.c lib.c mroute-api.c X+OBJS = ${SRC:.c=.o} X+igmpproxy: build.h ${OBJS} X+ cc ${CFLAGS} ${OBJS} -o igmpproxy X X build.h : X echo '#define BUILD "' `date +%y%m%d` '"' >build.h Xdiff -urN config.c igmpproxy.new/src/config.c X--- config.c 2005-05-24 19:49:29.000000000 +0400 X+++ igmpproxy.new/src/config.c 2009-01-05 01:58:27.000000000 +0300 X@@ -177,7 +177,7 @@ X } X X // Loop through all VIFs... X- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) { X X // Now try to find a matching config... X@@ -255,7 +255,7 @@ X while(token != NULL) { X if(strcmp("altnet", token)==0) { X // Altnet... X- struct in_addr networkAddr; X+ //struct in_addr networkAddr; X X token = nextConfigToken(); X IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Got altnet token %s.",token); X@@ -347,7 +347,7 @@ X mask <<= (32 - bitcnt); X } X X- if(addr == -1 || addr == 0) { X+ if(addr == (uint32) -1 || addr == 0) { X log(LOG_WARNING, 0, "Unable to parse address token '%s'.", addrstr); X return NULL; X } Xdiff -urN defs.h igmpproxy.new/src/defs.h X--- defs.h 2005-08-20 16:44:47.000000000 +0400 X+++ igmpproxy.new/src/defs.h 2009-01-05 02:10:11.000000000 +0300 X@@ -40,10 +40,18 @@ X #include X #include X #include X- X #include X+ X+#ifdef __FreeBSD__ X+#include X+#include X+#include X+#include X+ X+#else X #include X #include X+#endif X X #include X X@@ -52,15 +60,24 @@ X #include X #include X #else X+#ifdef __FreeBSD__ X+ #include X+ #include X+ #include X+#else X #include X #include X+#endif X #include X #include X #endif X X- X // The default path for the config file... X+#ifdef __FreeBSD__ X+#define IGMPPROXY_CONFIG_FILEPATH "/usr/local/etc/igmpproxy.conf" X+#else X #define IGMPPROXY_CONFIG_FILEPATH "/etc/igmpproxy.conf" X+#endif X #define ENABLE_DEBUG 1 X X /* X@@ -72,9 +89,31 @@ X X #define MAX_MC_VIFS 32 // !!! check this const in the specific includes X X+#ifndef IGMP_MEMBERSHIP_QUERY X+#define IGMP_MEMBERSHIP_QUERY IGMP_HOST_MEMBERSHIP_QUERY X+#endif X+#ifndef IGMP_V1_MEMBERSHIP_REPORT X+#define IGMP_V1_MEMBERSHIP_REPORT IGMP_v1_HOST_MEMBERSHIP_REPORT X+#endif X+#ifndef IGMP_V2_MEMBERSHIP_REPORT X+#define IGMP_V2_MEMBERSHIP_REPORT IGMP_v2_HOST_MEMBERSHIP_REPORT X+#endif X+#ifndef IGMP_V2_LEAVE_GROUP X+#define IGMP_V2_LEAVE_GROUP IGMP_HOST_LEAVE_MESSAGE X+#endif X+ X+#ifndef INADDR_ALLRTRS_GROUP X+/* address for multicast mtrace msg */ X+#define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */ X+#endif X+ X // Useful macros.. X+#ifndef MIN X #define MIN( a, b ) ((a) < (b) ? (a) : (b)) X+#endif X+#ifndef MAX X #define MAX( a, b ) ((a) < (b) ? (b) : (a)) X+#endif X #define VCMC( Vc ) (sizeof( Vc ) / sizeof( (Vc)[ 0 ] )) X #define VCEP( Vc ) (&(Vc)[ VCMC( Vc ) ]) X X@@ -126,7 +165,12 @@ X X #define IF_DEBUG if(Log2Stderr & LOG_DEBUG) X X-void log( int Serverity, int Errno, const char *FmtSt, ... ); X+#ifdef DEVEL_LOGGING X+#define log(Severity, Errno, Fmt, args...) _log((Severity), (Errno), __FUNCTION__, __LINE__, (Fmt), ##args) X+void _log( int Serverity, int Errno, const char *func, int line, const char *FmtSt, ...); X+#else X+void log( int Serverity, int Errno, const char *FmtSt, ...); X+#endif X X /* ifvc.c X */ X@@ -196,6 +240,7 @@ X struct IfDesc *getIfByName( const char *IfName ); X struct IfDesc *getIfByIx( unsigned Ix ); X struct IfDesc *getIfByAddress( uint32 Ix ); X+int isAdressValidForIf( struct IfDesc* intrface, uint32 ipaddr ); X X /* mroute-api.c X */ X@@ -235,7 +280,7 @@ X char *fmtInAdr( char *St, struct in_addr InAdr ); X char *inetFmt(uint32 addr, char *s); X char *inetFmts(uint32 addr, uint32 mask, char *s); X-int inetCksum(u_short *addr, u_int len); X+int inetChksum(u_short *addr, u_int len); X X /* kern.c X */ X@@ -264,7 +309,7 @@ X void initRouteTable(); X void clearAllRoutes(); X int insertRoute(uint32 group, int ifx); X-int activateRoute(uint32 group, uint32 originAddr); X+int activateRoute(uint32 group, uint32 originAddr, int downIf); X void ageActiveRoutes(); X void setRouteLastMemberMode(uint32 group); X int lastMemberGroupAge(uint32 group); Xdiff -urN ifvc.c igmpproxy.new/src/ifvc.c X--- ifvc.c 2005-05-24 19:49:18.000000000 +0400 X+++ igmpproxy.new/src/ifvc.c 2009-01-05 02:24:02.000000000 +0300 X@@ -32,7 +32,11 @@ X */ X X #include "defs.h" X+#ifdef __FreeBSD__ X+#include X+#else X #include X+#endif X X struct IfDesc IfDescVc[ MAX_IF ], *IfDescEp = IfDescVc; X X@@ -42,119 +46,91 @@ X ** X */ X void buildIfVc() { X- struct ifreq IfVc[ sizeof( IfDescVc ) / sizeof( IfDescVc[ 0 ] ) ]; X- struct ifreq *IfEp; X+ struct ifaddrs *ifap, *ifa; X+ struct IfDesc *ifp; X+ struct SubnetList *net; X X- int Sock; X- X- if ( (Sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) X- log( LOG_ERR, errno, "RAW socket open" ); X- X- /* get If vector X- */ X- { X- struct ifconf IoCtlReq; X- X- IoCtlReq.ifc_buf = (void *)IfVc; X- IoCtlReq.ifc_len = sizeof( IfVc ); X- X- if ( ioctl( Sock, SIOCGIFCONF, &IoCtlReq ) < 0 ) X- log( LOG_ERR, errno, "ioctl SIOCGIFCONF" ); X- X- IfEp = (void *)((char *)IfVc + IoCtlReq.ifc_len); X- } X+ if (getifaddrs(&ifap) < 0) X+ log( LOG_ERR, errno, "getifaddrs" ); X X /* loop over interfaces and copy interface info to IfDescVc X */ X { X- struct ifreq *IfPt; X- struct IfDesc *IfDp; X- X // Temp keepers of interface params... X uint32 addr, subnet, mask; X X- for ( IfPt = IfVc; IfPt < IfEp; IfPt++ ) { X- struct ifreq IfReq; X+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) { X char FmtBu[ 32 ]; X X- strncpy( IfDescEp->Name, IfPt->ifr_name, sizeof( IfDescEp->Name ) ); X- X- // Currently don't set any allowed nets... X- //IfDescEp->allowednets = NULL; X- X- // Set the index to -1 by default. X- IfDescEp->index = -1; X+ if (IfDescEp >= &IfDescVc[ MAX_IF ]) { X+ log(LOG_WARNING, 0, "Too many interfaces, skipping %d", ifa->ifa_name); X+ continue; X+ } X X- /* don't retrieve more info for non-IP interfaces X+ /* ignore non-IP interfaces X */ X- if ( IfPt->ifr_addr.sa_family != AF_INET ) { X- IfDescEp->InAdr.s_addr = 0; /* mark as non-IP interface */ X- IfDescEp++; X+ if ( ifa->ifa_addr->sa_family != AF_INET ) X continue; X- } X- X- // Get the interface adress... X- IfDescEp->InAdr = ((struct sockaddr_in *)&IfPt->ifr_addr)->sin_addr; X- addr = IfDescEp->InAdr.s_addr; X- X- memcpy( IfReq.ifr_name, IfDescEp->Name, sizeof( IfReq.ifr_name ) ); X- X- // Get the subnet mask... X- if (ioctl(Sock, SIOCGIFNETMASK, &IfReq ) < 0) X- log(LOG_ERR, errno, "ioctl SIOCGIFNETMASK for %s", IfReq.ifr_name); X- mask = ((struct sockaddr_in *)&IfReq.ifr_addr)->sin_addr.s_addr; X- subnet = addr & mask; X X- // Get the physical index of the Interface X- if (ioctl(Sock, SIOCGIFINDEX, &IfReq ) < 0) X- log(LOG_ERR, errno, "ioctl SIOCGIFINDEX for %s", IfReq.ifr_name); X- X- log(LOG_DEBUG, 0, "Physical Index value of IF '%s' is %d", X- IfDescEp->Name, IfReq.ifr_ifindex); X+ if ((ifp = getIfByName(ifa->ifa_name)) == NULL) { X X+ strlcpy( IfDescEp->Name, ifa->ifa_name, sizeof( IfDescEp->Name ) ); X X- /* get if flags X- ** X- ** typical flags: X- ** lo 0x0049 -> Running, Loopback, Up X- ** ethx 0x1043 -> Multicast, Running, Broadcast, Up X- ** ipppx 0x0091 -> NoArp, PointToPoint, Up X- ** grex 0x00C1 -> NoArp, Running, Up X- ** ipipx 0x00C1 -> NoArp, Running, Up X- */ X- if ( ioctl( Sock, SIOCGIFFLAGS, &IfReq ) < 0 ) X- log( LOG_ERR, errno, "ioctl SIOCGIFFLAGS" ); X+ log(LOG_DEBUG, 0, "Adding Physical Index value of IF '%s' is %d", X+ IfDescEp->Name, if_nametoindex(IfDescEp->Name)); X X- IfDescEp->Flags = IfReq.ifr_flags; X+ // Set the index to -1 by default. X+ IfDescEp->index = -1; X+ X+ // Get the interface adress... X+ IfDescEp->InAdr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; X+ X+ /* get if flags X+ ** X+ ** typical flags: X+ ** lo 0x0049 -> Running, Loopback, Up X+ ** ethx 0x1043 -> Multicast, Running, Broadcast, Up X+ ** ipppx 0x0091 -> NoArp, PointToPoint, Up X+ ** grex 0x00C1 -> NoArp, Running, Up X+ ** ipipx 0x00C1 -> NoArp, Running, Up X+ */ X+ X+ IfDescEp->Flags = ifa->ifa_flags; X+ X+ // Set the default params for the IF... X+ IfDescEp->state = IF_STATE_DOWNSTREAM; X+ IfDescEp->robustness = DEFAULT_ROBUSTNESS; X+ IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */ X+ IfDescEp->ratelimit = DEFAULT_RATELIMIT; X+ IfDescEp->allowednets = NULL; X+ ifp = IfDescEp++; X+ } X X // Insert the verified subnet as an allowed net... X- IfDescEp->allowednets = (struct SubnetList *)malloc(sizeof(struct SubnetList)); X- if(IfDescEp->allowednets == NULL) log(LOG_ERR, 0, "Out of memory !"); X+ addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; X+ mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr; X+ subnet = addr & mask; X+ X+ net = (struct SubnetList *)malloc(sizeof(struct SubnetList)); X+ if(net == NULL) log(LOG_ERR, 0, "Out of memory !"); X X // Create the network address for the IF.. X- IfDescEp->allowednets->next = NULL; X- IfDescEp->allowednets->subnet_mask = mask; X- IfDescEp->allowednets->subnet_addr = subnet; X- X- // Set the default params for the IF... X- IfDescEp->state = IF_STATE_DOWNSTREAM; X- IfDescEp->robustness = DEFAULT_ROBUSTNESS; X- IfDescEp->threshold = DEFAULT_THRESHOLD; /* ttl limit */ X- IfDescEp->ratelimit = DEFAULT_RATELIMIT; X+ net->next = ifp->allowednets; X+ net->subnet_mask = mask; X+ net->subnet_addr = subnet; X+ ifp->allowednets = net; X X- X // Debug log the result... X IF_DEBUG log( LOG_DEBUG, 0, "buildIfVc: Interface %s Addr: %s, Flags: 0x%04x, Network: %s", X- IfDescEp->Name, X- fmtInAdr( FmtBu, IfDescEp->InAdr ), X- IfDescEp->Flags, X+ ifp->Name, X+ fmtInAdr( FmtBu, ifp->InAdr ), X+ ifp->Flags, X inetFmts(subnet,mask, s1)); X X- IfDescEp++; X } X- } X X- close( Sock ); X+ } X+ freeifaddrs(ifap); X } X X /* Xdiff -urN igmp.c igmpproxy.new/src/igmp.c X--- igmp.c 2005-05-24 19:49:16.000000000 +0400 X+++ igmpproxy.new/src/igmp.c 2009-01-05 02:08:19.000000000 +0300 X@@ -105,7 +105,7 @@ X struct igmp *igmp; X int ipdatalen, iphdrlen, igmpdatalen; X X- if (recvlen < sizeof(struct ip)) { X+ if (recvlen < (int) sizeof(struct ip)) { X log(LOG_WARNING, 0, X "received packet too short (%u bytes) for IP header", recvlen); X return; X@@ -128,6 +128,7 @@ X } X else { X struct IfDesc *checkVIF; X+ int downIf = -1; X X // Check if the source address matches a valid address on upstream vif. X checkVIF = getIfByIx( upStreamVif ); X@@ -141,23 +142,44 @@ X return; X } X else if(!isAdressValidForIf(checkVIF, src)) { X- log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.", X- inetFmt(src, s1), inetFmt(dst, s2)); X- return; X+ unsigned Ix; X+ struct IfDesc *Dp; X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X+ if ((Dp->state == IF_STATE_DOWNSTREAM) &&isAdressValidForIf(Dp, src)) { X+ downIf = Ix; X+ break; X+ } X+ } X+ X+ if (downIf == -1) { X+ log(LOG_WARNING, 0, "The source address %s for group %s, is not in any valid net for upstream VIF.", X+ inetFmt(src, s1), inetFmt(dst, s2)); X+ return; X+ } else { X+ log(LOG_NOTICE, 0, "The source address %s for group %s, is valid DOWNSTREAM VIF #%d.", X+ inetFmt(src, s1), inetFmt(dst, s2), downIf); X+ } X } X X // Activate the route. X- IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to %s", X- inetFmt(src,s1), inetFmt(dst,s2)); X- activateRoute(dst, src); X+ IF_DEBUG log(LOG_DEBUG, 0, "Route activate request from %s to %s, downIf %d", X+ inetFmt(src,s1), inetFmt(dst,s2), downIf); X+ activateRoute(dst, src, downIf); X X X } X return; X } X X+ log(LOG_DEBUG, 0, "Packet from %s: proto: %d hdrlen: %d iplen: %d or %d", X+ inetFmt(src, s1), ip->ip_p, ip->ip_hl << 2, ip->ip_len, ntohs(ip->ip_len)); X+ X iphdrlen = ip->ip_hl << 2; X+#ifdef RAW_INPUT_IS_RAW X ipdatalen = ntohs(ip->ip_len) - iphdrlen; X+#else X+ ipdatalen = ip->ip_len; X+#endif X X if (iphdrlen + ipdatalen != recvlen) { X log(LOG_WARNING, 0, X@@ -176,9 +198,9 @@ X return; X } X X- log(LOG_NOTICE, 0, "RECV %s from %-15s to %s", X+ log(LOG_NOTICE, 0, "RECV %s from %-15s to %s (ip_hl %d, data %d)", X igmpPacketKind(igmp->igmp_type, igmp->igmp_code), X- inetFmt(src, s1), inetFmt(dst, s2) ); X+ inetFmt(src, s1), inetFmt(dst, s2), iphdrlen, ipdatalen); X X switch (igmp->igmp_type) { X case IGMP_V1_MEMBERSHIP_REPORT: X@@ -190,13 +212,10 @@ X acceptLeaveMessage(src, group); X return; X X- /* X case IGMP_MEMBERSHIP_QUERY: X //accept_membership_query(src, dst, group, igmp->igmp_code); X return; X X- */ X- X default: X log(LOG_INFO, 0, X "ignoring unknown IGMP message type %x from %s to %s", X@@ -220,8 +239,9 @@ X ip->ip_src.s_addr = src; X ip->ip_dst.s_addr = dst; X ip->ip_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; X+#ifdef RAW_OUTPUT_IS_RAW X ip->ip_len = htons(ip->ip_len); X- X+#endif X if (IN_MULTICAST(ntohl(dst))) { X ip->ip_ttl = curttl; X } else { Xdiff -urN igmpproxy.c igmpproxy.new/src/igmpproxy.c X--- igmpproxy.c 2005-08-20 16:56:32.000000000 +0400 X+++ igmpproxy.new/src/igmpproxy.c 2009-01-05 02:40:11.000000000 +0300 X@@ -80,7 +80,7 @@ X * on commandline. The number of commandline arguments, and a X * pointer to the arguments are recieved on the line... X */ X-int main( int ArgCn, const char *ArgVc[] ) { X+int main( int ArgCn, char *ArgVc[] ) { X X int debugMode = 0; X X@@ -155,17 +155,8 @@ X if ( ! debugMode ) { X X IF_DEBUG log( LOG_DEBUG, 0, "Starting daemon mode."); X- X- // Only daemon goes past this line... X- if (fork()) exit(0); X- X- // Detach deamon from terminal X- if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0 X- || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 0, 2 ) < 0 X- || setpgrp() < 0 X- ) { X+ if (daemon(1, 0) != 0) X log( LOG_ERR, errno, "failed to detach deamon" ); X- } X } X X // Go to the main loop. X@@ -218,7 +209,7 @@ X int vifcount = 0; X upStreamVif = -1; X X- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X X if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) { X if(Dp->state == IF_STATE_UPSTREAM) { X@@ -237,7 +228,7 @@ X X // If there is only one VIF, or no defined upstream VIF, we send an error. X if(vifcount < 2 || upStreamVif < 0) { X- log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream."); X+ log(LOG_ERR, 0, "There must be at least 2 Vif's where one is upstream. (vifcount %d, upStreamVif %d)", vifcount, upStreamVif); X } X } X X@@ -275,7 +266,7 @@ X register int recvlen; X int MaxFD, Rt, secs; X fd_set ReadFDS; X- int dummy = 0; X+ socklen_t dummy = 0; X struct timeval curtime, lasttime, difftime, tv; X // The timeout is a pointer in order to set it to NULL if nessecary. X struct timeval *timeout = &tv; Xdiff -urN igmpproxy.conf igmpproxy.new/src/igmpproxy.conf X--- igmpproxy.conf 2005-04-29 23:27:50.000000000 +0400 X+++ igmpproxy.new/src/igmpproxy.conf 2009-01-05 02:11:08.000000000 +0300 X@@ -25,22 +25,22 @@ X X X ##------------------------------------------------------ X-## Configuration for eth0 (Upstream Interface) X+## Configuration for em0 (Upstream Interface) X ##------------------------------------------------------ X-phyint eth0 upstream ratelimit 0 threshold 1 X+phyint em0 upstream ratelimit 0 threshold 1 X altnet 10.0.0.0/8 X altnet 192.168.0.0/24 X X X ##------------------------------------------------------ X-## Configuration for eth1 (Downstream Interface) X+## Configuration for em1 (Downstream Interface) X ##------------------------------------------------------ X-phyint eth1 downstream ratelimit 0 threshold 1 X+phyint em1 downstream ratelimit 0 threshold 1 X X X ##------------------------------------------------------ X-## Configuration for eth2 (Disabled Interface) X+## Configuration for xl0 (Disabled Interface) X ##------------------------------------------------------ X-phyint eth2 disabled X+phyint xl0 disabled X X Xdiff -urN mcgroup.c igmpproxy.new/src/mcgroup.c X--- mcgroup.c 2005-08-20 16:54:37.000000000 +0400 X+++ igmpproxy.new/src/mcgroup.c 2009-01-05 01:58:27.000000000 +0300 X@@ -49,7 +49,6 @@ X CtlReq.imr_interface.s_addr = IfDp->InAdr.s_addr; X X { X- char FmtBu[ 32 ]; X log( LOG_NOTICE, 0, "%sMcGroup: %s on %s", CmdSt, X inetFmt( mcastaddr, s1 ), IfDp ? IfDp->Name : "" ); X } Xdiff -urN mroute-api.c igmpproxy.new/src/mroute-api.c X--- mroute-api.c 2005-05-24 19:48:33.000000000 +0400 X+++ igmpproxy.new/src/mroute-api.c 2009-01-05 01:58:27.000000000 +0300 X@@ -37,7 +37,9 @@ X */ X X X+#ifndef __FreeBSD__ X #define USE_LINUX_IN_H X+#endif X #include "defs.h" X X // MAX_MC_VIFS from mclab.h must have same value as MAXVIFS from mroute.h X@@ -47,7 +49,7 @@ X X // need an IGMP socket as interface for the mrouted API X // - receives the IGMP messages X-int MRouterFD; /* socket for all network I/O */ X+int MRouterFD = -1; /* socket for all network I/O */ X char *recv_buf; /* input packet buffer */ X char *send_buf; /* output packet buffer */ X X@@ -177,13 +179,15 @@ X log( LOG_NOTICE, 0, "Adding MFC: %s -> %s, InpVIf: %d", X fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), X fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), X- CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent X+ CtlReq.mfcc_parent X ); X } X X if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_ADD_MFC, X (void *)&CtlReq, sizeof( CtlReq ) ) ) X log( LOG_WARNING, errno, "MRT_ADD_MFC" ); X+ X+ return 0; X } X X /* X@@ -210,13 +214,15 @@ X log( LOG_NOTICE, 0, "Removing MFC: %s -> %s, InpVIf: %d", X fmtInAdr( FmtBuO, CtlReq.mfcc_origin ), X fmtInAdr( FmtBuM, CtlReq.mfcc_mcastgrp ), X- CtlReq.mfcc_parent == ALL_VIFS ? -1 : CtlReq.mfcc_parent X+ CtlReq.mfcc_parent X ); X } X X if ( setsockopt( MRouterFD, IPPROTO_IP, MRT_DEL_MFC, X (void *)&CtlReq, sizeof( CtlReq ) ) ) X log( LOG_WARNING, errno, "MRT_DEL_MFC" ); X+ X+ return 0; X } X X /* Xdiff -urN request.c igmpproxy.new/src/request.c X--- request.c 2005-05-24 19:48:29.000000000 +0400 X+++ igmpproxy.new/src/request.c 2009-01-05 02:26:54.000000000 +0300 X@@ -88,10 +88,11 @@ X X } else { X // Log the state of the interface the report was recieved on. X- log(LOG_INFO, 0, "Mebership report was recieved on %s. Ignoring.", X+ log(LOG_INFO, 0, "Membership report was received on %s. Ignoring.", X sourceVif->state==IF_STATE_UPSTREAM?"the upstream interface":"a disabled interface"); X } X X+ log(LOG_DEBUG, 0, "Eliminate compiler warning for field type = %u", type); X } X X /** X@@ -136,7 +137,7 @@ X X } else { X // just ignore the leave request... X- IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request."); X+ IF_DEBUG log(LOG_DEBUG, 0, "The found if for %s was not downstream. Ignoring leave request.", inetFmt(src, s1)); X } X } X X@@ -184,7 +185,7 @@ X int Ix; X X // Loop through all downstream vifs... X- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) { X if(Dp->state == IF_STATE_DOWNSTREAM) { X // Send the membership query... Xdiff -urN rttable.c igmpproxy.new/src/rttable.c X--- rttable.c 2005-08-20 16:46:20.000000000 +0400 X+++ igmpproxy.new/src/rttable.c 2009-01-05 01:58:27.000000000 +0300 X@@ -38,15 +38,22 @@ X */ X X #include "defs.h" X+#include X X /** X * Routing table structure definition. Double linked list... X */ X+struct Origin { X+ TAILQ_ENTRY(Origin) next; X+ uint32 originAddr; X+ int flood; X+ uint32 pktcnt; X+}; X+ X struct RouteTable { X struct RouteTable *nextroute; // Pointer to the next group in line. X struct RouteTable *prevroute; // Pointer to the previous group in line. X uint32 group; // The group to route X- uint32 originAddr; // The origin adress (only set on activated routes) X uint32 vifBits; // Bits representing recieving VIFs. X X // Keeps the upstream membership state... X@@ -56,6 +63,7 @@ X uint32 ageVifBits; // Bits representing aging VIFs. X int ageValue; // Downcounter for death. X int ageActivity; // Records any acitivity that notes there are still listeners. X+ TAILQ_HEAD(originhead, Origin) originList; // The origin adresses (non-empty on activated routes) X }; X X X@@ -65,19 +73,17 @@ X // Prototypes X void logRouteTable(char *header); X int internAgeRoute(struct RouteTable* croute); X- X-// Socket for sending join or leave requests. X-int mcGroupSock = 0; X+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *o); X X X /** X * Function for retrieving the Multicast Group socket. X */ X int getMcGroupSock() { X- if( ! mcGroupSock ) { X- mcGroupSock = openUdpSocket( INADDR_ANY, 0 );; X+ if (MRouterFD < 0) { X+ log(LOG_ERR, errno, "no MRouterFD."); X } X- return mcGroupSock; X+ return MRouterFD; X } X X /** X@@ -91,7 +97,7 @@ X routing_table = NULL; X X // Join the all routers group on downstream vifs... X- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X // If this is a downstream vif, we should join the All routers group... X if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) { X IF_DEBUG log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s", X@@ -160,6 +166,7 @@ X */ X void clearAllRoutes() { X struct RouteTable *croute, *remainroute; X+ struct Origin *o; X X // Loop through all routes... X for(croute = routing_table; croute; croute = remainroute) { X@@ -171,7 +178,7 @@ X inetFmt(croute->group, s1)); X X // Uninstall current route X- if(!internUpdateKernelRoute(croute, 0)) { X+ if(!internUpdateKernelRoute(croute, 0, NULL)) { X log(LOG_WARNING, 0, "The removal from Kernel failed."); X } X X@@ -179,6 +186,10 @@ X sendJoinLeaveUpstream(croute, 0); X X // Clear memory, and set pointer to next route... X+ while ((o = TAILQ_FIRST(&croute->originList))) { X+ TAILQ_REMOVE(&croute->originList, o, next); X+ free(o); X+ } X free(croute); X } X routing_table = NULL; X@@ -212,7 +223,6 @@ X X struct Config *conf = getCommonConfig(); X struct RouteTable* croute; X- int result = 1; X X // Sanitycheck the group adress... X if( ! IN_MULTICAST( ntohl(group) )) { X@@ -241,7 +251,8 @@ X newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable)); X // Insert the route desc and clear all pointers... X newroute->group = group; X- newroute->originAddr = 0; X+ TAILQ_INIT(&newroute->originList); X+ X newroute->nextroute = NULL; X newroute->prevroute = NULL; X X@@ -325,10 +336,10 @@ X inetFmt(croute->group, s1), ifx); X X // If the route is active, it must be reloaded into the Kernel.. X- if(croute->originAddr != 0) { X+ if(!TAILQ_EMPTY(&croute->originList)) { X X // Update route in kernel... X- if(!internUpdateKernelRoute(croute, 1)) { X+ if(!internUpdateKernelRoute(croute, 1, NULL)) { X log(LOG_WARNING, 0, "The insertion into Kernel failed."); X return 0; X } X@@ -351,7 +362,7 @@ X * activated, it's reinstalled in the kernel. If X * the route is activated, no originAddr is needed. X */ X-int activateRoute(uint32 group, uint32 originAddr) { X+int activateRoute(uint32 group, uint32 originAddr, int downIf) { X struct RouteTable* croute; X int result = 0; X X@@ -369,21 +380,42 @@ X } X X if(croute != NULL) { X+ struct Origin *o = NULL; X+ int found = 0; X+ X // If the origin address is set, update the route data. X- if(originAddr > 0) { X- if(croute->originAddr > 0 && croute->originAddr!=originAddr) { X- log(LOG_WARNING, 0, "The origin for route %s changed from %s to %s", X- inetFmt(croute->group, s1), X- inetFmt(croute->originAddr, s2), X- inetFmt(originAddr, s3)); X- } X- croute->originAddr = originAddr; X- } X+ if(originAddr > 0) { X X- // Only update kernel table if there are listeners ! X- if(croute->vifBits > 0) { X- result = internUpdateKernelRoute(croute, 1); X- } X+ TAILQ_FOREACH(o, &croute->originList, next) { X+ log(LOG_INFO, 0, "Origin for route %s have %s, new %s", X+ inetFmt(croute->group, s1), X+ inetFmt(o->originAddr, s2), X+ inetFmt(originAddr, s3)); X+ if (o->originAddr==originAddr) { X+ found++; X+ break; X+ } X+ } X+ if (!found) { X+ log(LOG_NOTICE, 0, "New origin for route %s is %s, flood %d", X+ inetFmt(croute->group, s1), X+ inetFmt(originAddr, s3), downIf); X+ o = malloc(sizeof(*o)); X+ o->originAddr = originAddr; X+ o->flood = downIf; X+ o->pktcnt = 0; X+ TAILQ_INSERT_TAIL(&croute->originList, o, next); X+ } else { X+ log(LOG_INFO, 0, "Have origin for route %s at %s, pktcnt %d", X+ inetFmt(croute->group, s1), X+ inetFmt(o->originAddr, s3), X+ o->pktcnt); X+ } X+ } X+ X+ // Only update kernel table if there are listeners, but flood upstream! X+ if(croute->vifBits > 0 || downIf >= 0) X+ result = internUpdateKernelRoute(croute, 1, o); X } X IF_DEBUG logRouteTable("Activate Route"); X X@@ -443,7 +475,6 @@ X * route is not found, or not in this state, 0 is returned. X */ X int lastMemberGroupAge(uint32 group) { X- struct Config *conf = getCommonConfig(); X struct RouteTable *croute; X X croute = findRoute(group); X@@ -463,6 +494,7 @@ X */ X int removeRoute(struct RouteTable* croute) { X struct Config *conf = getCommonConfig(); X+ struct Origin *o; X int result = 1; X X // If croute is null, no routes was found. X@@ -477,7 +509,7 @@ X //BIT_ZERO(croute->vifBits); X X // Uninstall current route from kernel X- if(!internUpdateKernelRoute(croute, 0)) { X+ if(!internUpdateKernelRoute(croute, 0, NULL)) { X log(LOG_WARNING, 0, "The removal from Kernel failed."); X result = 0; X } X@@ -503,7 +535,12 @@ X croute->nextroute->prevroute = croute->prevroute; X } X } X+ X // Free the memory, and set the route to NULL... X+ while ((o = TAILQ_FIRST(&croute->originList))) { X+ TAILQ_REMOVE(&croute->originList, o, next); X+ free(o); X+ } X free(croute); X croute = NULL; X X@@ -551,6 +588,36 @@ X } X } X X+ { X+ struct Origin *o, *nxt; X+ struct sioc_sg_req sg_req; X+ X+ sg_req.grp.s_addr = croute->group; X+ for (o = TAILQ_FIRST(&croute->originList); o; o = nxt) { X+ nxt = TAILQ_NEXT(o, next); X+ sg_req.src.s_addr = o->originAddr; X+ if (ioctl(MRouterFD, SIOCGETSGCNT, (char *)&sg_req) < 0) { X+ log(LOG_WARNING, errno, "%s (%s %s)", X+ "age_table_entry: SIOCGETSGCNT failing for", X+ inetFmt(o->originAddr, s1), X+ inetFmt(croute->group, s2)); X+ /* Make sure it gets deleted below */ X+ sg_req.pktcnt = o->pktcnt; X+ } X+ log(LOG_DEBUG, 0, "Aging Origin %s Dst %s PktCnt %d -> %d", X+ inetFmt(o->originAddr, s1), inetFmt(croute->group, s2), X+ o->pktcnt, sg_req.pktcnt); X+ if (sg_req.pktcnt == o->pktcnt) { X+ /* no traffic, remove from kernel cache */ X+ internUpdateKernelRoute(croute, 0, o); X+ TAILQ_REMOVE(&croute->originList, o, next); X+ free(o); X+ } else { X+ o->pktcnt = sg_req.pktcnt; X+ } X+ } X+ } X+ X // If the aging counter has reached zero, its time for updating... X if(croute->ageValue == 0) { X // Check for activity in the aging process, X@@ -560,7 +627,7 @@ X inetFmt(croute->group,s1)); X X // Just update the routing settings in kernel... X- internUpdateKernelRoute(croute, 1); X+ internUpdateKernelRoute(croute, 1, NULL); X X // We append the activity counter to the age, and continue... X croute->ageValue = croute->ageActivity; X@@ -586,34 +653,57 @@ X /** X * Updates the Kernel routing table. If activate is 1, the route X * is (re-)activated. If activate is false, the route is removed. X+* if 'origin' is given, only the route with 'origin' will be X+* updated, otherwise all MFC routes for the group will updated. X */ X-int internUpdateKernelRoute(struct RouteTable *route, int activate) { X+int internUpdateKernelRoute(struct RouteTable *route, int activate, struct Origin *origin) { X struct MRouteDesc mrDesc; X struct IfDesc *Dp; X unsigned Ix; X- X- if(route->originAddr>0) { X+ struct Origin *o; X+ X+ if (TAILQ_EMPTY(&route->originList)) { X+ log(LOG_NOTICE, 0, "Route is not active. No kernel updates done."); X+ return 1; X+ } X+ TAILQ_FOREACH(o, &route->originList, next) { X+ if (origin && origin != o) X+ continue; X X // Build route descriptor from table entry... X // Set the source address and group address... X mrDesc.McAdr.s_addr = route->group; X- mrDesc.OriginAdr.s_addr = route->originAddr; X+ mrDesc.OriginAdr.s_addr = o->originAddr; X X // clear output interfaces X memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) ); X X- IF_DEBUG log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits); X- X+ IF_DEBUG log(LOG_DEBUG, 0, "Origin %s Vif bits : 0x%08x", inetFmt(o->originAddr, s1), route->vifBits); X // Set the TTL's for the route descriptor... X- for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { X- if(Dp->state == IF_STATE_UPSTREAM) { X- //IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index); X- mrDesc.InVif = Dp->index; X- } X- else if(BIT_TST(route->vifBits, Dp->index)) { X- IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold); X- mrDesc.TtlVc[ Dp->index ] = Dp->threshold; X- } X+ for ( Ix = 0; (Dp = getIfByIx( Ix )); Ix++ ) { X+ if (o->flood >= 0) { X+ if(Ix == (unsigned) o->flood) { X+ IF_DEBUG log(LOG_DEBUG, 0, "Identified Input VIF #%d as DOWNSTREAM.", Dp->index); X+ mrDesc.InVif = Dp->index; X+ } X+ else if(Dp->state == IF_STATE_UPSTREAM) { X+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for UPSTREAM Vif %d to %d", Dp->index, Dp->threshold); X+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold; X+ } X+ else if(BIT_TST(route->vifBits, Dp->index)) { X+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for DOWNSTREAM Vif %d to %d", Dp->index, Dp->threshold); X+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold; X+ } X+ } else { X+ if(Dp->state == IF_STATE_UPSTREAM) { X+ IF_DEBUG log(LOG_DEBUG, 0, "Identified VIF #%d as upstream.", Dp->index); X+ mrDesc.InVif = Dp->index; X+ } X+ else if(BIT_TST(route->vifBits, Dp->index)) { X+ IF_DEBUG log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold); X+ mrDesc.TtlVc[ Dp->index ] = Dp->threshold; X+ } X+ } X } X X // Do the actual Kernel route update... X@@ -625,9 +715,6 @@ X // Delete the route from Kernel... X delMRoute( &mrDesc ); X } X- X- } else { X- log(LOG_NOTICE, 0, "Route is not active. No kernel updates done."); X } X X return 1; X@@ -647,16 +734,17 @@ X log(LOG_DEBUG, 0, "No routes in table..."); X } else { X do { X- /* X- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, Prev: 0x%08x, T: 0x%08x, Next: 0x%08x", X- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2), X- croute->ageValue,(croute->originAddr>0?"A":"I"), X- croute->prevroute, croute, croute->nextroute); X- */ X- log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x", X- rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2), X- croute->ageValue,(croute->originAddr>0?"A":"I"), X- croute->vifBits); X+ log(LOG_DEBUG, 0, "#%d: Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x", X+ rcount, inetFmt(croute->group, s2), X+ croute->ageValue,(TAILQ_EMPTY(&croute->originList)?"I":"A"), X+ croute->vifBits); X+ { X+ struct Origin *o; X+ TAILQ_FOREACH(o, &croute->originList, next) { X+ log(LOG_DEBUG, 0, "#%d: Origin: %s floodIf %d pktcnt %d", X+ rcount, inetFmt(o->originAddr, s1), o->flood, o->pktcnt); X+ } X+ } X X croute = croute->nextroute; X Xdiff -urN syslog.c igmpproxy.new/src/syslog.c X--- syslog.c 2005-05-24 19:48:19.000000000 +0400 X+++ igmpproxy.new/src/syslog.c 2009-01-05 02:07:50.000000000 +0300 X@@ -53,12 +53,16 @@ X ** is logged to 'stderr'. X ** X */ X+#ifdef DEVEL_LOGGING X+void _log( int Serverity, int Errno, const char *func, int line, const char *FmtSt, ... ) X+#else X void log( int Serverity, int Errno, const char *FmtSt, ... ) X+#endif X { X const char ServVc[][ 5 ] = { "EMER", "ALER", "CRIT", "ERRO", X "Warn", "Note", "Info", "Debu" }; X X- const char *ServPt = Serverity < 0 || Serverity >= VCMC( ServVc ) ? X+ const char *ServPt = Serverity < 0 || Serverity >= (int) VCMC( ServVc ) ? X "!unknown serverity!" : ServVc[ Serverity ]; X X const char *ErrSt = (Errno <= 0) ? NULL : (const char *)strerror( Errno ); X@@ -69,6 +73,9 @@ X X va_start( ArgPt, FmtSt ); X Ln = snprintf( LogLastMsg, sizeof( LogLastMsg ), "%s: ", ServPt ); X+#ifdef DEVEL_LOGGING X+ Ln += snprintf( LogLastMsg + Ln, sizeof( LogLastMsg ) - Ln, "%s():%d: ", func, line); X+#endif X Ln += vsnprintf( LogLastMsg + Ln, sizeof( LogLastMsg ) - Ln, FmtSt, ArgPt ); X if( ErrSt ) X snprintf( LogLastMsg + Ln, sizeof( LogLastMsg ) - Ln, "; Errno(%d): %s", Errno, ErrSt ); END-of-igmpproxy/files/patch-fbsd echo x - igmpproxy/files/igmpproxy sed 's/^X//' >igmpproxy/files/igmpproxy << 'END-of-igmpproxy/files/igmpproxy' X#!/bin/sh X# X# $FreeBSD: src/etc/rc.d/lpd,v 1.8.4.1 2008/01/28 07:58:31 dougb Exp $ X# X X# PROVIDE: igmpproxy X# REQUIRE: NETWORKING X X. /etc/rc.subr X Xname="igmpproxy" Xrcvar=`set_rcvar` Xcommand="/usr/local/sbin/${name}" Xrequired_files="/usr/local/etc/igmpproxy.conf" Xigmpproxy_enable=${igmpproxy_enable-"NO"} X Xload_rc_config $name Xrun_rc_command "$1" END-of-igmpproxy/files/igmpproxy exit