Skip to content

Commit

Permalink
Merge branch 'nla_in_addr'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 31, 2015
2 parents f0ef312 + 67b61f6 commit 8e1fa36
Show file tree
Hide file tree
Showing 36 changed files with 234 additions and 214 deletions.
38 changes: 18 additions & 20 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 */
Expand All @@ -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 {
Expand All @@ -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

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -2807,13 +2805,13 @@ 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,
dst->remote_ip.sin.sin_addr.s_addr))
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),
&dst->remote_ip.sin6.sin6_addr))
if (nla_put_in6_addr(skb, IFLA_VXLAN_GROUP6,
&dst->remote_ip.sin6.sin6_addr))
goto nla_put_failure;
#endif
}
Expand All @@ -2824,13 +2822,13 @@ 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,
vxlan->saddr.sin.sin_addr.s_addr))
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),
&vxlan->saddr.sin6.sin6_addr))
if (nla_put_in6_addr(skb, IFLA_VXLAN_LOCAL6,
&vxlan->saddr.sin6.sin6_addr))
goto nla_put_failure;
#endif
}
Expand Down
5 changes: 2 additions & 3 deletions include/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion include/net/inetpeer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct inetpeer_addr_base {
union {
__be32 a4;
__be32 a6[4];
struct in6_addr in6;
};
};

Expand Down Expand Up @@ -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);
}
Expand Down
50 changes: 50 additions & 0 deletions include/net/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions include/uapi/linux/xfrm.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef _LINUX_XFRM_H
#define _LINUX_XFRM_H

#include <linux/in6.h>
#include <linux/types.h>

/* All of the structures in this file may not change size as they are
Expand All @@ -13,6 +14,7 @@
typedef union {
__be32 a4;
__be32 a6[4];
struct in6_addr in6;
} xfrm_address_t;

/* Ident of a specific xfrm_state. It is used on input to lookup
Expand Down
16 changes: 8 additions & 8 deletions net/ipv4/devinet.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,15 +593,15 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) {
if (tb[IFA_LOCAL] &&
ifa->ifa_local != nla_get_be32(tb[IFA_LOCAL]))
ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL]))
continue;

if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
continue;

if (tb[IFA_ADDRESS] &&
(ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
!inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa)))
!inet_ifa_match(nla_get_in_addr(tb[IFA_ADDRESS]), ifa)))
continue;

if (ipv4_is_multicast(ifa->ifa_address))
Expand Down Expand Up @@ -791,11 +791,11 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = in_dev;

ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]);
ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]);
ifa->ifa_local = nla_get_in_addr(tb[IFA_LOCAL]);
ifa->ifa_address = nla_get_in_addr(tb[IFA_ADDRESS]);

if (tb[IFA_BROADCAST])
ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]);
ifa->ifa_broadcast = nla_get_in_addr(tb[IFA_BROADCAST]);

if (tb[IFA_LABEL])
nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
Expand Down Expand Up @@ -1541,11 +1541,11 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
valid = INFINITY_LIFE_TIME;
}
if ((ifa->ifa_address &&
nla_put_be32(skb, IFA_ADDRESS, ifa->ifa_address)) ||
nla_put_in_addr(skb, IFA_ADDRESS, ifa->ifa_address)) ||
(ifa->ifa_local &&
nla_put_be32(skb, IFA_LOCAL, ifa->ifa_local)) ||
nla_put_in_addr(skb, IFA_LOCAL, ifa->ifa_local)) ||
(ifa->ifa_broadcast &&
nla_put_be32(skb, IFA_BROADCAST, ifa->ifa_broadcast)) ||
nla_put_in_addr(skb, IFA_BROADCAST, ifa->ifa_broadcast)) ||
(ifa->ifa_label[0] &&
nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
Expand Down
12 changes: 6 additions & 6 deletions net/ipv4/fib_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
}

if (frh->src_len)
rule4->src = nla_get_be32(tb[FRA_SRC]);
rule4->src = nla_get_in_addr(tb[FRA_SRC]);

if (frh->dst_len)
rule4->dst = nla_get_be32(tb[FRA_DST]);
rule4->dst = nla_get_in_addr(tb[FRA_DST]);

#ifdef CONFIG_IP_ROUTE_CLASSID
if (tb[FRA_FLOW]) {
Expand Down Expand Up @@ -260,10 +260,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
return 0;
#endif

if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
return 0;

if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
return 0;

return 1;
Expand All @@ -279,9 +279,9 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
frh->tos = rule4->tos;

if ((rule4->dst_len &&
nla_put_be32(skb, FRA_DST, rule4->dst)) ||
nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
(rule4->src_len &&
nla_put_be32(skb, FRA_SRC, rule4->src)))
nla_put_in_addr(skb, FRA_SRC, rule4->src)))
goto nla_put_failure;
#ifdef CONFIG_IP_ROUTE_CLASSID
if (rule4->tclassid &&
Expand Down
12 changes: 6 additions & 6 deletions net/ipv4/fib_semantics.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);

nla = nla_find(attrs, attrlen, RTA_GATEWAY);
nexthop_nh->nh_gw = nla ? nla_get_be32(nla) : 0;
nexthop_nh->nh_gw = nla ? nla_get_in_addr(nla) : 0;
#ifdef CONFIG_IP_ROUTE_CLASSID
nla = nla_find(attrs, attrlen, RTA_FLOW);
nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
Expand Down Expand Up @@ -523,7 +523,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);

nla = nla_find(attrs, attrlen, RTA_GATEWAY);
if (nla && nla_get_be32(nla) != nh->nh_gw)
if (nla && nla_get_in_addr(nla) != nh->nh_gw)
return 1;
#ifdef CONFIG_IP_ROUTE_CLASSID
nla = nla_find(attrs, attrlen, RTA_FLOW);
Expand Down Expand Up @@ -1015,7 +1015,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
rtm->rtm_protocol = fi->fib_protocol;

if (rtm->rtm_dst_len &&
nla_put_be32(skb, RTA_DST, dst))
nla_put_in_addr(skb, RTA_DST, dst))
goto nla_put_failure;
if (fi->fib_priority &&
nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
Expand All @@ -1024,11 +1024,11 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
goto nla_put_failure;

if (fi->fib_prefsrc &&
nla_put_be32(skb, RTA_PREFSRC, fi->fib_prefsrc))
nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc))
goto nla_put_failure;
if (fi->fib_nhs == 1) {
if (fi->fib_nh->nh_gw &&
nla_put_be32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw))
nla_put_in_addr(skb, RTA_GATEWAY, fi->fib_nh->nh_gw))
goto nla_put_failure;
if (fi->fib_nh->nh_oif &&
nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif))
Expand Down Expand Up @@ -1058,7 +1058,7 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
rtnh->rtnh_ifindex = nh->nh_oif;

if (nh->nh_gw &&
nla_put_be32(skb, RTA_GATEWAY, nh->nh_gw))
nla_put_in_addr(skb, RTA_GATEWAY, nh->nh_gw))
goto nla_put_failure;
#ifdef CONFIG_IP_ROUTE_CLASSID
if (nh->nh_tclassid &&
Expand Down
Loading

0 comments on commit 8e1fa36

Please sign in to comment.