diff options
| author | David L Stevens <dlstevens@us.ibm.com> | 2005-07-08 20:39:23 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2005-07-08 20:39:23 -0400 |
| commit | 8cdaaa15da58806ac3c75d96c40aef9e31445a25 (patch) | |
| tree | bdeee63b026525963143d3ffe07d93110c25297c | |
| parent | ca9b907d140a5f249250d19f956129dbbbf84f73 (diff) | |
[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>
| -rw-r--r-- | net/ipv4/igmp.c | 9 | ||||
| -rw-r--r-- | net/ipv4/ip_sockglue.c | 6 |
2 files changed, 12 insertions, 3 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 | |||
| 1724 | struct in_device *in_dev = NULL; | 1724 | struct in_device *in_dev = NULL; |
| 1725 | struct inet_sock *inet = inet_sk(sk); | 1725 | struct inet_sock *inet = inet_sk(sk); |
| 1726 | struct ip_sf_socklist *psl; | 1726 | struct ip_sf_socklist *psl; |
| 1727 | int leavegroup = 0; | ||
| 1727 | int i, j, rv; | 1728 | int i, j, rv; |
| 1728 | 1729 | ||
| 1729 | if (!MULTICAST(addr)) | 1730 | if (!MULTICAST(addr)) |
| @@ -1775,6 +1776,12 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
| 1775 | if (rv) /* source not found */ | 1776 | if (rv) /* source not found */ |
| 1776 | goto done; | 1777 | goto done; |
| 1777 | 1778 | ||
| 1779 | /* special case - (INCLUDE, empty) == LEAVE_GROUP */ | ||
| 1780 | if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { | ||
| 1781 | leavegroup = 1; | ||
| 1782 | goto done; | ||
| 1783 | } | ||
| 1784 | |||
| 1778 | /* update the interface filter */ | 1785 | /* update the interface filter */ |
| 1779 | ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, | 1786 | ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1, |
| 1780 | &mreqs->imr_sourceaddr, 1); | 1787 | &mreqs->imr_sourceaddr, 1); |
| @@ -1831,6 +1838,8 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct | |||
| 1831 | &mreqs->imr_sourceaddr, 1); | 1838 | &mreqs->imr_sourceaddr, 1); |
| 1832 | done: | 1839 | done: |
| 1833 | rtnl_shunlock(); | 1840 | rtnl_shunlock(); |
| 1841 | if (leavegroup) | ||
| 1842 | return ip_mc_leave_group(sk, &imr); | ||
| 1834 | return err; | 1843 | return err; |
| 1835 | } | 1844 | } |
| 1836 | 1845 | ||
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index f8b172f89811..fc7c481d0d79 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -677,11 +677,11 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
| 677 | mreq.imr_address.s_addr = mreqs.imr_interface; | 677 | mreq.imr_address.s_addr = mreqs.imr_interface; |
| 678 | mreq.imr_ifindex = 0; | 678 | mreq.imr_ifindex = 0; |
| 679 | err = ip_mc_join_group(sk, &mreq); | 679 | err = ip_mc_join_group(sk, &mreq); |
| 680 | if (err) | 680 | if (err && err != -EADDRINUSE) |
| 681 | break; | 681 | break; |
| 682 | omode = MCAST_INCLUDE; | 682 | omode = MCAST_INCLUDE; |
| 683 | add = 1; | 683 | add = 1; |
| 684 | } else /*IP_DROP_SOURCE_MEMBERSHIP */ { | 684 | } else /* IP_DROP_SOURCE_MEMBERSHIP */ { |
| 685 | omode = MCAST_INCLUDE; | 685 | omode = MCAST_INCLUDE; |
| 686 | add = 0; | 686 | add = 0; |
| 687 | } | 687 | } |
| @@ -754,7 +754,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
| 754 | mreq.imr_address.s_addr = 0; | 754 | mreq.imr_address.s_addr = 0; |
| 755 | mreq.imr_ifindex = greqs.gsr_interface; | 755 | mreq.imr_ifindex = greqs.gsr_interface; |
| 756 | err = ip_mc_join_group(sk, &mreq); | 756 | err = ip_mc_join_group(sk, &mreq); |
| 757 | if (err) | 757 | if (err && err != -EADDRINUSE) |
| 758 | break; | 758 | break; |
| 759 | greqs.gsr_interface = mreq.imr_ifindex; | 759 | greqs.gsr_interface = mreq.imr_ifindex; |
| 760 | omode = MCAST_INCLUDE; | 760 | omode = MCAST_INCLUDE; |
