Commit 479840ff authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

ipv6 addrconf: extend ifa_flags to u32



There is no more space in u8 ifa_flags. So do what davem suffested and
add another netlink attr called IFA_FLAGS for carry more flags.

Signed-off-by: default avatarJiri Pirko <jiri@resnulli.us>
Signed-off-by: default avatarThomas Haller <thaller@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e6247027
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -81,9 +81,9 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dev,
		       const struct in6_addr *daddr, unsigned int srcprefs,
		       struct in6_addr *saddr);
int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
		      unsigned char banned_flags);
		      u32 banned_flags);
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
		    unsigned char banned_flags);
		    u32 banned_flags);
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2);
void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);
void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr);
+1 −1
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ struct inet6_ifaddr {

	int			state;

	__u32			flags;
	__u8			dad_probes;
	__u8			flags;

	__u16			scope;

+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ struct ifaddrmsg {
 * It makes no difference for normally configured broadcast interfaces,
 * but for point-to-point IFA_ADDRESS is DESTINATION address,
 * local address is supplied in IFA_LOCAL attribute.
 *
 * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
 * If present, the value from struct ifaddrmsg will be ignored.
 */
enum {
	IFA_UNSPEC,
@@ -28,6 +31,7 @@ enum {
	IFA_ANYCAST,
	IFA_CACHEINFO,
	IFA_MULTICAST,
	IFA_FLAGS,
	__IFA_MAX,
};

+20 −12
Original line number Diff line number Diff line
@@ -1407,7 +1407,7 @@ try_nextdev:
EXPORT_SYMBOL(ipv6_dev_get_saddr);

int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
		      unsigned char banned_flags)
		      u32 banned_flags)
{
	struct inet6_ifaddr *ifp;
	int err = -EADDRNOTAVAIL;
@@ -1424,7 +1424,7 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
}

int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
		    unsigned char banned_flags)
		    u32 banned_flags)
{
	struct inet6_dev *idev;
	int err = -EADDRNOTAVAIL;
@@ -2178,7 +2178,7 @@ ok:
		}

		if (ifp) {
			int flags;
			u32 flags;
			unsigned long now;
			struct inet6_ifaddr *ift;
			u32 stored_lft;
@@ -2363,10 +2363,11 @@ err_exit:
/*
 *	Manual configuration of address on an interface
 */
static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx,
static int inet6_addr_add(struct net *net, int ifindex,
			  const struct in6_addr *pfx,
			  const struct in6_addr *peer_pfx,
			  unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
			  __u32 valid_lft)
			  unsigned int plen, __u32 ifa_flags,
			  __u32 prefered_lft, __u32 valid_lft)
{
	struct inet6_ifaddr *ifp;
	struct inet6_dev *idev;
@@ -3351,7 +3352,7 @@ static void if6_seq_stop(struct seq_file *seq, void *v)
static int if6_seq_show(struct seq_file *seq, void *v)
{
	struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
	seq_printf(seq, "%pi6 %02x %02x %02x %02x %8s\n",
	seq_printf(seq, "%pi6 %02x %02x %02x %03x %8s\n",
		   &ifp->addr,
		   ifp->idev->dev->ifindex,
		   ifp->prefix_len,
@@ -3572,6 +3573,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
	[IFA_ADDRESS]		= { .len = sizeof(struct in6_addr) },
	[IFA_LOCAL]		= { .len = sizeof(struct in6_addr) },
	[IFA_CACHEINFO]		= { .len = sizeof(struct ifa_cacheinfo) },
	[IFA_FLAGS]		= { .len = sizeof(u32) },
};

static int
@@ -3595,7 +3597,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
	return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
}

static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
			     u32 prefered_lft, u32 valid_lft)
{
	u32 flags;
@@ -3650,7 +3652,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
	struct inet6_ifaddr *ifa;
	struct net_device *dev;
	u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
	u8 ifa_flags;
	u32 ifa_flags;
	int err;

	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
@@ -3677,8 +3679,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
	if (dev == NULL)
		return -ENODEV;

	ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;

	/* We ignore other flags so far. */
	ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS);
	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS;

	ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
	if (ifa == NULL) {
@@ -3702,7 +3706,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
	return err;
}

static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,
static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
			  u8 scope, int ifindex)
{
	struct ifaddrmsg *ifm;
@@ -3745,7 +3749,8 @@ static inline int inet6_ifaddr_msgsize(void)
	return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
	       + nla_total_size(16) /* IFA_LOCAL */
	       + nla_total_size(16) /* IFA_ADDRESS */
	       + nla_total_size(sizeof(struct ifa_cacheinfo));
	       + nla_total_size(sizeof(struct ifa_cacheinfo))
	       + nla_total_size(4)  /* IFA_FLAGS */;
}

static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3793,6 +3798,9 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
	if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
		goto error;

	if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
		goto error;

	return nlmsg_end(skb, nlh);

error: