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>