[Quagga-bugs] [Bug 420] ospfd binds to wrong interfaces for multicast
[FreeBSD 7]
bugzilla-daemon at allevil.dishone.st
bugzilla-daemon at allevil.dishone.st
Sun Dec 2 21:11:14 GMT 2007
Please do not reply directly to this email. All additional
comments should be made in the comments box of this bug
report.
http://bugzilla.quagga.net/show_bug.cgi?id=420
------- Additional Comments From jeremy at vtdn.net 2007-12-02 21:11 -------
I've already finished debugging this completely.
FreeBSD 7 made some fundamental changes to the multicast processing which Quagga
relies on a 'hack' in the kernel to function properly.
The specific issue seems to occur when quagga calls IP_MULTICAST_IF with an IP
address of 0.0.0.0/8. FreeBSD will default to whatever interface the default
route is (usually).
Please see comments from other users at:
http://www.nabble.com/forum/ViewPost.jtp?post=11172865&framed=y
Here's the changelog from FreeBSD source tree:
20070612:
The IPv4 multicast socket code has been considerably modified, and
moved to the file sys/netinet/in_mcast.c. Initial support for the
RFC 3678 Source-Specific Multicast Socket API has been added to
the IPv4 network stack.
Strict multicast and broadcast reception is now the default for
UDP/IPv4 sockets; the net.inet.udp.strict_mcast_mship sysctl variable
has now been removed.
The RFC 1724 hack for interface selection has been removed; the use
of the Linux-derived ip_mreqn structure with IP_MULTICAST_IF has
been added to replace it. Consumers such as routed will soon be
updated to reflect this.
These changes affect users who are running routed(8) or rdisc(8)
from the FreeBSD base system on point-to-point or unnumbered
interfaces.
My solution on my system was to edit lib/sockopt.c and remove the following code:
Remove from:
#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
to
#endif
Remove:
#ifdef HAVE_BSD_STRUCT_IP_MREQ_HACK
if (ifindex)
m.s_addr = htonl(ifindex);
else
#endif
Thus making the complete function setsockopt_multicast_ipv4 looking like:
int
setsockopt_multicast_ipv4(int sock,
int optname,
struct in_addr if_addr /* required */,
unsigned int mcast_addr,
unsigned int ifindex /* optional: if non-zero, may be
used instead of if_addr */)
{
struct in_addr m;
struct ip_mreq mreq;
int ret;
m = if_addr;
switch (optname)
{
case IP_MULTICAST_IF:
return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));
break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
memset (&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = mcast_addr;
mreq.imr_interface = m;
ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
{
/* see above: handle possible problem when interface comes back up */
char buf[2][INET_ADDRSTRLEN];
zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
"re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
sock,
inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
inet_ntop(AF_INET, &mreq.imr_multiaddr,
buf[1], sizeof(buf[1])), ifindex);
setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(void *)&mreq, sizeof(mreq));
ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void *)&mreq, sizeof(mreq));
}
return ret;
break;
default:
/* Can out and give an understandable error */
errno = EINVAL;
return -1;
break;
}
}
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
More information about the Quagga-bugs
mailing list