Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 Dec 1998 00:06:11 +0900 (JST)
From:      greg@greg.rim.or.jp
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Cc:        greg@greg.rim.or.jp
Subject:   ports/9172: squid dose not join a multicast group without primary interface
Message-ID:  <199812221506.AAA23687@izanami.greg.rim.or.jp>

next in thread | raw e-mail | index | archive | help

>Number:         9172
>Category:       ports
>Synopsis:       squid dose not join a multicast group without primary interface
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 22 07:10:00 PST 1998
>Last-Modified:
>Originator:     Kensaku Masuda
>Organization:
>Release:        FreeBSD 2.2.8-STABLE i386
>Environment:

	My FreeBSD box has two network interface (de and ep).
And running FreeBSD 2.2.8-stable.

>Description:

	squid is executing a code like this ...

		struct ip_mreq mr;
		.
		.
		.
		mr.imr_interface.s_addr = INADDR_ANY;
		x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
			(char *)&mr, sizeof(mr));

So, FreeBSD joining a multicast group with 1st network interface.
But atfer 2nd is not.

>How-To-Repeat:

	use INADDR_ANY with imr_interface.s_addr like member of struct ip_mreq,
And call setsockopt with IP_ADD_MEMBERSHIP.

>Fix:
	

--- src.old/multicast.c	Thu Jul 23 05:37:36 1998
+++ src/multicast.c	Sat Dec 19 03:21:45 1998
@@ -32,9 +32,40 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  *
  */
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
 
 #include "squid.h"
 
+#if defined(NEED_BINDING_FOR_EACH_INTERFAE)
+#define ROUNDUP(a) \
+	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+static int mcastJoinGroupAtInterface(int fd, struct ip_mreq *mr);
+
+static void rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
+{
+	struct sockaddr *sa;
+	int i;
+
+	memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
+	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+		if ((rtinfo->rti_addrs & (1 << i)) == 0)
+			continue;
+		rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+		ADVANCE(cp, sa);
+	}
+}
+#endif
+
 int
 mcastSetTtl(int fd, int mcast_ttl)
 {
@@ -65,8 +96,12 @@
 	    inet_ntoa(*(ia->in_addrs + i)));
 	mr.imr_multiaddr.s_addr = (ia->in_addrs + i)->s_addr;
 	mr.imr_interface.s_addr = INADDR_ANY;
+#if defined(NEED_BINDING_FOR_EACH_INTERFAE)
+	x = mcastJoinGroupAtInterface(fd, &mr);
+#else
 	x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
 	    (char *) &mr, sizeof(struct ip_mreq));
+#endif
 	if (x < 0)
 	    debug(7, 1) ("comm_join_mcast_groups: FD %d, [%s]\n",
 		fd, inet_ntoa(*(ia->in_addrs + i)));
@@ -76,3 +111,90 @@
     }
 #endif
 }
+
+#if defined(NEED_BINDING_FOR_EACH_INTERFAE) && defined(IP_MULTICAST_TTL)
+static int mcastJoinGroupAtInterface(int fd, struct ip_mreq *mr)
+{
+	char *buf, *next, *last;
+	struct if_msghdr *	ifm;
+	struct if_msghdr *	nextifm;
+	struct sockaddr_dl *	sdl;
+	int			mib[6];
+	int			count;
+	int			flags, x;
+	char			name[8];
+	struct ifa_msghdr *	address;
+	struct rt_addrinfo	info;
+	struct sockaddr_in *	sin;
+	struct sockaddr_in	null;
+
+	mib[0] = CTL_NET;
+	mib[1] = PF_ROUTE;
+	mib[2] = 0;
+	mib[3] = AF_INET;
+	mib[4] = NET_RT_IFLIST;
+	mib[5] = 0;
+
+	memset(&null, 0, sizeof(null));
+	if(sysctl(mib, 6, NULL, &count, NULL, 0) < 0) {
+		printf("error at 1\n");
+		return 3;
+	}
+	buf = (char *)xmalloc(count);
+	if(buf == NULL) {
+		printf("error at 2\n");
+		return 3;
+	}
+	if(sysctl(mib, 6, buf, &count, NULL, 0) < 0) {
+		printf("error at 3\n");
+		return 3;
+	}
+	next = buf; last = buf + count;
+	while(next < last) {
+		ifm = (struct if_msghdr *)next;
+		sdl = (struct sockaddr_dl *)(ifm + 1);
+		flags = ifm->ifm_flags;
+		next += ifm->ifm_msglen;
+		address = NULL;
+		while(next < last) {
+			nextifm = (struct if_msghdr *)next;
+			if(nextifm->ifm_type != RTM_NEWADDR) {
+				break;
+			}
+			if(address == NULL) {
+				address = (struct ifa_msghdr *)nextifm;
+			}
+			next += nextifm->ifm_msglen;
+		}
+		memcpy(name, sdl->sdl_data + 0, sdl->sdl_nlen);
+		name[sdl->sdl_nlen] = 0;
+		if(address != NULL) {
+			info.rti_addrs = address->ifam_addrs;
+			rt_xaddrs(
+				(char *)(address + 1),
+				(char *)(address) + address->ifam_msglen,
+				&info);
+			if(sdl->sdl_nlen > 0 && (flags & IFF_UP)) {
+				sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
+				if(sin != NULL) {
+					mr->imr_interface.s_addr = sin->sin_addr.s_addr;
+					x = setsockopt(
+						fd,
+						IPPROTO_IP,
+						IP_ADD_MEMBERSHIP,
+						(char *)mr,
+						sizeof(struct ip_mreq));
+					if(x < 0) {
+						xfree(buf);
+						return x;
+					}
+				}
+			}
+		}
+	}
+	xfree(buf);
+	return 0;
+}
+
+#endif
+

--- src.old/squid.h	Sat Oct 31 04:48:16 1998
+++ src/squid.h	Sat Dec 19 03:51:19 1998
@@ -61,6 +61,7 @@
 #undef CHANGE_FD_SETSIZE
 #define CHANGE_FD_SETSIZE 0
 #endif
+#define NEED_BINDING_FOR_EACH_INTERFAE
 #endif
 
 /* Increase FD_SETSIZE if SQUID_MAXFD is bigger */
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812221506.AAA23687>