Subject: Re: emcast and PR 7003
To: Jonathan A. Kollasch <jakllsch@kollasch.net>
From: Jonathan Stone <jonathan@Pescadero.dsg.stanford.edu>
List: tech-net
Date: 11/14/2005 20:23:51
In message <20051113165823.GA27129@vergon.kollasch.net>,
"Jonathan A. Kollasch" writes:

>Hi,
>	Recently I've been working with IPv4 multicast on NetBSD. It seems that
>one problem described in PR 7003 (NetBSD sends and receive IP pkts  with
>multicast source address) still exists in 2.1. NetBSD will receive multicast
>packets from emcast running on Linux, but the Linux host cannot receive packets
>from emcast running on NetBSD. This is because the packets sent from the NetBSD
>host have a multicast *source* address. So my question; is this a problem in
>NetBSD or in emcast? I'm inclined to believe it may be a problem with both; as
>vlc on NetBSD multicasts packets with a normal unicast source address. Shouldn't
>the kernel enforce that the source address is unicast?
>
>	Jonathan Kollasch


Are you running emcast compiled native for NetBSD, or are you running
a Linux binary via Linux binary emulation?

I'm not sure how a source address can get out from ip_output, given
the fragment

        /*
         * packets with Class-D address as source are not valid per
         * RFC 1112
         */
        if (IN_MULTICAST(ip->ip_src.s_addr)) {
                ipstat.ips_odropped++;
                error = EADDRNOTAVAIL;
                goto bad;
        }


around line 480 in ip_output.c in -current (the same code fragment is
in 2.0 and 3.0, with some fuzz).  Can you build a custom kernel which
moves that code-fragment to immediately *below* the label "sendit:" in
ip_output(), add a printf() inside the if() {}, and test whether your
app fires the printf()? I suspect that the  code inside

        if (IN_MULTICAST(ip->ip_dst.s_addr) ||
            (ip->ip_dst.s_addr == INADDR_BROADCAST)) {
                struct in_multi *inm;
/* ... large body of code elided */

	goto sendit;
	}

        /*
         * If source address not specified yet, use address
         * of outgoing interface.
         */
        if (in_nullhost(ip->ip_src))
                ip->ip_src = ia->ia_addr.sin_addr;


just before the if (IN_MULTICAST()) test is the proximate culprit.
(nb, in NetBSD-2.0, I think the check for uspecified (INADDR_ANY)
source address seems to be #ifdef'ed out).


Do you have a packet trace which conclusively shows NetBSD is emitting
IP packets with class-D source addreses? Can you send a ktrace output
from the app which sends these packets? Can you identify by what
syscall or setsockopt() this Class-D address (the one which is leaking
out as an IP source address) is being passed into the kernel?

On the NetBSD host owning the source MAC address of the offending
packets, does netstat -n -d -i <interface> a nonzero value for  drops?


Occam's Razor suggests that perahps emcast is tickling to the same API
"bug" that xntpd-3.0 code was tickling in PR 7003; but I never
isolated just what that bug was.  As I wrote in the cited PR:

>I'm not sure about the sending side.
>	``the same source works on Linux''.
>	ktrace shows that  xntpd is doing sendto(). Perhaps it's an artifact
>	of sendto() to INADDR_ANY, on a socket which has been bound to
>	receive packets _from_ the multicast group address?



Last, do your kernels have ``options MROUTING'' turned on?