From: Lukasz Stelmach <stlman@poczta.fm>
To: LKML <linux-kernel@vger.kernel.org>
Cc: netdev@vger.kernel.org, davem@davemloft.net,
yoshfuji@linux-ipv6.org, ebiederm@xmission.com
Subject: Re: [PATCH] Temporary IPv6 address asignment (v.1.1)
Date: Mon, 04 May 2009 15:30:48 +0200 [thread overview]
Message-ID: <49FEEE08.1090503@poczta.fm> (raw)
In-Reply-To: <49FE107A.4020406@poczta.fm>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 7985 bytes --]
A fixed mechanism to create and recreate temporary addresses,
even for very short preferred lifetimes.
A new RFC-compliant DESYNC_FACTOR implemented as a sysctl
variable desync_factor which is assigned a random value
each time max_desync_factor is written to. Each interface
has its own desync_factor and max_desync_factor. Writes to
default/max_desync_factor influence only default values. Writes
to all/max_desync_factor influence "all" and default values but
not values of running interfaces.
The patch fixes issues described in bugs #13208 and #13221 at
http://bugzilla.kernel.org.
Signed-off-by: Åukasz Stelmach <stlman@poczta.fm>
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 476d946..678687d 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -146,6 +146,7 @@ struct ipv6_devconf {
__s32 temp_prefered_lft;
__s32 regen_max_retry;
__s32 max_desync_factor;
+ __s32 desync_factor;
#endif
__s32 max_addresses;
__s32 accept_ra_defrtr;
@@ -201,6 +202,7 @@ enum {
DEVCONF_MC_FORWARDING,
DEVCONF_DISABLE_IPV6,
DEVCONF_ACCEPT_DAD,
+ DEVCONF_DESYNC_FACTOR,
DEVCONF_MAX
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a8218bc..c883064 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -116,8 +116,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev)
static int __ipv6_regen_rndid(struct inet6_dev *idev);
static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
static void ipv6_regen_rndid(unsigned long data);
-
-static int desync_factor = MAX_DESYNC_FACTOR * HZ;
#endif
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
@@ -172,6 +170,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
.regen_max_retry = REGEN_MAX_RETRY,
.max_desync_factor = MAX_DESYNC_FACTOR,
+ .desync_factor = MAX_DESYNC_FACTOR / 2,
#endif
.max_addresses = IPV6_MAX_ADDRESSES,
.accept_ra_defrtr = 1,
@@ -206,6 +205,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.temp_prefered_lft = TEMP_PREFERRED_LIFETIME,
.regen_max_retry = REGEN_MAX_RETRY,
.max_desync_factor = MAX_DESYNC_FACTOR,
+ .desync_factor = MAX_DESYNC_FACTOR / 2,
#endif
.max_addresses = IPV6_MAX_ADDRESSES,
.accept_ra_defrtr = 1,
@@ -831,11 +831,13 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
}
#ifdef CONFIG_IPV6_PRIVACY
-static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *ift)
+static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp,
+ struct inet6_ifaddr *ift,
+ unsigned long now)
{
struct inet6_dev *idev = ifp->idev;
struct in6_addr addr, *tmpaddr;
- unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp;
+ unsigned long tmp_prefered_lft, tmp_valid_lft;
unsigned long regen_advance;
int tmp_plen;
int ret = 0;
@@ -890,11 +892,9 @@ retry:
idev->cnf.temp_valid_lft);
tmp_prefered_lft = min_t(__u32,
ifp->prefered_lft,
- idev->cnf.temp_prefered_lft - desync_factor / HZ);
+ idev->cnf.temp_prefered_lft - idev->cnf.desync_factor);
tmp_plen = ifp->prefix_len;
max_addresses = idev->cnf.max_addresses;
- tmp_cstamp = ifp->cstamp;
- tmp_tstamp = ifp->tstamp;
spin_unlock_bh(&ifp->lock);
regen_advance = idev->cnf.regen_max_retry *
@@ -938,8 +938,7 @@ retry:
ift->ifpub = ifp;
ift->valid_lft = tmp_valid_lft;
ift->prefered_lft = tmp_prefered_lft;
- ift->cstamp = tmp_cstamp;
- ift->tstamp = tmp_tstamp;
+ ift->cstamp = ift->tstamp = now;
spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift, 0);
@@ -1388,7 +1387,7 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
if (ifpub) {
in6_ifa_hold(ifpub);
spin_unlock_bh(&ifp->lock);
- ipv6_create_tempaddr(ifpub, ifp);
+ ipv6_create_tempaddr(ifpub, ifp, jiffies);
in6_ifa_put(ifpub);
} else {
spin_unlock_bh(&ifp->lock);
@@ -1624,7 +1623,8 @@ static void ipv6_regen_rndid(unsigned long data)
expires = jiffies +
idev->cnf.temp_prefered_lft * HZ -
- idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor;
+ idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time -
+ idev->cnf.desync_factor * HZ;
if (time_before(expires, jiffies)) {
printk(KERN_WARNING
"ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n",
@@ -1971,7 +1971,7 @@ ok:
* also create a new temporary address.
*/
read_unlock_bh(&in6_dev->lock);
- ipv6_create_tempaddr(ifp, NULL);
+ ipv6_create_tempaddr(ifp, NULL, jiffies);
} else {
read_unlock_bh(&in6_dev->lock);
}
@@ -2809,6 +2809,11 @@ static void addrconf_dad_timer(unsigned long data)
read_unlock_bh(&idev->lock);
addrconf_dad_completed(ifp);
+ /*
+ * Required to expire properly temporary addresses
+ * with preferred lifetimes < ADDR_CHECK_FREQUENCY
+ */
+ addrconf_verify(0);
goto out;
}
@@ -3121,7 +3126,7 @@ restart:
spin_lock(&ifpub->lock);
ifpub->regen_count = 0;
spin_unlock(&ifpub->lock);
- ipv6_create_tempaddr(ifpub, ifp);
+ ipv6_create_tempaddr(ifpub, ifp, now);
in6_ifa_put(ifpub);
in6_ifa_put(ifp);
goto restart;
@@ -3638,6 +3643,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_TEMP_PREFERED_LFT] = cnf->temp_prefered_lft;
array[DEVCONF_REGEN_MAX_RETRY] = cnf->regen_max_retry;
array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
+ array[DEVCONF_DESYNC_FACTOR] = cnf->desync_factor;
#endif
array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
@@ -3935,6 +3941,43 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
}
#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_IPV6_PRIVACY
+static int addrconf_sysctl_desync(ctl_table *ctl, int write,
+ struct file *filp, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+ if (write) {
+ __s32 df;
+ int *valp = ctl->data;
+ struct ipv6_devconf *all, *dflt;
+ struct inet6_dev *idev = ctl->extra1;
+ struct net *net = ctl->extra2;
+ all = net->ipv6.devconf_all;
+ dflt = net->ipv6.devconf_dflt;
+
+ get_random_bytes(&df, sizeof(df));
+ /* The global abs() casts to int. */;
+ df = ((df) < 0 ? -(df) : df) % (*valp)
+
+ /* XXX How about some locking? */
+ if(idev)
+ idev->cnf.desync_factor = df;
+ else if (valp == &dflt->max_desync_factor)
+ dflt->desync_factor = df;
+ else if (valp == &all->max_desync_factor) {
+ all->desync_factor = df;
+ dflt->max_desync_factor = all->max_desync_factor;
+ dflt->desync_factor = df;
+ }
+
+ }
+ return ret;
+}
+#endif
static
int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
@@ -4124,6 +4167,14 @@ static struct addrconf_sysctl_table
.data = &ipv6_devconf.max_desync_factor,
.maxlen = sizeof(int),
.mode = 0644,
+ .proc_handler = addrconf_sysctl_desync,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "desync_factor",
+ .data = &ipv6_devconf.desync_factor,
+ .maxlen = sizeof(int),
+ .mode = 0444,
.proc_handler = proc_dointvec,
},
#endif
@@ -4449,6 +4500,11 @@ int __init addrconf_init(void)
rtnl_unlock();
if (err)
goto errlo;
+#ifdef CONFIG_IPV6_PRIVACY
+ get_random_bytes(&ipv6_devconf.desync_factor, sizeof(ipv6_devconf.desync_factor));
+ ipv6_devconf.desync_factor = abs(ipv6_devconf.desync_factor) % ipv6_devconf.max_desync_factor;
+ ipv6_devconf_dflt.desync_factor = ipv6_devconf.desync_factor;
+#endif
register_netdevice_notifier(&ipv6_dev_notf);
--
ByÅo mi bardzo miÅo. Czwarta pospolita klÄska, [...]
>Åukasz< Już nie katolicka lecz zÅodziejska. (c)PP
----------------------------------------------------------------------
Dzwonki na komorkê!
Sprawdz >> http://link.interia.pl/f2152
[-- Attachment #2: stlman.vcf --]
[-- Type: text/x-vcard, Size: 177 bytes --]
begin:vcard
fn;quoted-printable:=C5=81ukasz Stelmach
n;quoted-printable:Stelmach;=C5=81ukasz
email;internet:stlman@poczta.fm
x-mozilla-html:FALSE
version:2.1
end:vcard
prev parent reply other threads:[~2009-05-04 13:31 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-03 21:45 [PATCH] Temporary IPv6 address asignment Lukasz Stelmach
2009-05-03 21:47 ` David Miller
2009-05-03 22:20 ` Lukasz Stelmach
2009-05-03 22:34 ` David Miller
2009-05-03 22:45 ` Lukasz Stelmach
2009-05-03 23:58 ` Eric W. Biederman
2009-05-04 0:21 ` David Miller
2009-05-04 10:57 ` YOSHIFUJI Hideaki / 吉藤英明
2009-05-04 13:30 ` Lukasz Stelmach [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=49FEEE08.1090503@poczta.fm \
--to=stlman@poczta.fm \
--cc=davem@davemloft.net \
--cc=ebiederm@xmission.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=yoshfuji@linux-ipv6.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.