svn commit: r217592 - head/sys/netinet
John Baldwin
jhb at freebsd.org
Tue Mar 29 18:01:05 UTC 2011
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
More information about the svn-src-head
mailing list