netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch net-next 0/2] ipv6: allow temporary address management for user-created addresses
@ 2013-12-06  8:45 Jiri Pirko
  2013-12-06  8:45 ` [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32 Jiri Pirko
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Jiri Pirko @ 2013-12-06  8:45 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

Jiri Pirko (2):
  ipv6 addrconf: extend ifa_flags to u32
  ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage
    temporary addresses

 include/net/addrconf.h       |   4 +-
 include/net/if_inet6.h       |   2 +-
 include/uapi/linux/if_addr.h |   5 ++
 net/ipv6/addrconf.c          | 201 +++++++++++++++++++++++++------------------
 4 files changed, 126 insertions(+), 86 deletions(-)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32
  2013-12-06  8:45 [patch net-next 0/2] ipv6: allow temporary address management for user-created addresses Jiri Pirko
@ 2013-12-06  8:45 ` Jiri Pirko
  2013-12-06 21:35   ` David Miller
  2013-12-06  8:45 ` [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses Jiri Pirko
  2013-12-06  8:46 ` [patch iproute2 1/2] add support for extended ifa_flags Jiri Pirko
  2 siblings, 1 reply; 12+ messages in thread
From: Jiri Pirko @ 2013-12-06  8:45 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

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: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Thomas Haller <thaller@redhat.com>
---
 include/net/addrconf.h       |  4 ++--
 include/net/if_inet6.h       |  2 +-
 include/uapi/linux/if_addr.h |  4 ++++
 net/ipv6/addrconf.c          | 32 ++++++++++++++++++++------------
 4 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 86505bf..e70278e 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -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);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 76d5427..b58c36c 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -50,8 +50,8 @@ struct inet6_ifaddr {
 
 	int			state;
 
+	__u32			flags;
 	__u8			dad_probes;
-	__u8			flags;
 
 	__u16			scope;
 
diff --git a/include/uapi/linux/if_addr.h b/include/uapi/linux/if_addr.h
index 23357ab..8ab0c2c 100644
--- a/include/uapi/linux/if_addr.h
+++ b/include/uapi/linux/if_addr.h
@@ -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,
 };
 
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d5fa5b8..334a7e1 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -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:
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses
  2013-12-06  8:45 [patch net-next 0/2] ipv6: allow temporary address management for user-created addresses Jiri Pirko
  2013-12-06  8:45 ` [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32 Jiri Pirko
@ 2013-12-06  8:45 ` Jiri Pirko
  2013-12-06 21:35   ` David Miller
  2013-12-07  3:36   ` Hannes Frederic Sowa
  2013-12-06  8:46 ` [patch iproute2 1/2] add support for extended ifa_flags Jiri Pirko
  2 siblings, 2 replies; 12+ messages in thread
From: Jiri Pirko @ 2013-12-06  8:45 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

Creating an address with this flag set will result in kernel taking care
of temporary addresses in the same way as if the address was created by
kernel itself (after RA receive). This allows userspace applications
implementing the autoconfiguration (NetworkManager for example) to
implement ipv6 addresses privacy.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Thomas Haller <thaller@redhat.com>
---
 include/uapi/linux/if_addr.h |   1 +
 net/ipv6/addrconf.c          | 171 +++++++++++++++++++++++++------------------
 2 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/include/uapi/linux/if_addr.h b/include/uapi/linux/if_addr.h
index 8ab0c2c..cfed10b 100644
--- a/include/uapi/linux/if_addr.h
+++ b/include/uapi/linux/if_addr.h
@@ -48,6 +48,7 @@ enum {
 #define IFA_F_DEPRECATED	0x20
 #define IFA_F_TENTATIVE		0x40
 #define IFA_F_PERMANENT		0x80
+#define IFA_F_MANAGETEMPADDR	0x100
 
 struct ifa_cacheinfo {
 	__u32	ifa_prefered;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 334a7e1..5087cc5 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1024,7 +1024,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
 	u32 addr_flags;
 	unsigned long now = jiffies;
 
-	write_lock(&idev->lock);
+	write_lock_bh(&idev->lock);
 	if (ift) {
 		spin_lock_bh(&ift->lock);
 		memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
@@ -1036,7 +1036,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
 retry:
 	in6_dev_hold(idev);
 	if (idev->cnf.use_tempaddr <= 0) {
-		write_unlock(&idev->lock);
+		write_unlock_bh(&idev->lock);
 		pr_info("%s: use_tempaddr is disabled\n", __func__);
 		in6_dev_put(idev);
 		ret = -1;
@@ -1046,7 +1046,7 @@ retry:
 	if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
 		idev->cnf.use_tempaddr = -1;	/*XXX*/
 		spin_unlock_bh(&ifp->lock);
-		write_unlock(&idev->lock);
+		write_unlock_bh(&idev->lock);
 		pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
 			__func__);
 		in6_dev_put(idev);
@@ -1072,7 +1072,7 @@ retry:
 	regen_advance = idev->cnf.regen_max_retry *
 	                idev->cnf.dad_transmits *
 	                idev->nd_parms->retrans_time / HZ;
-	write_unlock(&idev->lock);
+	write_unlock_bh(&idev->lock);
 
 	/* A temporary address is created only if this calculated Preferred
 	 * Lifetime is greater than REGEN_ADVANCE time units.  In particular,
@@ -1099,7 +1099,7 @@ retry:
 		in6_dev_put(idev);
 		pr_info("%s: retry temporary address regeneration\n", __func__);
 		tmpaddr = &addr;
-		write_lock(&idev->lock);
+		write_lock_bh(&idev->lock);
 		goto retry;
 	}
 
@@ -2016,6 +2016,73 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
 	return idev;
 }
 
+static void manage_tempaddrs(struct inet6_dev *idev,
+			     struct inet6_ifaddr *ifp,
+			     __u32 valid_lft, __u32 prefered_lft,
+			     bool create, unsigned long now)
+{
+	u32 flags;
+	struct inet6_ifaddr *ift;
+
+	read_lock_bh(&idev->lock);
+	/* update all temporary addresses in the list */
+	list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
+		int age, max_valid, max_prefered;
+
+		if (ifp != ift->ifpub)
+			continue;
+
+		/* RFC 4941 section 3.3:
+		 * If a received option will extend the lifetime of a public
+		 * address, the lifetimes of temporary addresses should
+		 * be extended, subject to the overall constraint that no
+		 * temporary addresses should ever remain "valid" or "preferred"
+		 * for a time longer than (TEMP_VALID_LIFETIME) or
+		 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
+		 */
+		age = (now - ift->cstamp) / HZ;
+		max_valid = idev->cnf.temp_valid_lft - age;
+		if (max_valid < 0)
+			max_valid = 0;
+
+		max_prefered = idev->cnf.temp_prefered_lft -
+			       idev->cnf.max_desync_factor - age;
+		if (max_prefered < 0)
+			max_prefered = 0;
+
+		if (valid_lft > max_valid)
+			valid_lft = max_valid;
+
+		if (prefered_lft > max_prefered)
+			prefered_lft = max_prefered;
+
+		spin_lock(&ift->lock);
+		flags = ift->flags;
+		ift->valid_lft = valid_lft;
+		ift->prefered_lft = prefered_lft;
+		ift->tstamp = now;
+		if (prefered_lft > 0)
+			ift->flags &= ~IFA_F_DEPRECATED;
+
+		spin_unlock(&ift->lock);
+		if (!(flags&IFA_F_TENTATIVE))
+			ipv6_ifa_notify(0, ift);
+	}
+
+	if ((create || list_empty(&idev->tempaddr_list)) &&
+	    idev->cnf.use_tempaddr > 0) {
+		/* When a new public address is created as described
+		 * in [ADDRCONF], also create a new temporary address.
+		 * Also create a temporary address if it's enabled but
+		 * no temporary address currently exists.
+		 */
+		read_unlock_bh(&idev->lock);
+		ipv6_create_tempaddr(ifp, NULL);
+	} else {
+		read_unlock_bh(&idev->lock);
+	}
+}
+
 void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 {
 	struct prefix_info *pinfo;
@@ -2170,6 +2237,7 @@ ok:
 				return;
 			}
 
+			ifp->flags |= IFA_F_MANAGETEMPADDR;
 			update_lft = 0;
 			create = 1;
 			ifp->cstamp = jiffies;
@@ -2180,7 +2248,6 @@ ok:
 		if (ifp) {
 			u32 flags;
 			unsigned long now;
-			struct inet6_ifaddr *ift;
 			u32 stored_lft;
 
 			/* update lifetime (RFC2462 5.5.3 e) */
@@ -2221,70 +2288,8 @@ ok:
 			} else
 				spin_unlock(&ifp->lock);
 
-			read_lock_bh(&in6_dev->lock);
-			/* update all temporary addresses in the list */
-			list_for_each_entry(ift, &in6_dev->tempaddr_list,
-					    tmp_list) {
-				int age, max_valid, max_prefered;
-
-				if (ifp != ift->ifpub)
-					continue;
-
-				/*
-				 * RFC 4941 section 3.3:
-				 * If a received option will extend the lifetime
-				 * of a public address, the lifetimes of
-				 * temporary addresses should be extended,
-				 * subject to the overall constraint that no
-				 * temporary addresses should ever remain
-				 * "valid" or "preferred" for a time longer than
-				 * (TEMP_VALID_LIFETIME) or
-				 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR),
-				 * respectively.
-				 */
-				age = (now - ift->cstamp) / HZ;
-				max_valid = in6_dev->cnf.temp_valid_lft - age;
-				if (max_valid < 0)
-					max_valid = 0;
-
-				max_prefered = in6_dev->cnf.temp_prefered_lft -
-					       in6_dev->cnf.max_desync_factor -
-					       age;
-				if (max_prefered < 0)
-					max_prefered = 0;
-
-				if (valid_lft > max_valid)
-					valid_lft = max_valid;
-
-				if (prefered_lft > max_prefered)
-					prefered_lft = max_prefered;
-
-				spin_lock(&ift->lock);
-				flags = ift->flags;
-				ift->valid_lft = valid_lft;
-				ift->prefered_lft = prefered_lft;
-				ift->tstamp = now;
-				if (prefered_lft > 0)
-					ift->flags &= ~IFA_F_DEPRECATED;
-
-				spin_unlock(&ift->lock);
-				if (!(flags&IFA_F_TENTATIVE))
-					ipv6_ifa_notify(0, ift);
-			}
-
-			if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
-				/*
-				 * When a new public address is created as
-				 * described in [ADDRCONF], also create a new
-				 * temporary address. Also create a temporary
-				 * address if it's enabled but no temporary
-				 * address currently exists.
-				 */
-				read_unlock_bh(&in6_dev->lock);
-				ipv6_create_tempaddr(ifp, NULL);
-			} else {
-				read_unlock_bh(&in6_dev->lock);
-			}
+			manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
+					 create, now);
 
 			in6_ifa_put(ifp);
 			addrconf_verify(0);
@@ -2386,6 +2391,9 @@ static int inet6_addr_add(struct net *net, int ifindex,
 	if (!valid_lft || prefered_lft > valid_lft)
 		return -EINVAL;
 
+	if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
+		return -EINVAL;
+
 	dev = __dev_get_by_index(net, ifindex);
 	if (!dev)
 		return -ENODEV;
@@ -2426,6 +2434,9 @@ static int inet6_addr_add(struct net *net, int ifindex,
 		 * manually configured addresses
 		 */
 		addrconf_dad_start(ifp);
+		if (ifa_flags & IFA_F_MANAGETEMPADDR)
+			manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
+					 true, jiffies);
 		in6_ifa_put(ifp);
 		addrconf_verify(0);
 		return 0;
@@ -3603,10 +3614,15 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
 	u32 flags;
 	clock_t expires;
 	unsigned long timeout;
+	bool was_managetempaddr;
 
 	if (!valid_lft || (prefered_lft > valid_lft))
 		return -EINVAL;
 
+	if (ifa_flags & IFA_F_MANAGETEMPADDR &&
+	    (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
+		return -EINVAL;
+
 	timeout = addrconf_timeout_fixup(valid_lft, HZ);
 	if (addrconf_finite_timeout(timeout)) {
 		expires = jiffies_to_clock_t(timeout * HZ);
@@ -3626,7 +3642,10 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
 	}
 
 	spin_lock_bh(&ifp->lock);
-	ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags;
+	was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
+	ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
+			IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR);
+	ifp->flags |= ifa_flags;
 	ifp->tstamp = jiffies;
 	ifp->valid_lft = valid_lft;
 	ifp->prefered_lft = prefered_lft;
@@ -3637,6 +3656,14 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
 
 	addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
 			      expires, flags);
+
+	if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
+		if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
+			valid_lft = prefered_lft = 0;
+		manage_tempaddrs(ifp->idev, ifp, valid_lft, prefered_lft,
+				 !was_managetempaddr, jiffies);
+	}
+
 	addrconf_verify(0);
 
 	return 0;
@@ -3682,7 +3709,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
 	ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
 
 	/* We ignore other flags so far. */
-	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS;
+	ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR;
 
 	ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
 	if (ifa == NULL) {
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch iproute2 1/2] add support for extended ifa_flags
  2013-12-06  8:45 [patch net-next 0/2] ipv6: allow temporary address management for user-created addresses Jiri Pirko
  2013-12-06  8:45 ` [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32 Jiri Pirko
  2013-12-06  8:45 ` [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses Jiri Pirko
@ 2013-12-06  8:46 ` Jiri Pirko
  2013-12-06  8:46   ` [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR Jiri Pirko
  2013-12-28 19:21   ` [patch iproute2 1/2] add support for extended ifa_flags Stephen Hemminger
  2 siblings, 2 replies; 12+ messages in thread
From: Jiri Pirko @ 2013-12-06  8:46 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/if_addr.h |  1 +
 ip/ipaddress.c          | 44 ++++++++++++++++++++++++++++++--------------
 2 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index 58b39f4..cced59f 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -28,6 +28,7 @@ enum {
 	IFA_ANYCAST,
 	IFA_CACHEINFO,
 	IFA_MULTICAST,
+	IFA_FLAGS,
 	__IFA_MAX,
 };
 
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index d02eaaf..e012f8e 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -541,6 +541,13 @@ static int set_lifetime(unsigned int *lifetime, char *argv)
 	return 0;
 }
 
+static unsigned int get_ifa_flags(struct ifaddrmsg *ifa,
+				  struct rtattr *ifa_flags_attr)
+{
+	return ifa_flags_attr ? rta_getattr_u32(ifa_flags_attr) :
+				ifa->ifa_flags;
+}
+
 int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 		   void *arg)
 {
@@ -567,6 +574,8 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 
 	parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa), n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
 
+	ifa_flags = get_ifa_flags(ifa, rta_tb[IFA_FLAGS]);
+
 	if (!rta_tb[IFA_LOCAL])
 		rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
 	if (!rta_tb[IFA_ADDRESS])
@@ -576,7 +585,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 		return 0;
 	if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
 		return 0;
-	if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+	if ((filter.flags ^ ifa_flags) & filter.flagmask)
 		return 0;
 	if (filter.label) {
 		SPRINT_BUF(b1);
@@ -670,36 +679,35 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 				    abuf, sizeof(abuf)));
 	}
 	fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
-	ifa_flags = ifa->ifa_flags;
-	if (ifa->ifa_flags&IFA_F_SECONDARY) {
+	if (ifa_flags & IFA_F_SECONDARY) {
 		ifa_flags &= ~IFA_F_SECONDARY;
 		if (ifa->ifa_family == AF_INET6)
 			fprintf(fp, "temporary ");
 		else
 			fprintf(fp, "secondary ");
 	}
-	if (ifa->ifa_flags&IFA_F_TENTATIVE) {
+	if (ifa_flags & IFA_F_TENTATIVE) {
 		ifa_flags &= ~IFA_F_TENTATIVE;
 		fprintf(fp, "tentative ");
 	}
-	if (ifa->ifa_flags&IFA_F_DEPRECATED) {
+	if (ifa_flags & IFA_F_DEPRECATED) {
 		ifa_flags &= ~IFA_F_DEPRECATED;
 		deprecated = 1;
 		fprintf(fp, "deprecated ");
 	}
-	if (ifa->ifa_flags&IFA_F_HOMEADDRESS) {
+	if (ifa_flags & IFA_F_HOMEADDRESS) {
 		ifa_flags &= ~IFA_F_HOMEADDRESS;
 		fprintf(fp, "home ");
 	}
-	if (ifa->ifa_flags&IFA_F_NODAD) {
+	if (ifa_flags & IFA_F_NODAD) {
 		ifa_flags &= ~IFA_F_NODAD;
 		fprintf(fp, "nodad ");
 	}
-	if (!(ifa->ifa_flags&IFA_F_PERMANENT)) {
+	if (!(ifa_flags & IFA_F_PERMANENT)) {
 		fprintf(fp, "dynamic ");
 	} else
 		ifa_flags &= ~IFA_F_PERMANENT;
-	if (ifa->ifa_flags&IFA_F_DADFAILED) {
+	if (ifa_flags & IFA_F_DADFAILED) {
 		ifa_flags &= ~IFA_F_DADFAILED;
 		fprintf(fp, "dadfailed ");
 	}
@@ -926,6 +934,8 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
 		for (a = ainfo->head; a; a = a->next) {
 			struct nlmsghdr *n = &a->h;
 			struct ifaddrmsg *ifa = NLMSG_DATA(n);
+			struct rtattr *tb[IFA_MAX + 1];
+			unsigned int ifa_flags;
 
 			if (ifa->ifa_index != ifi->ifi_index)
 				continue;
@@ -934,11 +944,13 @@ static void ipaddr_filter(struct nlmsg_chain *linfo, struct nlmsg_chain *ainfo)
 				continue;
 			if ((filter.scope^ifa->ifa_scope)&filter.scopemask)
 				continue;
-			if ((filter.flags^ifa->ifa_flags)&filter.flagmask)
+
+			parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
+			ifa_flags = get_ifa_flags(ifa, tb[IFA_FLAGS]);
+
+			if ((filter.flags ^ ifa_flags) & filter.flagmask)
 				continue;
 			if (filter.pfx.family || filter.label) {
-				struct rtattr *tb[IFA_MAX+1];
-				parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(n));
 				if (!tb[IFA_LOCAL])
 					tb[IFA_LOCAL] = tb[IFA_ADDRESS];
 
@@ -1252,6 +1264,7 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 	__u32 preferred_lft = INFINITY_LIFE_TIME;
 	__u32 valid_lft = INFINITY_LIFE_TIME;
 	struct ifa_cacheinfo cinfo;
+	unsigned int ifa_flags = 0;
 
 	memset(&req, 0, sizeof(req));
 
@@ -1329,9 +1342,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 			if (set_lifetime(&preferred_lft, *argv))
 				invarg("preferred_lft value", *argv);
 		} else if (strcmp(*argv, "home") == 0) {
-			req.ifa.ifa_flags |= IFA_F_HOMEADDRESS;
+			ifa_flags |= IFA_F_HOMEADDRESS;
 		} else if (strcmp(*argv, "nodad") == 0) {
-			req.ifa.ifa_flags |= IFA_F_NODAD;
+			ifa_flags |= IFA_F_NODAD;
 		} else {
 			if (strcmp(*argv, "local") == 0) {
 				NEXT_ARG();
@@ -1349,6 +1362,9 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 		}
 		argc--; argv++;
 	}
+	req.ifa.ifa_flags = ifa_flags & 0xff;
+	addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags);
+
 	if (d == NULL) {
 		fprintf(stderr, "Not enough information: \"dev\" argument is required.\n");
 		return -1;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR
  2013-12-06  8:46 ` [patch iproute2 1/2] add support for extended ifa_flags Jiri Pirko
@ 2013-12-06  8:46   ` Jiri Pirko
  2013-12-28 19:27     ` Stephen Hemminger
  2013-12-28 19:21   ` [patch iproute2 1/2] add support for extended ifa_flags Stephen Hemminger
  1 sibling, 1 reply; 12+ messages in thread
From: Jiri Pirko @ 2013-12-06  8:46 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/if_addr.h | 1 +
 ip/ipaddress.c          | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index cced59f..e1e95ce 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -45,6 +45,7 @@ enum {
 #define IFA_F_DEPRECATED	0x20
 #define IFA_F_TENTATIVE		0x40
 #define IFA_F_PERMANENT		0x80
+#define IFA_F_MANAGETEMPADDR	0x0100
 
 struct ifa_cacheinfo {
 	__u32	ifa_prefered;
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index e012f8e..a4a19cc 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -703,6 +703,10 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
 		ifa_flags &= ~IFA_F_NODAD;
 		fprintf(fp, "nodad ");
 	}
+	if (ifa_flags & IFA_F_MANAGETEMPADDR) {
+		ifa_flags &= ~IFA_F_MANAGETEMPADDR;
+		fprintf(fp, "mngtmpaddr ");
+	}
 	if (!(ifa_flags & IFA_F_PERMANENT)) {
 		fprintf(fp, "dynamic ");
 	} else
@@ -1345,6 +1349,8 @@ static int ipaddr_modify(int cmd, int flags, int argc, char **argv)
 			ifa_flags |= IFA_F_HOMEADDRESS;
 		} else if (strcmp(*argv, "nodad") == 0) {
 			ifa_flags |= IFA_F_NODAD;
+		} else if (strcmp(*argv, "mngtmpaddr") == 0) {
+			ifa_flags |= IFA_F_MANAGETEMPADDR;
 		} else {
 			if (strcmp(*argv, "local") == 0) {
 				NEXT_ARG();
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32
  2013-12-06  8:45 ` [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32 Jiri Pirko
@ 2013-12-06 21:35   ` David Miller
  2013-12-07  8:51     ` Jiri Pirko
  0 siblings, 1 reply; 12+ messages in thread
From: David Miller @ 2013-12-06 21:35 UTC (permalink / raw)
  To: jiri
  Cc: netdev, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

From: Jiri Pirko <jiri@resnulli.us>
Date: Fri,  6 Dec 2013 09:45:21 +0100

> 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: Jiri Pirko <jiri@resnulli.us>
> Signed-off-by: Thomas Haller <thaller@redhat.com>

Applied, can you extend the handling of this attribute to the other
protocols as I asked you to?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses
  2013-12-06  8:45 ` [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses Jiri Pirko
@ 2013-12-06 21:35   ` David Miller
  2013-12-07  3:36   ` Hannes Frederic Sowa
  1 sibling, 0 replies; 12+ messages in thread
From: David Miller @ 2013-12-06 21:35 UTC (permalink / raw)
  To: jiri
  Cc: netdev, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

From: Jiri Pirko <jiri@resnulli.us>
Date: Fri,  6 Dec 2013 09:45:22 +0100

> Creating an address with this flag set will result in kernel taking care
> of temporary addresses in the same way as if the address was created by
> kernel itself (after RA receive). This allows userspace applications
> implementing the autoconfiguration (NetworkManager for example) to
> implement ipv6 addresses privacy.
> 
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
> Signed-off-by: Thomas Haller <thaller@redhat.com>

Applied.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses
  2013-12-06  8:45 ` [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses Jiri Pirko
  2013-12-06 21:35   ` David Miller
@ 2013-12-07  3:36   ` Hannes Frederic Sowa
  1 sibling, 0 replies; 12+ messages in thread
From: Hannes Frederic Sowa @ 2013-12-07  3:36 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, thaller,
	stephen, vyasevich, dcbw, David.Laight, fx.lebail

Hi Jiri!

On Fri, Dec 06, 2013 at 09:45:22AM +0100, Jiri Pirko wrote:
> Creating an address with this flag set will result in kernel taking care
> of temporary addresses in the same way as if the address was created by
> kernel itself (after RA receive). This allows userspace applications
> implementing the autoconfiguration (NetworkManager for example) to
> implement ipv6 addresses privacy.

I think we should follow up on something François-Xavier Le Bail proposed
here:

http://patchwork.ozlabs.org/patch/294029/

In general I like the idea, and I also agree with David, we should disable
it by default. But this would be beneficial to NetworkManager to not need
to set temp_addresses to 2 to have them used by default. I guess a netlink
api and a per-interface flag would be the easiest thing for NM to handle?

Greetings,

  Hannes

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32
  2013-12-06 21:35   ` David Miller
@ 2013-12-07  8:51     ` Jiri Pirko
  0 siblings, 0 replies; 12+ messages in thread
From: Jiri Pirko @ 2013-12-07  8:51 UTC (permalink / raw)
  To: David Miller
  Cc: netdev, kuznet, jmorris, yoshfuji, kaber, thaller, stephen,
	hannes, vyasevich, dcbw, David.Laight

Fri, Dec 06, 2013 at 10:35:18PM CET, davem@davemloft.net wrote:
>From: Jiri Pirko <jiri@resnulli.us>
>Date: Fri,  6 Dec 2013 09:45:21 +0100
>
>> 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: Jiri Pirko <jiri@resnulli.us>
>> Signed-off-by: Thomas Haller <thaller@redhat.com>
>
>Applied, can you extend the handling of this attribute to the other
>protocols as I asked you to?


Will send follow-up. Thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch iproute2 1/2] add support for extended ifa_flags
  2013-12-06  8:46 ` [patch iproute2 1/2] add support for extended ifa_flags Jiri Pirko
  2013-12-06  8:46   ` [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR Jiri Pirko
@ 2013-12-28 19:21   ` Stephen Hemminger
  2013-12-28 21:20     ` Jiri Pirko
  1 sibling, 1 reply; 12+ messages in thread
From: Stephen Hemminger @ 2013-12-28 19:21 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, thaller, hannes,
	vyasevich, dcbw, David.Laight

Was about to apply this but found something while reviewing.

On Fri,  6 Dec 2013 09:46:26 +0100
Jiri Pirko <jiri@resnulli.us> wrote:

> +	req.ifa.ifa_flags = ifa_flags & 0xff;
> +	addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags);

I don't like the mystery mask (0xff) here. I think this was to mask
off private flags. Perhaps a manifest constant should be added to if.h
lie IFA_F_RDONLY_MASK??

Plus from an API point of view, hard coding a value (even in #define)
seems like a problem when future values get added.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR
  2013-12-06  8:46   ` [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR Jiri Pirko
@ 2013-12-28 19:27     ` Stephen Hemminger
  0 siblings, 0 replies; 12+ messages in thread
From: Stephen Hemminger @ 2013-12-28 19:27 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, thaller, hannes,
	vyasevich, dcbw, David.Laight

On Fri,  6 Dec 2013 09:46:27 +0100
Jiri Pirko <jiri@resnulli.us> wrote:

> Signed-off-by: Jiri Pirko <jiri@resnulli.us>

This is ok, but since patch depends on previous one can't apply.
Please resubmit when first patch is fixed.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch iproute2 1/2] add support for extended ifa_flags
  2013-12-28 19:21   ` [patch iproute2 1/2] add support for extended ifa_flags Stephen Hemminger
@ 2013-12-28 21:20     ` Jiri Pirko
  0 siblings, 0 replies; 12+ messages in thread
From: Jiri Pirko @ 2013-12-28 21:20 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, thaller, hannes,
	vyasevich, dcbw, David.Laight

Sat, Dec 28, 2013 at 08:21:47PM CET, stephen@networkplumber.org wrote:
>Was about to apply this but found something while reviewing.
>
>On Fri,  6 Dec 2013 09:46:26 +0100
>Jiri Pirko <jiri@resnulli.us> wrote:
>
>> +	req.ifa.ifa_flags = ifa_flags & 0xff;
>> +	addattr32(&req.n, sizeof(req), IFA_FLAGS, ifa_flags);
>
>I don't like the mystery mask (0xff) here. I think this was to mask
>off private flags. Perhaps a manifest constant should be added to if.h
>lie IFA_F_RDONLY_MASK??

Hmm.. I wanted to emhasize that only 1 byte of value is taken.
But I think that simple "req.ifa.ifa_flags = ifa_flags" should be fine
here.

I will change this and repost.

Thanks!

>
>Plus from an API point of view, hard coding a value (even in #define)
>seems like a problem when future values get added.
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-12-28 21:20 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-06  8:45 [patch net-next 0/2] ipv6: allow temporary address management for user-created addresses Jiri Pirko
2013-12-06  8:45 ` [patch net-next 1/2] ipv6 addrconf: extend ifa_flags to u32 Jiri Pirko
2013-12-06 21:35   ` David Miller
2013-12-07  8:51     ` Jiri Pirko
2013-12-06  8:45 ` [patch net-next 2/2] ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses Jiri Pirko
2013-12-06 21:35   ` David Miller
2013-12-07  3:36   ` Hannes Frederic Sowa
2013-12-06  8:46 ` [patch iproute2 1/2] add support for extended ifa_flags Jiri Pirko
2013-12-06  8:46   ` [patch iproute2 2/2] add support for IFA_F_MANAGETEMPADDR Jiri Pirko
2013-12-28 19:27     ` Stephen Hemminger
2013-12-28 19:21   ` [patch iproute2 1/2] add support for extended ifa_flags Stephen Hemminger
2013-12-28 21:20     ` Jiri Pirko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).