From patchwork Tue Jan 10 13:54:34 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Trudel-Lapierre X-Patchwork-Id: 135364 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id D8BE1B6EEE for ; Wed, 11 Jan 2012 19:02:52 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1Rkt8u-0000WZ-7l; Wed, 11 Jan 2012 08:02:44 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1RkcAB-00079O-7x for kernel-team@lists.ubuntu.com; Tue, 10 Jan 2012 13:54:55 +0000 Received: from business-89-133-214-90.business.broadband.hu ([89.133.214.90] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1RkcAB-00080x-3E; Tue, 10 Jan 2012 13:54:55 +0000 From: Mathieu Trudel-Lapierre To: kernel-team@lists.ubuntu.com Subject: [PATCH] ipv6: make the net.ipv6.conf.all.use_tempaddr sysctl propagate to interface settings Date: Tue, 10 Jan 2012 14:54:34 +0100 Message-Id: <1326203674-15445-1-git-send-email-mathieu.trudel-lapierre@canonical.com> X-Mailer: git-send-email 1.7.7.3 X-Mailman-Approved-At: Wed, 11 Jan 2012 08:02:42 +0000 Cc: Mathieu Trudel-Lapierre X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com The description for IPV6_PRIVACY mentions using .../all/use_tempaddr to enable IPv6 Privacy Extensions, and IP sysctl documentation mentions 'all' as setting all interface-specific settings. We make sure at least use_tempaddr actually works as documented. Signed-off-by: Mathieu Trudel-Lapierre --- net/ipv6/addrconf.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 79 insertions(+), 1 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cf88df8..a20ab55 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4340,6 +4340,84 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, return ret; } +#ifdef CONFIG_IPV6_PRIVACY +static void dev_tempaddr_change(struct inet6_dev *idev) +{ + if (!idev || !idev->dev) + return; + + if (!idev->cnf.disable_ipv6) { + /* If ipv6 is enabled, try to bring down and back up the + * interface to get new temporary addresses created + */ + addrconf_notify(NULL, NETDEV_DOWN, idev->dev); + addrconf_notify(NULL, NETDEV_UP, idev->dev); + } +} + +static void addrconf_tempaddr_change(struct net *net, __s32 newf) +{ + struct net_device *dev; + struct inet6_dev *idev; + + rcu_read_lock(); + for_each_netdev_rcu(net, dev) { + idev = __in6_dev_get(dev); + if (idev) { + int changed = (!idev->cnf.use_tempaddr) ^ (!newf); + idev->cnf.use_tempaddr = newf; + if (changed) + dev_tempaddr_change(idev); + } + } + rcu_read_unlock(); +} + +static int addrconf_use_tempaddr(struct ctl_table *table, int *p, int old) +{ + struct net *net; + + net = (struct net *)table->extra2; + + if (p == &net->ipv6.devconf_dflt->use_tempaddr) + return 0; + + if (!rtnl_trylock()) { + /* Restore the original values before restarting */ + *p = old; + return restart_syscall(); + } + + if (p == &net->ipv6.devconf_all->use_tempaddr) { + __s32 newf = net->ipv6.devconf_all->use_tempaddr; + net->ipv6.devconf_dflt->use_tempaddr = newf; + addrconf_tempaddr_change(net, newf); + } else if ((!*p) ^ (!old)) + dev_tempaddr_change((struct inet6_dev *)table->extra1); + + rtnl_unlock(); + return 0; +} + +static +int addrconf_sysctl_tempaddr(ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int *valp = ctl->data; + int val = *valp; + loff_t pos = *ppos; + int ret; + + ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + + if (write) + ret = addrconf_use_tempaddr(ctl, valp, val); + if (ret) + *ppos = pos; + return ret; +} +#endif + static struct addrconf_sysctl_table { struct ctl_table_header *sysctl_header; @@ -4431,7 +4509,7 @@ static struct addrconf_sysctl_table .data = &ipv6_devconf.use_tempaddr, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = addrconf_sysctl_tempaddr, }, { .procname = "temp_valid_lft",