Re: setsockopt IP_ADD_MEMBERSHIP not honored

From: William A.Carrel (william.a_at_carrel.org)
Date: 10/21/03

  • Next message: _at_babolo.ru: "Re: natd+ipfw+trafic shaping"
    Date: Tue, 21 Oct 2003 14:02:39 -0700
    To: Joshua Graessley <jgraessley@apple.com>
    
    

    On Tuesday, October 21, 2003, at 12:59PM, Joshua Graessley wrote:

    > On Oct 21, 2003, at 12:28 PM, William A.Carrel wrote:
    >
    >> I have two such sockets set up, one on each of the interfaces I'm
    >> interested in. The problem is that a packet that comes in on one
    >> interface winds up in the receive queue for both sockets. Both the
    >> queue for the socket that has the membership on the interface I care
    >> about, and the receive queue for the socket that has the membership
    >> on the other interface.
    >>
    >> My reading of UNP vol. 1 (pg. 496) and the ip(4) man page would imply
    >> that this is not the correct behavior for a multicast membership that
    >> was tied to a specific interface. This means that new processes that
    >> add membership to the multicast address on a new interface can cause
    >> older processes to receive packets on that interface that they did
    >> not intend to read.

    > This is "by design". When you perform IP_ADD_MEMBERSHIP, it assures
    > you that the interface you've selected will receive packets destined
    > for the multicast address you specify. It will deal with any IGMP
    > traffic necessary for joining the group.
    >
    > When a packet is received on any interface, the packet is matched up
    > to any number of sockets. This matching is based on the address and
    > port the socket is bound to. This chunk of the code that matches a
    > packet up to an interface does not check to see if that socket joined
    > the multicast group on that specific interface.

    Right. This is exactly the issue I'm pointing out, and it is certainly
    my impression from the documentation of IP_ADD_MEMBERSHIP on this
    subject that the existing behavior needs fixing, as I'll elucidate in a
    little bit more detail below.

    > Some applications may rely on this behavior, so it might be unwise to
    > change it. If you're going to make this change, you should probably
    > make it some sort of socket option that applications can opt in to on
    > a per socket basis.

    Relying on this behavior doesn't seem to make sense. It would be
    relying on the kernel to let other programs to make you receive
    unintended multicast packets. It would also be relying on behavior
    contrary to the documentation.

    The only change in behavior would be if the program presumes someone
    else is holding memberships on all the interfaces (on its behalf) so it
    only has to open one. For example, in the case of multicast DNS, if
    the program is really wanting to listen for mDNS traffic on all
    interfaces, it needs to be adding membership on all interfaces. It
    would be broken behavior on the part of the application to add
    membership to the multicast address on one interface and trust that
    someone else has memberships to that multicast address on all the other
    interfaces, so it can get the multicast traffic for all interfaces.
    The example code from Apple in mDNSResponder-58/mDNSPosix/mDNSPosix.c
    (SetupSocket() at line 464) also seems to acknowledge that the
    multicast socket is only handling multicast for a specific interface.

    If a program really wants to get the multicast traffic on all
    interfaces, then it needs to add membership for all the interfaces.
    And if it holds membership on all the interfaces, my suggested fix will
    not keep it from receiving the packets that it wants destined for it.
    As such, I don't see the potential for a POLA violation in the
    suggested fix.

     From the manpage:
          A host must become a member of a multicast group before it can
    receive
          datagrams sent to the group. To join a multicast group, use the
          IP_ADD_MEMBERSHIP option:

          struct ip_mreq mreq;
          setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

          where mreq is the following structure:

          struct ip_mreq {
              struct in_addr imr_multiaddr; /* multicast group to join */
              struct in_addr imr_interface; /* interface to join on */
          }

          imr_interface should be INADDR_ANY to choose the default multicast
    inter-
          face, or the IP address of a particular multicast-capable
    interface if
          the host is multihomed. Membership is associated with a single
    inter-
          face; programs running on multihomed hosts may need to join the
    same
          group on more than one interface. Up to IP_MAX_MEMBERSHIPS
    (currently
          20) memberships may be added on a single socket.

    The assertion that "membership is associated with a single interface"
    is false under the current implementation. Membership is, at the
    moment, associated with the interface you specified to join on, and any
    other interfaces that any other processes on the entire system
    (possibly even processes in jails) have joined the same multicast
    address on.

    W. Richard Stevens wrote similarly on page 496 of UNP Vol. 1 (2nd ed.).
      "Join a multicast group on a specified local interface. ... If the
    local interface is specified as the wildcard address (INADDR_ANY for
    IPv4)..., then the local interface is chosen by the kernel. ... More
    than one join is allowed on a given socket... This can be used on a
    multihomed host where, for example, one socket is created and then for
    each interface a join is performed for a given multicast address."

    It seems odd that someone would join on a specified local interface and
    then start receiving packets on from an interface other than the one
    they had specified. The descriptions given both by Stevens, by Apple's
    mDNS example code and in the ip(4) man page run counter to the current
    behavior, hence the code I presented a moment ago to bring the behavior
    in line with the documentation.

    _______________________________________________
    freebsd-net@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-net
    To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"


  • Next message: _at_babolo.ru: "Re: natd+ipfw+trafic shaping"

    Relevant Pages

    • Re: rev. 1.94 of netinet/in.c broke CARP
      ... B>>of all multicast instances and deletes all the instances, ... B>>belonging to a particular interface. ... and the other to prevent the netinet ifp detach path ... B>>membership instances had freed is theirselves. ...
      (freebsd-net)
    • Re: 6.0BETA3 panic in ip_output (vlan/RIP related?)
      ... > that I understand the problem here: this occurs when an interface is ... > removed while IP multicast membership is still present for multicast ... > kernel panics because it has a now invalid cached pointer to the ... Do they simply invalidate current membership related with the ...
      (freebsd-current)
    • setsockopt IP_ADD_MEMBERSHIP not honored
      ... I've been working on a miniature multicast routing program and am ... socket to receive packets from. ... address is translated into an ifp for the interface that address is ... and the receive queue for the socket that has the membership on ...
      (freebsd-net)
    • Re: [PATCH} Network interface for IPMI
      ... af_ipmi - A network socket interface to IPMI. ... -Note that the KCS-only interface ahs been removed. ... struct sockaddr_ipmi saddr; ...
      (Linux-Kernel)
    • Re: Too much multicasting in Linux
      ... > that didn't join the multicast address where the data is being sent. ... > the interface 0.0.0.0 causes them to receive all data. ... if I have a socket that joins the SAME ... > multicast group but is tied to a different interface it will not receive ...
      (comp.os.linux.networking)