Hi David,

David Stevens wrote:
OK, I see what you're trying to fix now.

I think the scope_id checks are not quite right-- they
should be something like this:

if (addr_type&IPV6_ADDR_LINKLOCAL) {
        if (addr_len >= sizeof(struct sockaddr_in6)) {
                if (sk->sk_bound_dev_if && usin->sin6_scope_id &&
                    sk->sk_bound_dev_if != usin->sin6_scope_id) {
                        err = -EINVAL;
                        goto out;
                }
                if (usin->sin6_scope_id)
                        sk->sk_bound_dev_if = usin->sin6_scope_id;
                if (!sk->sk_bound_dev_if &&
                     (addr_type & IPV6_ADDR_MULTICAST))
                        fl.oif = np->mcast_oif;

This assignment will not get us past the next check...

        /* connect to the link-local addres requires an interface */
        if (!sk->sk_bound_dev_if) {
                err = -EINVAL;
                goto out;
        }

... and even if it did, fl.oif is over-written by sk_bound_dev_if just a few lines down.

        If I did an SO_BINDTODEVICE and specified sin6_scope_id,
then they better agree.
        If I specified sin6_scope_id without SO_BINDTODEVICE, set
the device to that.
If I get this far without a device and it's multicast, use mcast_oif
        If I get all through that and don't have a device, EINVAL.

You also need to check if mcast_oif matches sk_bind_dev_if here - it's actually done in the setsockopt() code already when we set it, duplicating it here isn't that big a deal.

How about the following patch? It does not set sk_bound_dev_if to mcast_oif, but does allow the connect() to succeed.

-Brian


Signed-off-by: Brian Haley <[EMAIL PROTECTED]>
---
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 2ed689a..3226970 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -114,6 +114,8 @@ ipv4_connected:
 		goto out;
 	}
 
+	fl.oif = sk->sk_bound_dev_if;
+
 	if (addr_type&IPV6_ADDR_LINKLOCAL) {
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    usin->sin6_scope_id) {
@@ -122,14 +124,14 @@ ipv4_connected:
 				err = -EINVAL;
 				goto out;
 			}
-			sk->sk_bound_dev_if = usin->sin6_scope_id;
-			if (!sk->sk_bound_dev_if &&
-			    (addr_type & IPV6_ADDR_MULTICAST))
-				fl.oif = np->mcast_oif;
+			fl.oif = sk->sk_bound_dev_if = usin->sin6_scope_id;
 		}
 
+		if (!fl.oif && (addr_type & IPV6_ADDR_MULTICAST))
+			fl.oif = np->mcast_oif;
+
 		/* Connect to link-local address requires an interface */
-		if (!sk->sk_bound_dev_if) {
+		if (!fl.oif) {
 			err = -EINVAL;
 			goto out;
 		}
@@ -148,7 +150,6 @@ ipv4_connected:
 	fl.proto = sk->sk_protocol;
 	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
 	ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-	fl.oif = sk->sk_bound_dev_if;
 	fl.fl_ip_dport = inet->dport;
 	fl.fl_ip_sport = inet->sport;
 

Reply via email to