diff options
author | David L Stevens <dlstevens@us.ibm.com> | 2005-07-08 17:39:23 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-07-08 17:39:23 -0700 |
commit | 8cdaaa15da58806ac3c75d96c40aef9e31445a25 (patch) | |
tree | bdeee63b026525963143d3ffe07d93110c25297c /net/ipv4/igmp.c | |
parent | ca9b907d140a5f249250d19f956129dbbbf84f73 (diff) | |
download | lwn-8cdaaa15da58806ac3c75d96c40aef9e31445a25.tar.gz lwn-8cdaaa15da58806ac3c75d96c40aef9e31445a25.zip |
[IPV4]: multicast API "join" issues
1) Changes IP_ADD_SOURCE_MEMBERSHIP and MCAST_JOIN_SOURCE_GROUP to ignore
EADDRINUSE errors on a "courtesy join" -- prior membership or not
is ok for these.
2) Adds "leave group" equivalence of (INCLUDE, empty) filters in the
delta-based API. Without this, mixing delta-based API calls that
end in an (INCLUDE, empty) filter would not allow a subsequent
regular IP_ADD_MEMBERSHIP. It also frees socket buffer memory that
isn't needed for both the multicast group record and source filter.
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r-- | net/ipv4/igmp.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 111eb678cbac..e21ebe759907 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1724,6 +1724,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct struct in_device *in_dev = NULL; struct inet_sock *inet = inet_sk(sk); struct ip_sf_socklist *psl; + int leavegroup = 0; int i, j, rv; if (!MULTICAST(addr)) @@ -1775,6 +1776,12 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct if (rv) /* source not found */ goto done; + /* special case - (INCLUDE, empty) == LEAVE_GROUP */ + if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { + leavegroup = 1; + goto done; + } + /* update the interface filter */ ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, &mreqs->imr_sourceaddr, 1); @@ -1831,6 +1838,8 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct &mreqs->imr_sourceaddr, 1); done: rtnl_shunlock(); + if (leavegroup) + return ip_mc_leave_group(sk, &imr); return err; } |