lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20130214042543.GB24534@order.stressinduktion.org>
Date:	Thu, 14 Feb 2013 05:25:44 +0100
From:	Hannes Frederic Sowa <hannes@...essinduktion.org>
To:	YOSHIFUJI Hideaki <yoshfuji@...ux-ipv6.org>
Cc:	Brian Haley <brian.haley@...com>, netdev@...r.kernel.org
Subject: Re: [PATCH net-next 2/3] ipv6: use newly introduced __ipv6_addr_needs_scope_id and ipv6_iface_scope_id

On Thu, Feb 14, 2013 at 01:47:47AM +0900, YOSHIFUJI Hideaki wrote:
> If you have several address checks around, please use ipv6_addr_type()
> (or __ipv6_addr_type()).  Above "direct" checks should be used only for
> single-shot test.  But well, I have to agree that ipv6_addr_type and
> friends is becoming complex.  In mid-term, I would like to take look
> at it.  I might think of having addr_type for src/dst in skb->cb
> after all.

What do you think about the attached patch?  If you agree with the changes I
would test it tomorrow and rebase my other patches ontop. The changes are only
compile tested.

[PATCH net-next RFC] ipv6: introduce new type ipv6_addr_props to hold type and scope

---
 include/net/ipv6.h       | 16 +++++---
 net/ipv6/addrconf.c      | 27 +++++++-------
 net/ipv6/addrconf_core.c | 97 +++++++++++++++++++++++++++++++-----------------
 net/ipv6/datagram.c      | 12 +++---
 4 files changed, 95 insertions(+), 57 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 851d541..3a3ec1cc 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -298,20 +298,26 @@ static inline int ip6_frag_mem(struct net *net)
 #define IPV6_FRAG_LOW_THRESH	(3 * 1024*1024)	/* 3145728 */
 #define IPV6_FRAG_TIMEOUT	(60 * HZ)	/* 60 seconds */
 
-extern int __ipv6_addr_type(const struct in6_addr *addr);
+struct ipv6_addr_props {
+	u16 type;
+	s16 scope;
+};
+
+extern struct ipv6_addr_props __ipv6_addr_type(const struct in6_addr *addr);
 static inline int ipv6_addr_type(const struct in6_addr *addr)
 {
-	return __ipv6_addr_type(addr) & 0xffff;
+	return __ipv6_addr_type(addr).type;
 }
 
 static inline int ipv6_addr_scope(const struct in6_addr *addr)
 {
-	return __ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK;
+	return __ipv6_addr_type(addr).scope;
 }
 
-static inline int __ipv6_addr_src_scope(int type)
+static inline int __ipv6_addr_src_scope(struct ipv6_addr_props props)
 {
-	return (type == IPV6_ADDR_ANY) ? __IPV6_ADDR_SCOPE_INVALID : (type >> 16);
+	return (props.type == IPV6_ADDR_ANY) ?
+		__IPV6_ADDR_SCOPE_INVALID : props.scope;
 }
 
 static inline int ipv6_addr_src_scope(const struct in6_addr *addr)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 86c235d..f9adec4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1106,7 +1106,7 @@ enum {
 
 struct ipv6_saddr_score {
 	int			rule;
-	int			addr_type;
+	struct ipv6_addr_props	addr_props;
 	struct inet6_ifaddr	*ifa;
 	DECLARE_BITMAP(scorebits, IPV6_SADDR_RULE_MAX);
 	int			scopedist;
@@ -1180,7 +1180,7 @@ static int ipv6_get_saddr_eval(struct net *net,
 		 * C > d + 14 - B >= 15 + 14 - B = 29 - B.
 		 * Assume B = 0 and we get C > 29.
 		 */
-		ret = __ipv6_addr_src_scope(score->addr_type);
+		ret = __ipv6_addr_src_scope(score->addr_props);
 		if (ret >= dst->scope)
 			ret = -ret;
 		else
@@ -1189,8 +1189,9 @@ static int ipv6_get_saddr_eval(struct net *net,
 		break;
 	case IPV6_SADDR_RULE_PREFERRED:
 		/* Rule 3: Avoid deprecated and optimistic addresses */
-		ret = ipv6_saddr_preferred(score->addr_type) ||
-		      !(score->ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
+		ret = ipv6_saddr_preferred(score->addr_props.type) ||
+			!(score->ifa->flags &
+			  (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC));
 		break;
 #ifdef CONFIG_IPV6_MIP6
 	case IPV6_SADDR_RULE_HOA:
@@ -1209,7 +1210,7 @@ static int ipv6_get_saddr_eval(struct net *net,
 	case IPV6_SADDR_RULE_LABEL:
 		/* Rule 6: Prefer matching label */
 		ret = ipv6_addr_label(net,
-				      &score->ifa->addr, score->addr_type,
+				      &score->ifa->addr, score->addr_props.type,
 				      score->ifa->idev->dev->ifindex) == dst->label;
 		break;
 #ifdef CONFIG_IPV6_PRIVACY
@@ -1258,13 +1259,12 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 				*score = &scores[0], *hiscore = &scores[1];
 	struct ipv6_saddr_dst dst;
 	struct net_device *dev;
-	int dst_type;
+	struct ipv6_addr_props dst_props = __ipv6_addr_type(daddr);
 
-	dst_type = __ipv6_addr_type(daddr);
 	dst.addr = daddr;
 	dst.ifindex = dst_dev ? dst_dev->ifindex : 0;
-	dst.scope = __ipv6_addr_src_scope(dst_type);
-	dst.label = ipv6_addr_label(net, daddr, dst_type, dst.ifindex);
+	dst.scope = __ipv6_addr_src_scope(dst_props);
+	dst.label = ipv6_addr_label(net, daddr, dst_props.type, dst.ifindex);
 	dst.prefs = prefs;
 
 	hiscore->rule = -1;
@@ -1287,7 +1287,7 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 		 *    belonging to the same site as the outgoing
 		 *    interface.)
 		 */
-		if (((dst_type & IPV6_ADDR_MULTICAST) ||
+		if ((dst_props.type & IPV6_ADDR_MULTICAST ||
 		     dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
 		    dst.ifindex && dev->ifindex != dst.ifindex)
 			continue;
@@ -1314,10 +1314,11 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
 			    (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
 				continue;
 
-			score->addr_type = __ipv6_addr_type(&score->ifa->addr);
+			score->addr_props = __ipv6_addr_type(&score->ifa->addr);
 
-			if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
-				     score->addr_type & IPV6_ADDR_MULTICAST)) {
+			if (unlikely(score->addr_props.type == IPV6_ADDR_ANY ||
+				     score->addr_props.type &
+				     IPV6_ADDR_MULTICAST)) {
 				LIMIT_NETDEBUG(KERN_DEBUG
 					       "ADDRCONF: unspecified / multicast address "
 					       "assigned as unicast address on %s",
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index d051e5f..cb3eb1d 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -6,75 +6,104 @@
 #include <linux/export.h>
 #include <net/ipv6.h>
 
-#define IPV6_ADDR_SCOPE_TYPE(scope)	((scope) << 16)
-
-static inline unsigned int ipv6_addr_scope2type(unsigned int scope)
+static inline struct ipv6_addr_props ipv6_addr_scope2type(unsigned int scope)
 {
 	switch (scope) {
 	case IPV6_ADDR_SCOPE_NODELOCAL:
-		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) |
-			IPV6_ADDR_LOOPBACK);
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK,
+			.scope = IPV6_ADDR_SCOPE_NODELOCAL
+		};
 	case IPV6_ADDR_SCOPE_LINKLOCAL:
-		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) |
-			IPV6_ADDR_LINKLOCAL);
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL,
+			.scope = IPV6_ADDR_SCOPE_LINKLOCAL
+		};
 	case IPV6_ADDR_SCOPE_SITELOCAL:
-		return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) |
-			IPV6_ADDR_SITELOCAL);
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_MULTICAST|IPV6_ADDR_SITELOCAL,
+			.scope = IPV6_ADDR_SCOPE_SITELOCAL
+		};
 	}
-	return IPV6_ADDR_SCOPE_TYPE(scope);
+	return (struct ipv6_addr_props){
+		.type = IPV6_ADDR_MULTICAST,
+		.scope = scope
+	};
 }
 
-int __ipv6_addr_type(const struct in6_addr *addr)
+struct ipv6_addr_props __ipv6_addr_type(const struct in6_addr *addr)
 {
-	__be32 st;
-
-	st = addr->s6_addr32[0];
+	__be32 st = addr->s6_addr32[0];
 
 	/* Consider all addresses with the first three bits different of
 	   000 and 111 as unicasts.
 	 */
 	if ((st & htonl(0xE0000000)) != htonl(0x00000000) &&
 	    (st & htonl(0xE0000000)) != htonl(0xE0000000))
-		return (IPV6_ADDR_UNICAST |
-			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_UNICAST,
+			.scope = IPV6_ADDR_SCOPE_GLOBAL
+		};
 
 	if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) {
 		/* multicast */
 		/* addr-select 3.1 */
-		return (IPV6_ADDR_MULTICAST |
-			ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr)));
+		return ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr));
 	}
 
 	if ((st & htonl(0xFFC00000)) == htonl(0xFE800000))
-		return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST |
-			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));		/* addr-select 3.1 */
+		/* addr-select 3.1 */
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST,
+			.scope = IPV6_ADDR_SCOPE_LINKLOCAL
+		};
 	if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000))
-		return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST |
-			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL));		/* addr-select 3.1 */
+		/* addr-select 3.1 */
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST,
+			.scope = IPV6_ADDR_SCOPE_SITELOCAL,
+		};
 	if ((st & htonl(0xFE000000)) == htonl(0xFC000000))
-		return (IPV6_ADDR_UNICAST |
-			IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));			/* RFC 4193 */
+		/* RFC 4193 */
+		return (struct ipv6_addr_props){
+			.type = IPV6_ADDR_UNICAST,
+			.scope = IPV6_ADDR_SCOPE_GLOBAL,
+		};
 
 	if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) {
 		if (addr->s6_addr32[2] == 0) {
 			if (addr->s6_addr32[3] == 0)
-				return IPV6_ADDR_ANY;
+				return (struct ipv6_addr_props){
+					.type = IPV6_ADDR_ANY
+				};
 
 			if (addr->s6_addr32[3] == htonl(0x00000001))
-				return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST |
-					IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL));	/* addr-select 3.4 */
+				/* addr-select 3.4 */
+				return (struct ipv6_addr_props){
+					.type = IPV6_ADDR_LOOPBACK|
+						IPV6_ADDR_UNICAST,
+					.scope = IPV6_ADDR_SCOPE_LINKLOCAL
+				};
 
-			return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST |
-				IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.3 */
+			/* addr-select 3.3 */
+			return (struct ipv6_addr_props){
+				.type = IPV6_ADDR_COMPATv4|IPV6_ADDR_UNICAST,
+				.scope = IPV6_ADDR_SCOPE_GLOBAL
+			};
 		}
 
 		if (addr->s6_addr32[2] == htonl(0x0000ffff))
-			return (IPV6_ADDR_MAPPED |
-				IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.3 */
+			/* addr-select 3.3 */
+			return (struct ipv6_addr_props){
+				.type = IPV6_ADDR_MAPPED,
+					.scope = IPV6_ADDR_SCOPE_GLOBAL
+					};
 	}
 
-	return (IPV6_ADDR_UNICAST |
-		IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL));	/* addr-select 3.4 */
+	/* addr-select 3.4 */
+	return (struct ipv6_addr_props){
+		.type = IPV6_ADDR_UNICAST,
+		.scope = IPV6_ADDR_SCOPE_GLOBAL
+	};
 }
 EXPORT_SYMBOL(__ipv6_addr_type);
-
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index f5a5478..e859899 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -614,7 +614,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
 	int err = 0;
 
 	for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
-		int addr_type;
+		struct ipv6_addr_props addr_props;
 
 		if (!CMSG_OK(msg, cmsg)) {
 			err = -EINVAL;
@@ -644,7 +644,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
 				fl6->flowi6_oif = src_info->ipi6_ifindex;
 			}
 
-			addr_type = __ipv6_addr_type(&src_info->ipi6_addr);
+			addr_props = __ipv6_addr_type(&src_info->ipi6_addr);
 
 			rcu_read_lock();
 			if (fl6->flowi6_oif) {
@@ -653,13 +653,15 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
 					rcu_read_unlock();
 					return -ENODEV;
 				}
-			} else if (addr_type & IPV6_ADDR_LINKLOCAL) {
+			} else if (addr_props.type & IPV6_ADDR_LINKLOCAL) {
 				rcu_read_unlock();
 				return -EINVAL;
 			}
 
-			if (addr_type != IPV6_ADDR_ANY) {
-				int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL;
+			if (addr_props.type != IPV6_ADDR_ANY) {
+				int strict =
+					__ipv6_addr_src_scope(addr_props) <=
+					IPV6_ADDR_SCOPE_LINKLOCAL;
 				if (!(inet_sk(sk)->freebind || inet_sk(sk)->transparent) &&
 				    !ipv6_chk_addr(net, &src_info->ipi6_addr,
 						   strict ? dev : NULL, 0))
-- 
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ