Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 29 Mar 2011 14:01:03 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        Randall Stewart <rrs@freebsd.org>
Cc:        svn-src-head@freebsd.org, deischen@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r217592 - head/sys/netinet
Message-ID:  <201103291401.03565.jhb@freebsd.org>
In-Reply-To: <201101191907.p0JJ7GMp086060@svn.freebsd.org>
References:  <201101191907.p0JJ7GMp086060@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday, January 19, 2011 2:07:16 pm Randall Stewart wrote:
> Author: rrs
> Date: Wed Jan 19 19:07:16 2011
> New Revision: 217592
> URL: http://svn.freebsd.org/changeset/base/217592
> 
> Log:
>   Fix a bug where Multicast packets sent from a
>   udp endpoint may end up echoing back to the sender
>   even with OUT joining the multi-cast group.
>   
>   Reviewed by:	gnn, bms, bz?
>   Obtained from:	deischen (with help from)
> 
> Modified:
>   head/sys/netinet/udp_usrreq.c
> 
> Modified: head/sys/netinet/udp_usrreq.c
> 
==============================================================================
> --- head/sys/netinet/udp_usrreq.c	Wed Jan 19 18:20:11 2011	(r217591)
> +++ head/sys/netinet/udp_usrreq.c	Wed Jan 19 19:07:16 2011	(r217592)
> @@ -479,11 +479,13 @@ udp_input(struct mbuf *m, int off)
>  			 * and source-specific multicast. [RFC3678]
>  			 */
>  			imo = inp->inp_moptions;
> -			if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
> -			    imo != NULL) {
> +			if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
>  				struct sockaddr_in	 group;
>  				int			 blocked;
> -
> +				if(imo == NULL) {
> +					INP_RUNLOCK(inp);
> +					continue;
> +				}
>  				bzero(&group, sizeof(struct sockaddr_in));
>  				group.sin_len = sizeof(struct sockaddr_in);
>  				group.sin_family = AF_INET;

So it turns out that this is a feature, not a bug, and is how multicast has 
always worked.  Specifically, if you bind a UDP socket with a wildcard 
address, it should receive all traffic for the bound port, unicast or 
multicast.  When you join a group, you have switched the socket into a mode 
where it now has a whitelist of acceptable multicast groups, but if a socket 
has no joined groups, it should receive all multicast traffic, not none.  This 
change breaks that.

I did not find this behavior intuitive at first, but it does seem to be 
required.  Note the description of IP_ADD_MEMBERSHIP from RFC 3678 for 
example:

3.  Overview of APIs

   There are a number of different APIs described in this document that
   are appropriate for a number of different application types and IP
   versions.  Before providing detailed descriptions, this section
   provides a "taxonomy" with a brief description of each.

   There are two categories of source-filter APIs, both of which are
   designed to allow multicast receiver applications to designate the
   unicast address(es) of sender(s) along with the multicast group
   (destination address) to receive.

      o  Basic (Delta-based): Some applications desire the simplicity of
         a delta-based API in which each function call specifies a
         single source address which should be added to or removed from
         the existing filter for a given multicast group address on
         which to listen.  Such applications typically fall into either
         of two categories:

         +  Any-Source Multicast: By default, all sources are accepted.
            Individual sources may be turned off and back on as needed
            over time.  This is also known as "exclude" mode, since the
            source filter contains a list of excluded sources.

         +  Source-Specific Multicast: Only sources in a given list are
            allowed.  The list may change over time.  This is also known
            as "include" mode, since the source filter contains a list
            of included sources.

            This API would be used, for example, by "single-source"
            applications such as audio/video broadcasting.  It would
            also be used for logical multi-source sessions where each
            source independently allocates its own Source-Specific
            Multicast group address.


.....

4.1.1.  IPv4 Any-Source Multicast API

   The following socket options are defined in <netinet/in.h> for
   applications in the Any-Source Multicast category:

   Socket option             Argument type
   IP_ADD_MEMBERSHIP         struct ip_mreq
   IP_BLOCK_SOURCE           struct ip_mreq_source
   IP_UNBLOCK_SOURCE         struct ip_mreq_source
   IP_DROP_MEMBERSHIP        struct ip_mreq

   IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP are already implemented on
   most operating systems, and are used to join and leave an any-source
   group.

   IP_BLOCK_SOURCE can be used to block data from a given source to a
   given group (e.g., if the user "mutes" that source), and
   IP_UNBLOCK_SOURCE can be used to undo this (e.g., if the user then
   "unmutes" the source).

As to why the packets loop back to the receiver, I believe that is a separate 
issue on the output side, not the receive side.

-- 
John Baldwin



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