On Tue, 29 Mar 2011, John Baldwin wrote:

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.

That may be, but the behavior is undesired if the no process
on the system has joined the multicast group.  I believe it
was broke with r189359, and the comment in the code that broke
it says:

        /*
         * Loop back multicast datagram if not expressly
         * forbidden to do so, even if we are not a member
         * of the group; ip_input() will filter it later,
         * thus deferring a hash lookup and mutex acquisition
         * at the expense of a cheap copy using m_copym().
         */

The previous revision did a lookup of the multicast address
and looped it if an entry was found for it.

--
DE
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to