|
@@ -1793,29 +1793,35 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
|
|
|
struct in_device *in_dev;
|
|
|
u32 group = imr->imr_multiaddr.s_addr;
|
|
|
u32 ifindex;
|
|
|
+ int ret = -EADDRNOTAVAIL;
|
|
|
|
|
|
rtnl_lock();
|
|
|
in_dev = ip_mc_find_dev(imr);
|
|
|
- if (!in_dev) {
|
|
|
- rtnl_unlock();
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
ifindex = imr->imr_ifindex;
|
|
|
for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
|
|
|
- if (iml->multi.imr_multiaddr.s_addr == group &&
|
|
|
- iml->multi.imr_ifindex == ifindex) {
|
|
|
- (void) ip_mc_leave_src(sk, iml, in_dev);
|
|
|
+ if (iml->multi.imr_multiaddr.s_addr != group)
|
|
|
+ continue;
|
|
|
+ if (ifindex) {
|
|
|
+ if (iml->multi.imr_ifindex != ifindex)
|
|
|
+ continue;
|
|
|
+ } else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
|
|
|
+ iml->multi.imr_address.s_addr)
|
|
|
+ continue;
|
|
|
|
|
|
- *imlp = iml->next;
|
|
|
+ (void) ip_mc_leave_src(sk, iml, in_dev);
|
|
|
|
|
|
+ *imlp = iml->next;
|
|
|
+
|
|
|
+ if (in_dev)
|
|
|
ip_mc_dec_group(in_dev, group);
|
|
|
- rtnl_unlock();
|
|
|
- sock_kfree_s(sk, iml, sizeof(*iml));
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ rtnl_unlock();
|
|
|
+ sock_kfree_s(sk, iml, sizeof(*iml));
|
|
|
+ return 0;
|
|
|
}
|
|
|
+ if (!in_dev)
|
|
|
+ ret = -ENODEV;
|
|
|
rtnl_unlock();
|
|
|
- return -EADDRNOTAVAIL;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
int ip_mc_source(int add, int omode, struct sock *sk, struct
|