patch-2.3.49 linux/net/ipv6/af_inet6.c

Next file: linux/net/ipv6/datagram.c
Previous file: linux/net/ipv4/udp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.48/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
@@ -7,7 +7,10 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.54 2000/02/12 23:34:45 davem Exp $
+ *	$Id: af_inet6.c,v 1.55 2000/02/27 19:51:47 davem Exp $
+ *
+ * 	Fixes:
+ * 	Hideaki YOSHIFUJI	:	sin6_scope_id support
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -220,9 +223,8 @@
 	if(sk->prot->bind)
 		return sk->prot->bind(sk, uaddr, addr_len);
 
-	if (addr_len < sizeof(struct sockaddr_in6))
+	if (addr_len < SIN6_LEN_RFC2133)
 		return -EINVAL;
-
 	addr_type = ipv6_addr_type(&addr->sin6_addr);
 	if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM)
 		return -EINVAL;
@@ -258,6 +260,22 @@
 		return -EINVAL;
 	}
 
+	if (addr_type & IPV6_ADDR_LINKLOCAL) {
+		if (addr_len >= sizeof(struct sockaddr_in6) &&
+		    addr->sin6_scope_id) {
+			/* Override any existing binding, if another one
+			 * is supplied by user.
+			 */
+			sk->bound_dev_if = addr->sin6_scope_id;
+		}
+
+		/* Binding to link-local address requires an interface */
+		if (sk->bound_dev_if == 0) {
+			release_sock(sk);
+			return -EINVAL;
+		}
+	}
+
 	sk->rcv_saddr = v4addr;
 	sk->saddr = v4addr;
 
@@ -338,6 +356,7 @@
   
 	sin->sin6_family = AF_INET6;
 	sin->sin6_flowinfo = 0;
+	sin->sin6_scope_id = 0;
 	if (peer) {
 		if (!sk->dport)
 			return -ENOTCONN;
@@ -360,7 +379,9 @@
 
 		sin->sin6_port = sk->sport;
 	}
-	*uaddr_len = sizeof(*sin);	
+	if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
+		sin->sin6_scope_id = sk->bound_dev_if;
+	*uaddr_len = sizeof(*sin);
 	return(0);
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)