[SCM] Samba Shared Repository - branch v3-2-test updated - initial-v3-2-unstable-120-ge6609ca

Jeremy Allison jra at samba.org
Fri Oct 26 01:35:10 GMT 2007


The branch, v3-2-test has been updated
       via  e6609cab732d5cd5cc9a5ae50aee15147f2ec6ec (commit)
      from  2df8252ff76406bfe57cd76e9927b5056e89e6ae (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-2-test


- Log -----------------------------------------------------------------
commit e6609cab732d5cd5cc9a5ae50aee15147f2ec6ec
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Oct 25 18:28:36 2007 -0700

    Fix resolve name to resolve IPv6 addresses of link-local%ifaddr
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 source/lib/interface.c    |  117 +++++++++------------------------------------
 source/lib/interfaces.c   |  117 +++++++++++++++++++++++++++++++++++++++++++--
 source/lib/util_sock.c    |    6 ++-
 source/libsmb/namequery.c |   26 ++++++++++
 4 files changed, 166 insertions(+), 100 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source/lib/interface.c b/source/lib/interface.c
index 49bbcec..9d073bc 100644
--- a/source/lib/interface.c
+++ b/source/lib/interface.c
@@ -88,6 +88,29 @@ bool is_local_net(const struct sockaddr_storage *from)
 	return false;
 }
 
+#if defined(HAVE_IPV6)
+void setup_linklocal_scope_id(struct sockaddr_storage *pss)
+{
+	struct interface *i;
+	for (i=local_interfaces;i;i=i->next) {
+		if (addr_equal(&i->ip,pss)) {
+			struct sockaddr_in6 *psa6 =
+				(struct sockaddr_in6 *)pss;
+			psa6->sin6_scope_id = if_nametoindex(i->name);
+			return;
+		}
+	}
+	for (i=local_interfaces;i;i=i->next) {
+		if (same_net(pss, &i->ip, &i->netmask)) {
+			struct sockaddr_in6 *psa6 =
+				(struct sockaddr_in6 *)pss;
+			psa6->sin6_scope_id = if_nametoindex(i->name);
+			return;
+		}
+	}
+}
+#endif
+
 /****************************************************************************
  Check if a packet is from a local (known) net.
 **************************************************************************/
@@ -326,100 +349,6 @@ static void add_interface(const struct iface_struct *ifs)
 }
 
 /****************************************************************************
- Create a struct sockaddr_storage with the netmask bits set to 1.
-****************************************************************************/
-
-bool make_netmask(struct sockaddr_storage *pss_out,
-			const struct sockaddr_storage *pss_in,
-			unsigned long masklen)
-{
-	*pss_out = *pss_in;
-	/* Now apply masklen bits of mask. */
-#if defined(HAVE_IPV6)
-	if (pss_in->ss_family == AF_INET6) {
-		char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
-		unsigned int i;
-
-		if (masklen > 128) {
-			return false;
-		}
-		for (i = 0; masklen >= 8; masklen -= 8, i++) {
-			*p++ = 0xff;
-		}
-		/* Deal with the partial byte. */
-		*p++ &= (0xff & ~(0xff>>masklen));
-		i++;
-		for (;i < sizeof(struct in6_addr); i++) {
-			*p++ = '\0';
-		}
-		return true;
-	}
-#endif
-	if (pss_in->ss_family == AF_INET) {
-		if (masklen > 32) {
-			return false;
-		}
-		((struct sockaddr_in *)pss_out)->sin_addr.s_addr =
-			htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL));
-		return true;
-	}
-	return false;
-}
-
-/****************************************************************************
- Create a struct sockaddr_storage set to the broadcast or network adress from
- an incoming sockaddr_storage.
-****************************************************************************/
-
-static void make_bcast_or_net(struct sockaddr_storage *pss_out,
-			const struct sockaddr_storage *pss_in,
-			const struct sockaddr_storage *nmask,
-			bool make_bcast)
-{
-	unsigned int i = 0, len = 0;
-	char *pmask = NULL;
-	char *p = NULL;
-	*pss_out = *pss_in;
-
-	/* Set all zero netmask bits to 1. */
-#if defined(HAVE_IPV6)
-	if (pss_in->ss_family == AF_INET6) {
-		p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
-		pmask = (char *)&((struct sockaddr_in6 *)nmask)->sin6_addr;
-		len = 16;
-	}
-#endif
-	if (pss_in->ss_family == AF_INET) {
-		p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr;
-		pmask = (char *)&((struct sockaddr_in *)nmask)->sin_addr;
-		len = 4;
-	}
-
-	for (i = 0; i < len; i++, p++, pmask++) {
-		if (make_bcast) {
-			*p = (*p & *pmask) | (*pmask ^ 0xff);
-		} else {
-			/* make_net */
-			*p = (*p & *pmask);
-		}
-	}
-}
-
-static void make_bcast(struct sockaddr_storage *pss_out,
-			const struct sockaddr_storage *pss_in,
-			const struct sockaddr_storage *nmask)
-{
-	make_bcast_or_net(pss_out, pss_in, nmask, true);
-}
-
-static void make_net(struct sockaddr_storage *pss_out,
-			const struct sockaddr_storage *pss_in,
-			const struct sockaddr_storage *nmask)
-{
-	make_bcast_or_net(pss_out, pss_in, nmask, false);
-}
-
-/****************************************************************************
  Interpret a single element from a interfaces= config line.
 
  This handles the following different forms:
diff --git a/source/lib/interfaces.c b/source/lib/interfaces.c
index ee5d9df..48fe249 100644
--- a/source/lib/interfaces.c
+++ b/source/lib/interfaces.c
@@ -88,6 +88,104 @@
 #include "lib/replace/replace.h"
 
 /****************************************************************************
+ Utility functions.
+****************************************************************************/
+
+/****************************************************************************
+ Create a struct sockaddr_storage with the netmask bits set to 1.
+****************************************************************************/
+
+bool make_netmask(struct sockaddr_storage *pss_out,
+			const struct sockaddr_storage *pss_in,
+			unsigned long masklen)
+{
+	*pss_out = *pss_in;
+	/* Now apply masklen bits of mask. */
+#if defined(HAVE_IPV6)
+	if (pss_in->ss_family == AF_INET6) {
+		char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
+		unsigned int i;
+
+		if (masklen > 128) {
+			return false;
+		}
+		for (i = 0; masklen >= 8; masklen -= 8, i++) {
+			*p++ = 0xff;
+		}
+		/* Deal with the partial byte. */
+		*p++ &= (0xff & ~(0xff>>masklen));
+		i++;
+		for (;i < sizeof(struct in6_addr); i++) {
+			*p++ = '\0';
+		}
+		return true;
+	}
+#endif
+	if (pss_in->ss_family == AF_INET) {
+		if (masklen > 32) {
+			return false;
+		}
+		((struct sockaddr_in *)pss_out)->sin_addr.s_addr =
+			htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL));
+		return true;
+	}
+	return false;
+}
+
+/****************************************************************************
+ Create a struct sockaddr_storage set to the broadcast or network adress from
+ an incoming sockaddr_storage.
+****************************************************************************/
+
+static void make_bcast_or_net(struct sockaddr_storage *pss_out,
+			const struct sockaddr_storage *pss_in,
+			const struct sockaddr_storage *nmask,
+			bool make_bcast)
+{
+	unsigned int i = 0, len = 0;
+	char *pmask = NULL;
+	char *p = NULL;
+	*pss_out = *pss_in;
+
+	/* Set all zero netmask bits to 1. */
+#if defined(HAVE_IPV6)
+	if (pss_in->ss_family == AF_INET6) {
+		p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
+		pmask = (char *)&((struct sockaddr_in6 *)nmask)->sin6_addr;
+		len = 16;
+	}
+#endif
+	if (pss_in->ss_family == AF_INET) {
+		p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr;
+		pmask = (char *)&((struct sockaddr_in *)nmask)->sin_addr;
+		len = 4;
+	}
+
+	for (i = 0; i < len; i++, p++, pmask++) {
+		if (make_bcast) {
+			*p = (*p & *pmask) | (*pmask ^ 0xff);
+		} else {
+			/* make_net */
+			*p = (*p & *pmask);
+		}
+	}
+}
+
+void make_bcast(struct sockaddr_storage *pss_out,
+			const struct sockaddr_storage *pss_in,
+			const struct sockaddr_storage *nmask)
+{
+	make_bcast_or_net(pss_out, pss_in, nmask, true);
+}
+
+void make_net(struct sockaddr_storage *pss_out,
+			const struct sockaddr_storage *pss_in,
+			const struct sockaddr_storage *nmask)
+{
+	make_bcast_or_net(pss_out, pss_in, nmask, false);
+}
+
+/****************************************************************************
  Try the "standard" getifaddrs/freeifaddrs interfaces.
  Also gets IPv6 interfaces.
 ****************************************************************************/
@@ -137,11 +235,20 @@ static int _get_interfaces(struct iface_struct *ifaces, int max_interfaces)
 		memcpy(&ifaces[total].ip, ifptr->ifa_addr, copy_size);
 		memcpy(&ifaces[total].netmask, ifptr->ifa_netmask, copy_size);
 
-		if ((ifaces[total].flags & (IFF_BROADCAST|IFF_LOOPBACK)) &&
-				ifptr->ifa_broadaddr) {
-			memcpy(&ifaces[total].bcast,
-				ifptr->ifa_broadaddr,
-				copy_size);
+		if (ifaces[total].flags & (IFF_BROADCAST|IFF_LOOPBACK)) {
+			if (ifptr->ifa_broadaddr) {
+				memcpy(&ifaces[total].bcast,
+					ifptr->ifa_broadaddr,
+					copy_size);
+			} else {
+				/* For some reason ifptr->ifa_broadaddr
+				 * is null. Make one from ifa_addr and
+				 * ifa_netmask.
+				 */
+				make_bcast(&ifaces[total].bcast,
+					&ifaces[total].ip,
+					&ifaces[total].netmask);
+			}
 		} else if ((ifaces[total].flags & IFF_POINTOPOINT) &&
 			       ifptr->ifa_dstaddr ) {
 			memcpy(&ifaces[total].bcast,
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 8a85f7a..c30f21e 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -64,7 +64,7 @@ bool is_ipaddress(const char *str)
 }
 
 /****************************************************************************
- Is a sockaddr_storage a broadcast address ? 
+ Is a sockaddr_storage a broadcast address ?
 ****************************************************************************/
 
 bool is_broadcast_addr(const struct sockaddr_storage *pss)
@@ -1478,6 +1478,10 @@ int open_socket_out(int type,
 	if (pss->ss_family == AF_INET6) {
 		struct sockaddr_in6 *psa6 = (struct sockaddr_in6 *)&sock_out;
 		psa6->sin6_port = htons(port);
+		if (psa6->sin6_scope_id == 0 &&
+				IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
+			setup_linklocal_scope_id(&sock_out);
+		}
 	}
 #endif
 	if (pss->ss_family == AF_INET) {
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 34fe09b..90e6be6 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -1594,6 +1594,32 @@ bool resolve_name(const char *name,
 	char *sitename = NULL;
 	int count = 0;
 
+#if defined(HAVE_IPV6)
+	unsigned int if_idx = 0;
+	const char *p = strchr_m(name, '%');
+
+	if (p && (if_idx = if_nametoindex(p+1)) != 0) {
+		char *newname = SMB_STRDUP(name);
+		if (!newname) {
+			return false;
+		}
+		newname[PTR_DIFF(p,name)] = '\0';
+		if (is_ipaddress(newname) &&
+				interpret_string_addr(return_ss,
+					newname, AI_NUMERICHOST)) {
+			struct sockaddr_in6 *psa6 =
+				(struct sockaddr_in6 *)&return_ss;
+			if (psa6->sin6_scope_id == 0 &&
+					IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
+				psa6->sin6_scope_id = if_idx;
+			}
+			SAFE_FREE(newname);
+			return true;
+		}
+		SAFE_FREE(newname);
+	}
+#endif
+
 	if (is_ipaddress(name)) {
 		return interpret_string_addr(return_ss, name, AI_NUMERICHOST);
 	}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list