]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/sctp/ipv6.c
[SCTP] Fix incorrect setting of sk_bound_dev_if when binding/sending to a ipv6
[net-next-2.6.git] / net / sctp / ipv6.c
index c9d9ea064734ad58e18c14e03055816b0c219dd7..c7e42d125b9cc544af46e640a725352c5ea1b6a1 100644 (file)
@@ -812,26 +812,23 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
        if (addr->sa.sa_family != AF_INET6)
                af = sctp_get_af_specific(addr->sa.sa_family);
        else {
-               struct sock *sk;
                int type = ipv6_addr_type(&addr->v6.sin6_addr);
-               sk = sctp_opt2sk(opt);
+               struct net_device *dev;
+
                if (type & IPV6_ADDR_LINKLOCAL) {
-                       /* Note: Behavior similar to af_inet6.c:
-                        *  1) Overrides previous bound_dev_if
-                        *  2) Destructive even if bind isn't successful.
-                        */
-
-                       if (addr->v6.sin6_scope_id)
-                               sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
-                       if (!sk->sk_bound_dev_if)
+                       if (!addr->v6.sin6_scope_id)
+                               return 0;
+                       dev = dev_get_by_index(addr->v6.sin6_scope_id);
+                       if (!dev)
                                return 0;
+                       dev_put(dev);
                }
                af = opt->pf->af;
        }
        return af->available(addr, opt);
 }
 
-/* Verify that the provided sockaddr looks bindable.   Common verification,
+/* Verify that the provided sockaddr looks sendable.   Common verification,
  * has already been taken care of.
  */
 static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
@@ -842,19 +839,16 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
        if (addr->sa.sa_family != AF_INET6)
                af = sctp_get_af_specific(addr->sa.sa_family);
        else {
-               struct sock *sk;
                int type = ipv6_addr_type(&addr->v6.sin6_addr);
-               sk = sctp_opt2sk(opt);
+               struct net_device *dev;
+
                if (type & IPV6_ADDR_LINKLOCAL) {
-                       /* Note: Behavior similar to af_inet6.c:
-                        *  1) Overrides previous bound_dev_if
-                        *  2) Destructive even if bind isn't successful.
-                        */
-
-                       if (addr->v6.sin6_scope_id)
-                               sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
-                       if (!sk->sk_bound_dev_if)
+                       if (!addr->v6.sin6_scope_id)
+                               return 0;
+                       dev = dev_get_by_index(addr->v6.sin6_scope_id);
+                       if (!dev)
                                return 0;
+                       dev_put(dev);
                }
                af = opt->pf->af;
        }