Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e1fa36b authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'nla_in_addr'



Jiri Benc says:

====================
netlink: access functions for IP address attributes

There are many places that read or write IP addresses to netlink attributes.
With IPv6 addresses, every such place currently has to use generic nla_put
and nla_memcpy. Implementing IPv6 address access functions simplify things
and makes the code more intelligible. IPv4 address access functions has
lesser value but it would be better to be consistent between IPv6 and IPv4
and they still serve as documentation.

The conversion is straightforward and the resulting patches are not that
large, thus I kept all the changes in the patches that introduce the access
functions. If anyone prefers to split the definition of access functions and
the conversion and/or break it out by network protocols, please let me know.

While doing the conversion, I came across ugly typecasting in
inetpeer_addr_base and xfrm_address_t when dealing with IPv6 addresses.
Instead of introducing more of this, I cleaned it up. Those are the first
two patches, serving as a prerequisite to the latter two.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f0ef3126 67b61f6c
Loading
Loading
Loading
Loading
+18 −20
Original line number Diff line number Diff line
@@ -171,11 +171,11 @@ static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla)
{
	if (nla_len(nla) >= sizeof(struct in6_addr)) {
		nla_memcpy(&ip->sin6.sin6_addr, nla, sizeof(struct in6_addr));
		ip->sin6.sin6_addr = nla_get_in6_addr(nla);
		ip->sa.sa_family = AF_INET6;
		return 0;
	} else if (nla_len(nla) >= sizeof(__be32)) {
		ip->sin.sin_addr.s_addr = nla_get_be32(nla);
		ip->sin.sin_addr.s_addr = nla_get_in_addr(nla);
		ip->sa.sa_family = AF_INET;
		return 0;
	} else {
@@ -187,9 +187,9 @@ static int vxlan_nla_put_addr(struct sk_buff *skb, int attr,
			      const union vxlan_addr *ip)
{
	if (ip->sa.sa_family == AF_INET6)
		return nla_put(skb, attr, sizeof(struct in6_addr), &ip->sin6.sin6_addr);
		return nla_put_in6_addr(skb, attr, &ip->sin6.sin6_addr);
	else
		return nla_put_be32(skb, attr, ip->sin.sin_addr.s_addr);
		return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr);
}

#else /* !CONFIG_IPV6 */
@@ -215,7 +215,7 @@ static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla)
	if (nla_len(nla) >= sizeof(struct in6_addr)) {
		return -EAFNOSUPPORT;
	} else if (nla_len(nla) >= sizeof(__be32)) {
		ip->sin.sin_addr.s_addr = nla_get_be32(nla);
		ip->sin.sin_addr.s_addr = nla_get_in_addr(nla);
		ip->sa.sa_family = AF_INET;
		return 0;
	} else {
@@ -226,7 +226,7 @@ static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla)
static int vxlan_nla_put_addr(struct sk_buff *skb, int attr,
			      const union vxlan_addr *ip)
{
	return nla_put_be32(skb, attr, ip->sin.sin_addr.s_addr);
	return nla_put_in_addr(skb, attr, ip->sin.sin_addr.s_addr);
}
#endif

@@ -2602,27 +2602,25 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
	/* Unless IPv6 is explicitly requested, assume IPv4 */
	dst->remote_ip.sa.sa_family = AF_INET;
	if (data[IFLA_VXLAN_GROUP]) {
		dst->remote_ip.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
		dst->remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
	} else if (data[IFLA_VXLAN_GROUP6]) {
		if (!IS_ENABLED(CONFIG_IPV6))
			return -EPFNOSUPPORT;

		nla_memcpy(&dst->remote_ip.sin6.sin6_addr, data[IFLA_VXLAN_GROUP6],
			   sizeof(struct in6_addr));
		dst->remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]);
		dst->remote_ip.sa.sa_family = AF_INET6;
		use_ipv6 = true;
	}

	if (data[IFLA_VXLAN_LOCAL]) {
		vxlan->saddr.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
		vxlan->saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]);
		vxlan->saddr.sa.sa_family = AF_INET;
	} else if (data[IFLA_VXLAN_LOCAL6]) {
		if (!IS_ENABLED(CONFIG_IPV6))
			return -EPFNOSUPPORT;

		/* TODO: respect scope id */
		nla_memcpy(&vxlan->saddr.sin6.sin6_addr, data[IFLA_VXLAN_LOCAL6],
			   sizeof(struct in6_addr));
		vxlan->saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]);
		vxlan->saddr.sa.sa_family = AF_INET6;
		use_ipv6 = true;
	}
@@ -2807,12 +2805,12 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)

	if (!vxlan_addr_any(&dst->remote_ip)) {
		if (dst->remote_ip.sa.sa_family == AF_INET) {
			if (nla_put_be32(skb, IFLA_VXLAN_GROUP,
			if (nla_put_in_addr(skb, IFLA_VXLAN_GROUP,
					    dst->remote_ip.sin.sin_addr.s_addr))
				goto nla_put_failure;
#if IS_ENABLED(CONFIG_IPV6)
		} else {
			if (nla_put(skb, IFLA_VXLAN_GROUP6, sizeof(struct in6_addr),
			if (nla_put_in6_addr(skb, IFLA_VXLAN_GROUP6,
					     &dst->remote_ip.sin6.sin6_addr))
				goto nla_put_failure;
#endif
@@ -2824,12 +2822,12 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)

	if (!vxlan_addr_any(&vxlan->saddr)) {
		if (vxlan->saddr.sa.sa_family == AF_INET) {
			if (nla_put_be32(skb, IFLA_VXLAN_LOCAL,
			if (nla_put_in_addr(skb, IFLA_VXLAN_LOCAL,
					    vxlan->saddr.sin.sin_addr.s_addr))
				goto nla_put_failure;
#if IS_ENABLED(CONFIG_IPV6)
		} else {
			if (nla_put(skb, IFLA_VXLAN_LOCAL6, sizeof(struct in6_addr),
			if (nla_put_in6_addr(skb, IFLA_VXLAN_LOCAL6,
					     &vxlan->saddr.sin6.sin6_addr))
				goto nla_put_failure;
#endif
+2 −3
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr)

	if (!__nested)
		return -EMSGSIZE;
	ret = nla_put_net32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr);
	ret = nla_put_in_addr(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr);
	if (!ret)
		ipset_nest_end(skb, __nested);
	return ret;
@@ -497,8 +497,7 @@ static inline int nla_put_ipaddr6(struct sk_buff *skb, int type,

	if (!__nested)
		return -EMSGSIZE;
	ret = nla_put(skb, IPSET_ATTR_IPADDR_IPV6,
		      sizeof(struct in6_addr), ipaddrptr);
	ret = nla_put_in6_addr(skb, IPSET_ATTR_IPADDR_IPV6, ipaddrptr);
	if (!ret)
		ipset_nest_end(skb, __nested);
	return ret;
+2 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ struct inetpeer_addr_base {
	union {
		__be32			a4;
		__be32			a6[4];
		struct in6_addr		in6;
	};
};

@@ -151,7 +152,7 @@ static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
{
	struct inetpeer_addr daddr;

	*(struct in6_addr *)daddr.addr.a6 = *v6daddr;
	daddr.addr.in6 = *v6daddr;
	daddr.family = AF_INET6;
	return inet_getpeer(base, &daddr, create);
}
+50 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/netlink.h>
#include <linux/jiffies.h>
#include <linux/in6.h>

/* ========================================================================
 *         Netlink Messages and Attributes Interface (As Seen On TV)
@@ -105,6 +106,8 @@
 *   nla_put_string(skb, type, str)	add string attribute to skb
 *   nla_put_flag(skb, type)		add flag attribute to skb
 *   nla_put_msecs(skb, type, jiffies)	add msecs attribute to skb
 *   nla_put_in_addr(skb, type, addr)	add IPv4 address attribute to skb
 *   nla_put_in6_addr(skb, type, addr)	add IPv6 address attribute to skb
 *
 * Nested Attributes Construction:
 *   nla_nest_start(skb, type)		start a nested attribute
@@ -956,6 +959,32 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
	return nla_put(skb, attrtype, sizeof(u64), &tmp);
}

/**
 * nla_put_in_addr - Add an IPv4 address netlink attribute to a socket
 * buffer
 * @skb: socket buffer to add attribute to
 * @attrtype: attribute type
 * @addr: IPv4 address
 */
static inline int nla_put_in_addr(struct sk_buff *skb, int attrtype,
				  __be32 addr)
{
	return nla_put_be32(skb, attrtype, addr);
}

/**
 * nla_put_in6_addr - Add an IPv6 address netlink attribute to a socket
 * buffer
 * @skb: socket buffer to add attribute to
 * @attrtype: attribute type
 * @addr: IPv6 address
 */
static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
				   const struct in6_addr *addr)
{
	return nla_put(skb, attrtype, sizeof(*addr), addr);
}

/**
 * nla_get_u32 - return payload of u32 attribute
 * @nla: u32 netlink attribute
@@ -1098,6 +1127,27 @@ static inline unsigned long nla_get_msecs(const struct nlattr *nla)
	return msecs_to_jiffies((unsigned long) msecs);
}

/**
 * nla_get_in_addr - return payload of IPv4 address attribute
 * @nla: IPv4 address netlink attribute
 */
static inline __be32 nla_get_in_addr(const struct nlattr *nla)
{
	return *(__be32 *) nla_data(nla);
}

/**
 * nla_get_in6_addr - return payload of IPv6 address attribute
 * @nla: IPv6 address netlink attribute
 */
static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla)
{
	struct in6_addr tmp;

	nla_memcpy(&tmp, nla, sizeof(tmp));
	return tmp;
}

/**
 * nla_nest_start - Start a new level of nested attributes
 * @skb: socket buffer to add attributes to
+3 −3
Original line number Diff line number Diff line
@@ -1025,7 +1025,7 @@ xfrm_addr_any(const xfrm_address_t *addr, unsigned short family)
	case AF_INET:
		return addr->a4 == 0;
	case AF_INET6:
		return ipv6_addr_any((struct in6_addr *)&addr->a6);
		return ipv6_addr_any(&addr->in6);
	}
	return 0;
}
@@ -1238,8 +1238,8 @@ void xfrm_flowi_addr_get(const struct flowi *fl,
		memcpy(&daddr->a4, &fl->u.ip4.daddr, sizeof(daddr->a4));
		break;
	case AF_INET6:
		*(struct in6_addr *)saddr->a6 = fl->u.ip6.saddr;
		*(struct in6_addr *)daddr->a6 = fl->u.ip6.daddr;
		saddr->in6 = fl->u.ip6.saddr;
		daddr->in6 = fl->u.ip6.daddr;
		break;
	}
}
Loading