[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 03398) Re: MLDv2 linux implementation questions
David,
Thanks for the quick fixup, but this patch causes a kernel panic on my i386
architecture after the first SSM calls. Also, would it be possible to
fix the IPv4 code
too ?
To reproduce :
./test_msf ff3e::1234
>p 2001:6::1 0
>r 2001:6::1 0
=> kernel panic.
Hoerdt Mickaël
David Stevens wrote:
>Hoerdt,
> Here's the complete patch, which should
>fix the problem you've seen. Please let me know if
>you turn up anything else, of course. :-)
>
> +-DLS
>diff -ruNp linux-2.6.11.12/net/ipv6/ipv6_sockglue.c
>linux-2.6.11.12MCT/net/ipv6/ipv6_sockglue.c
>--- linux-2.6.11.12/net/ipv6/ipv6_sockglue.c 2005-03-01
>23:37:48.000000000 -0800
>+++ linux-2.6.11.12MCT/net/ipv6/ipv6_sockglue.c 2005-06-15
>14:17:46.000000000 -0700
>@@ -423,11 +423,12 @@ done:
> 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;
> }
>diff -ruNp linux-2.6.11.12/net/ipv6/mcast.c
>linux-2.6.11.12MCT/net/ipv6/mcast.c
>--- linux-2.6.11.12/net/ipv6/mcast.c 2005-03-01 23:38:25.000000000
>-0800
>+++ linux-2.6.11.12MCT/net/ipv6/mcast.c 2005-06-14 16:37:22.000000000
>-0700
>@@ -188,6 +188,16 @@ int ipv6_sock_mc_join(struct sock *sk, i
> 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)
>@@ -241,19 +251,18 @@ int ipv6_sock_mc_join(struct sock *sk, i
> /*
> * socket leave on multicast group
> */
>-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr
>*addr)
>+static int __ipv6_sock_mc_drop(struct sock *sk, int ifindex,
>+ struct in6_addr *addr)
> {
> struct ipv6_pinfo *np = inet6_sk(sk);
> struct ipv6_mc_socklist *mc_lst, **lnk;
>
>- write_lock_bh(&ipv6_sk_mc_lock);
> for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk =
>&mc_lst->next) {
> if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
> ipv6_addr_equal(&mc_lst->addr, addr)) {
> struct net_device *dev;
>
> *lnk = mc_lst->next;
>- write_unlock_bh(&ipv6_sk_mc_lock);
>
> if ((dev = dev_get_by_index(mc_lst->ifindex)) !=
>NULL) {
> struct inet6_dev *idev = in6_dev_get(dev);
>@@ -269,11 +278,21 @@ int ipv6_sock_mc_drop(struct sock *sk, i
> return 0;
> }
> }
>- write_unlock_bh(&ipv6_sk_mc_lock);
>
> return -ENOENT;
> }
>
>+int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr
>*addr)
>+{
>+ int rv;
>+
>+ write_lock_bh(&ipv6_sk_mc_lock);
>+ rv = __ipv6_sock_mc_drop(sk, ifindex, addr);
>+ write_unlock_bh(&ipv6_sk_mc_lock);
>+ return rv;
>+}
>+
>+
> static struct inet6_dev *ip6_mc_find_dev(struct in6_addr *group, int
>ifindex)
> {
> struct net_device *dev = NULL;
>@@ -368,6 +387,7 @@ int ip6_mc_source(int add, int omode, st
>
> err = -EADDRNOTAVAIL;
>
>+ write_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;
>@@ -401,6 +421,13 @@ int ip6_mc_source(int add, int omode, st
> if (rv) /* source not found */
> goto done;
>
>+ /* special case - (INCLUDE, empty) == LEAVE_GROUP */
>+ if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
>+ err = __ipv6_sock_mc_drop(sk, pgsr->gsr_interface,
>+ group);
>+ goto done;
>+ }
>+
> /* update the interface filter */
> ip6_mc_del_src(idev, group, omode, 1, source, 1);
>
>@@ -453,6 +480,7 @@ int ip6_mc_source(int add, int omode, st
> /* update the interface list */
> ip6_mc_add_src(idev, group, omode, 1, source, 1);
> done:
>+ write_unlock_bh(&ipv6_sk_mc_lock);
> read_unlock_bh(&idev->lock);
> in6_dev_put(idev);
> dev_put(dev);
>
>
>
>