Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 2418
b: refs/heads/master
c: c9e3e8b
h: refs/heads/master
v: v3
  • Loading branch information
David L Stevens authored and David S. Miller committed Jun 21, 2005
1 parent 577d03f commit c8f8c47
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d51aa80a9b1db43920c0770c3bb842dd823c005
refs/heads/master: c9e3e8b6958e02230079e6817862ea2968509866
5 changes: 3 additions & 2 deletions trunk/net/ipv6/ipv6_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,12 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
&psin6->sin6_addr);
if (retv)
/* prior join w/ different source is ok */
if (retv && retv != -EADDRINUSE)
break;
omode = MCAST_INCLUDE;
add = 1;
} else /*IP_DROP_SOURCE_MEMBERSHIP */ {
} else /* MCAST_LEAVE_SOURCE_GROUP */ {
omode = MCAST_INCLUDE;
add = 0;
}
Expand Down
21 changes: 21 additions & 0 deletions trunk/net/ipv6/mcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,16 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
if (!ipv6_addr_is_multicast(addr))
return -EINVAL;

read_lock_bh(&ipv6_sk_mc_lock);
for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) {
if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
ipv6_addr_equal(&mc_lst->addr, addr)) {
read_unlock_bh(&ipv6_sk_mc_lock);
return -EADDRINUSE;
}
}
read_unlock_bh(&ipv6_sk_mc_lock);

mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);

if (mc_lst == NULL)
Expand Down Expand Up @@ -349,6 +359,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
struct ipv6_pinfo *inet6 = inet6_sk(sk);
struct ip6_sf_socklist *psl;
int i, j, rv;
int leavegroup = 0;
int err;

if (pgsr->gsr_group.ss_family != AF_INET6 ||
Expand All @@ -368,6 +379,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,

err = -EADDRNOTAVAIL;

read_lock_bh(&ipv6_sk_mc_lock);
for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
continue;
Expand Down Expand Up @@ -401,6 +413,12 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
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 */
ip6_mc_del_src(idev, group, omode, 1, source, 1);

Expand Down Expand Up @@ -453,9 +471,12 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
/* update the interface list */
ip6_mc_add_src(idev, group, omode, 1, source, 1);
done:
read_unlock_bh(&ipv6_sk_mc_lock);
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
dev_put(dev);
if (leavegroup)
return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
return err;
}

Expand Down

0 comments on commit c8f8c47

Please sign in to comment.