sctp: use the right sk after waking up from wait_buf sleep
[pandora-kernel.git] / net / bridge / br_multicast.c
index 5ac1811..5f21e53 100644 (file)
@@ -36,6 +36,9 @@
 #define mlock_dereference(X, br) \
        rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
 
+static void br_multicast_add_router(struct net_bridge *br,
+                                   struct net_bridge_port *port);
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
 {
@@ -467,8 +470,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
        skb_set_transport_header(skb, skb->len);
        mldq = (struct mld_msg *) icmp6_hdr(skb);
 
-       interval = ipv6_addr_any(group) ? br->multicast_last_member_interval :
-                                         br->multicast_query_response_interval;
+       interval = ipv6_addr_any(group) ?
+                       br->multicast_query_response_interval :
+                       br->multicast_last_member_interval;
 
        mldq->mld_type = ICMPV6_MGM_QUERY;
        mldq->mld_code = 0;
@@ -841,6 +845,8 @@ void br_multicast_enable_port(struct net_bridge_port *port)
                goto out;
 
        __br_multicast_enable_port(port);
+       if (port->multicast_router == 2 && hlist_unhashed(&port->rlist))
+               br_multicast_add_router(br, port);
 
 out:
        spin_unlock(&br->multicast_lock);
@@ -971,7 +977,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
                }
 
                err = br_ip6_multicast_add_group(br, port, &grec->grec_mca);
-               if (!err)
+               if (err)
                        break;
        }
 
@@ -990,6 +996,9 @@ static void br_multicast_add_router(struct net_bridge *br,
        struct net_bridge_port *p;
        struct hlist_node *n, *slot = NULL;
 
+       if (!hlist_unhashed(&port->rlist))
+               return;
+
        hlist_for_each_entry(p, n, &br->router_list, rlist) {
                if ((unsigned long) port >= (unsigned long) p)
                        break;
@@ -1017,12 +1026,8 @@ static void br_multicast_mark_router(struct net_bridge *br,
        if (port->multicast_router != 1)
                return;
 
-       if (!hlist_unhashed(&port->rlist))
-               goto timer;
-
        br_multicast_add_router(br, port);
 
-timer:
        mod_timer(&port->multicast_router_timer,
                  now + br->multicast_querier_interval);
 }
@@ -1137,6 +1142,12 @@ static int br_ip6_multicast_query(struct net_bridge *br,
 
        br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr));
 
+       /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
+       if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
+               err = -EINVAL;
+               goto out;
+       }
+
        if (skb->len == sizeof(*mld)) {
                if (!pskb_may_pull(skb, sizeof(*mld))) {
                        err = -EINVAL;
@@ -1154,7 +1165,8 @@ static int br_ip6_multicast_query(struct net_bridge *br,
                mld2q = (struct mld2_query *)icmp6_hdr(skb);
                if (!mld2q->mld2q_nsrcs)
                        group = &mld2q->mld2q_mca;
-               max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1;
+
+               max_delay = max(msecs_to_jiffies(MLDV2_MRC(ntohs(mld2q->mld2q_mrc))), 1UL);
        }
 
        if (!group)
@@ -1741,7 +1753,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
        u32 old;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (!netif_running(br->dev))
                goto unlock;
 
@@ -1773,7 +1785,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }