* [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
@ 2006-07-27 9:57 YOSHIFUJI Hideaki / 吉藤英明
2006-07-27 10:28 ` Hugo Santos
0 siblings, 1 reply; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-07-27 9:57 UTC (permalink / raw)
To: davem; +Cc: yoshfuji, vnuorval, anttit, netdev, usagi-core
Hello.
Based on MIPL kernel patch, these changesets contain following:
- fix payload length checking
- fix infinity lifetime handling
- add/modify finity lifetime from userspace
This is only for review. Comments appreciated.
We will prepare another round.
(To Ville and Antti: please send me your "sign-off" if you like.)
Git tree is also available on addrconf-lifetime-20060727 branch at:
git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.18-rc2-addr-lifetime/linux-2.6.18-rc2-addr-lifetime
Thank you.
HEADLINES
---------
[IPV6] ADDRCONF: Check payload length for IFA_LOCAL attribute in RTM_{ADD,DEL}MSG message.
[IPV6] ADDRCONF: Allow user-space to specify address lifetime.
[IPV6] ADDRCONF: Do not verify an address with infinity lifetime.
[IPV6] ADDRCONF: Support get operation of single address.
[IPV6] ADDRCONF: NLM_F_REPLACE support for RTM_NEWADDR
DIFFSTAT
--------
net/ipv6/addrconf.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 166 insertions(+), 8 deletions(-)
CHANGESETS
----------
commit cb9e0e620c90ee486141bd737a93a20142d6dad1
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Mon Jul 3 13:58:39 2006 +0900
[IPV6] ADDRCONF: Check payload length for IFA_LOCAL attribute in RTM_{ADD,DEL}MSG message.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2316a43..81702b9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2853,7 +2853,8 @@ inet6_rtm_deladdr(struct sk_buff *skb, s
pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
}
if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+ (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
return -EINVAL;
pfx = RTA_DATA(rta[IFA_LOCAL-1]);
}
@@ -2877,7 +2878,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
}
if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+ (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
return -EINVAL;
pfx = RTA_DATA(rta[IFA_LOCAL-1]);
}
---
commit 78fee6e086390892e8b297b64700546491fdb871
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Mon Jul 3 14:02:28 2006 +0900
[IPV6] ADDRCONF: Allow user-space to specify address lifetime.
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 81702b9..c064188 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1869,15 +1869,21 @@ err_exit:
/*
* Manual configuration of address on an interface
*/
-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
+static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ __u32 prefered_lft, __u32 valid_lft)
{
struct inet6_ifaddr *ifp;
struct inet6_dev *idev;
struct net_device *dev;
+ __u8 ifa_flags = 0;
int scope;
ASSERT_RTNL();
+ /* check the lifetime */
+ if (!valid_lft || prefered_lft > valid_lft)
+ return -EINVAL;
+
if ((dev = __dev_get_by_index(ifindex)) == NULL)
return -ENODEV;
@@ -1889,10 +1895,29 @@ static int inet6_addr_add(int ifindex, s
scope = ipv6_addr_scope(pfx);
- ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT);
+ if (valid_lft == INFINITY_LIFE_TIME)
+ ifa_flags |= IFA_F_PERMANENT;
+ else if (valid_lft >= 0x7FFFFFFF/HZ)
+ valid_lft = 0x7FFFFFFF/HZ;
+
+ if (prefered_lft == 0)
+ ifa_flags |= IFA_F_DEPRECATED;
+ else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+ (prefered_lft != INFINITY_LIFE_TIME))
+ prefered_lft = 0x7FFFFFFF/HZ;
+
+ ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
+
if (!IS_ERR(ifp)) {
+ spin_lock(&ifp->lock);
+ ifp->valid_lft = valid_lft;
+ ifp->prefered_lft = prefered_lft;
+ ifp->tstamp = jiffies;
+ spin_unlock(&ifp->lock);
+
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
+ addrconf_verify(0);
return 0;
}
@@ -1945,7 +1970,8 @@ int addrconf_add_ifaddr(void __user *arg
return -EFAULT;
rtnl_lock();
- err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
+ err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
rtnl_unlock();
return err;
}
@@ -2870,6 +2896,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
struct rtattr **rta = arg;
struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
struct in6_addr *pfx;
+ __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME;
pfx = NULL;
if (rta[IFA_ADDRESS-1]) {
@@ -2886,7 +2913,18 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
if (pfx == NULL)
return -EINVAL;
- return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
+ if (rta[IFA_CACHEINFO-1]) {
+ struct ifa_cacheinfo *ci;
+ if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci))
+ return -EINVAL;
+ ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
+ valid_lft = ci->ifa_valid;
+ prefered_lft = ci->ifa_prefered;
+ }
+
+ return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
+ prefered_lft, valid_lft);
+
}
/* Maximum length of ifa_cacheinfo attributes */
---
commit d8be7c7b011b989fd134a10ca3bf27d78e209275
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Mon Jul 3 15:11:30 2006 +0900
[IPV6] ADDRCONF: Do not verify an address with infinity lifetime.
We also do not try regenarating new temporary address corresponding to an
address with infinite preferred lifetime.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c064188..93a40a8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2797,12 +2797,16 @@ #ifdef CONFIG_IPV6_PRIVACY
ifp->idev->nd_parms->retrans_time / HZ;
#endif
- if (age >= ifp->valid_lft) {
+ if (ifp->valid_lft != INFINITY_LIFE_TIME &&
+ age >= ifp->valid_lft) {
spin_unlock(&ifp->lock);
in6_ifa_hold(ifp);
read_unlock(&addrconf_hash_lock);
ipv6_del_addr(ifp);
goto restart;
+ } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
+ spin_unlock(&ifp->lock);
+ continue;
} else if (age >= ifp->prefered_lft) {
/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
int deprecate = 0;
---
commit 9cfa5093e1c50d192f1b9d0958a5110e2470f8ad
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Tue Jul 4 17:32:55 2006 +0900
[IPV6] ADDRCONF: Support get operation of single address.
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 93a40a8..3ef3fe2 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3165,6 +3165,62 @@ static int inet6_dump_ifacaddr(struct sk
return inet6_dump_addr(skb, cb, type);
}
+static int inet6_rtm_getaddr(struct sk_buff *in_skb,
+ struct nlmsghdr* nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct in6_addr *addr = NULL;
+ struct net_device *dev = NULL;
+ struct inet6_ifaddr *ifa;
+ struct sk_buff *skb;
+ int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
+ int err;
+
+ if (rta[IFA_ADDRESS-1]) {
+ if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr))
+ return -EINVAL;
+ addr = RTA_DATA(rta[IFA_ADDRESS-1]);
+ }
+ if (rta[IFA_LOCAL-1]) {
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) ||
+ (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr))))
+ return -EINVAL;
+ addr = RTA_DATA(rta[IFA_LOCAL-1]);
+ }
+ if (addr == NULL)
+ return -EINVAL;
+
+ if (ifm->ifa_index)
+ dev = __dev_get_by_index(ifm->ifa_index);
+
+ if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL)
+ return -EADDRNOTAVAIL;
+
+ if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) {
+ err = -ENOBUFS;
+ goto out;
+ }
+
+ NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+ err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
+ nlh->nlmsg_seq, RTM_NEWADDR, 0);
+ if (err < 0) {
+ err = -EMSGSIZE;
+ goto out_free;
+ }
+
+ err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
+ if (err > 0)
+ err = 0;
+out:
+ in6_ifa_put(ifa);
+ return err;
+out_free:
+ kfree_skb(skb);
+ goto out;
+}
+
static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
{
struct sk_buff *skb;
@@ -3407,7 +3463,8 @@ static struct rtnetlink_link inet6_rtnet
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
[RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, },
- [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, },
+ [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr,
+ .dumpit = inet6_dump_ifaddr, },
[RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, },
[RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, },
[RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, },
---
commit 21e1b516ba98ac9b369eaf1084a1b5a1927ad72a
Author: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Sun Jul 2 01:18:32 2006 +0900
[IPV6] ADDRCONF: NLM_F_REPLACE support for RTM_NEWADDR
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3ef3fe2..25032c2 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2895,6 +2895,55 @@ inet6_rtm_deladdr(struct sk_buff *skb, s
}
static int
+inet6_addr_modify(int ifindex, struct in6_addr *pfx,
+ __u32 prefered_lft, __u32 valid_lft)
+{
+ struct inet6_ifaddr *ifp = NULL;
+ struct net_device *dev;
+ int ifa_flags = 0;
+
+ if ((dev = __dev_get_by_index(ifindex)) == NULL)
+ return -ENODEV;
+
+ if (!(dev->flags&IFF_UP))
+ return -ENETDOWN;
+
+ ifp = ipv6_get_ifaddr(pfx, dev, 1);
+ if (ifp == NULL)
+ return -ENOENT;
+
+ if (!valid_lft || (prefered_lft > valid_lft))
+ return -EINVAL;
+
+ if (valid_lft == INFINITY_LIFE_TIME)
+ ifa_flags = IFA_F_PERMANENT;
+ else if (valid_lft >= 0x7FFFFFFF/HZ)
+ valid_lft = 0x7FFFFFFF/HZ;
+
+ if (prefered_lft == 0)
+ ifa_flags = IFA_F_DEPRECATED;
+ else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+ (prefered_lft != INFINITY_LIFE_TIME))
+ prefered_lft = 0x7FFFFFFF/HZ;
+
+ spin_lock_bh(&ifp->lock);
+ ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags;
+
+ ifp->tstamp = jiffies;
+ ifp->valid_lft = valid_lft;
+ ifp->prefered_lft = prefered_lft;
+
+ spin_unlock_bh(&ifp->lock);
+ if (!(ifp->flags&IFA_F_TENTATIVE))
+ ipv6_ifa_notify(0, ifp);
+ in6_ifa_put(ifp);
+
+ addrconf_verify(0);
+
+ return 0;
+}
+
+static int
inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct rtattr **rta = arg;
@@ -2926,6 +2975,14 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
prefered_lft = ci->ifa_prefered;
}
+ if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+ int ret;
+ ret = inet6_addr_modify(ifm->ifa_index, pfx,
+ prefered_lft, valid_lft);
+ if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
+ return ret;
+ }
+
return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
prefered_lft, valid_lft);
---
--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-27 9:57 [RFC] [IPV6] ADDRCONF: Lifetime handling fixes YOSHIFUJI Hideaki / 吉藤英明
@ 2006-07-27 10:28 ` Hugo Santos
2006-07-27 10:49 ` Noriaki TAKAMIYA
0 siblings, 1 reply; 7+ messages in thread
From: Hugo Santos @ 2006-07-27 10:28 UTC (permalink / raw)
To: YOSHIFUJI Hideaki / ?$B5HF#1QL@
Cc: davem, vnuorval, anttit, netdev, usagi-core
[-- Attachment #1: Type: text/plain, Size: 395 bytes --]
Hi,
> static int
> +inet6_addr_modify(int ifindex, struct in6_addr *pfx,
> + __u32 prefered_lft, __u32 valid_lft)
> +{
...
> + ifp = ipv6_get_ifaddr(pfx, dev, 1);
> + if (ifp == NULL)
> + return -ENOENT;
> +
> + if (!valid_lft || (prefered_lft > valid_lft))
> + return -EINVAL;
^^^^^^^^^^^^^^^
Unreleased ifp? This test should go before ipv6_get_ifaddr.
Hugo
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-27 10:28 ` Hugo Santos
@ 2006-07-27 10:49 ` Noriaki TAKAMIYA
2006-07-28 8:11 ` David Miller
0 siblings, 1 reply; 7+ messages in thread
From: Noriaki TAKAMIYA @ 2006-07-27 10:49 UTC (permalink / raw)
To: hsantos; +Cc: yoshfuji, davem, vnuorval, anttit, netdev, usagi-core
Hi,
This is Takamiya, from USAGI Project.
>> Thu, 27 Jul 2006 11:28:02 +0100
>> [Subject: Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes] wrote...
>> Hugo Santos <hsantos@av.it.pt> wrote...
> > + ifp = ipv6_get_ifaddr(pfx, dev, 1);
> > + if (ifp == NULL)
> > + return -ENOENT;
> > +
> > + if (!valid_lft || (prefered_lft > valid_lft))
> > + return -EINVAL;
> ^^^^^^^^^^^^^^^
>
> Unreleased ifp? This test should go before ipv6_get_ifaddr.
That's right. Thanks.
--
Noriaki Takamiya
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-27 10:49 ` Noriaki TAKAMIYA
@ 2006-07-28 8:11 ` David Miller
2006-07-28 8:18 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 1 reply; 7+ messages in thread
From: David Miller @ 2006-07-28 8:11 UTC (permalink / raw)
To: takamiya; +Cc: hsantos, yoshfuji, vnuorval, anttit, netdev, usagi-core
From: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Thu, 27 Jul 2006 19:49:29 +0900 (JST)
> >> Thu, 27 Jul 2006 11:28:02 +0100
> >> [Subject: Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes] wrote...
> >> Hugo Santos <hsantos@av.it.pt> wrote...
>
> > > + ifp = ipv6_get_ifaddr(pfx, dev, 1);
> > > + if (ifp == NULL)
> > > + return -ENOENT;
> > > +
> > > + if (!valid_lft || (prefered_lft > valid_lft))
> > > + return -EINVAL;
> > ^^^^^^^^^^^^^^^
> >
> > Unreleased ifp? This test should go before ipv6_get_ifaddr.
>
> That's right. Thanks.
Thank you Takamiya-san.
Besides this correction, the rest of the changes look fine to me.
I think we should get these fixes into 2.6.18, if you don't mind.
So please resubmit with the correction.
Thanks again.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-28 8:11 ` David Miller
@ 2006-07-28 8:18 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-28 9:25 ` YOSHIFUJI Hideaki / 吉藤英明
0 siblings, 1 reply; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-07-28 8:18 UTC (permalink / raw)
To: davem; +Cc: takamiya, hsantos, vnuorval, anttit, netdev, usagi-core, yoshfuji
In article <20060728.011103.21926965.davem@davemloft.net> (at Fri, 28 Jul 2006 01:11:03 -0700 (PDT)), David Miller <davem@davemloft.net> says:
> Besides this correction, the rest of the changes look fine to me.
> I think we should get these fixes into 2.6.18, if you don't mind.
>
> So please resubmit with the correction.
Okay. I'll do this soon.
--yoshfuji
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-28 8:18 ` YOSHIFUJI Hideaki / 吉藤英明
@ 2006-07-28 9:25 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-31 3:32 ` David Miller
0 siblings, 1 reply; 7+ messages in thread
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2006-07-28 9:25 UTC (permalink / raw)
To: davem; +Cc: takamiya, hsantos, vnuorval, anttit, netdev, usagi-core, yoshfuji
In article <20060728.171818.37443466.yoshfuji@linux-ipv6.org> (at Fri, 28 Jul 2006 17:18:18 +0900 (JST)), YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> says:
> In article <20060728.011103.21926965.davem@davemloft.net> (at Fri, 28 Jul 2006 01:11:03 -0700 (PDT)), David Miller <davem@davemloft.net> says:
>
> > Besides this correction, the rest of the changes look fine to me.
> > I think we should get these fixes into 2.6.18, if you don't mind.
> >
> > So please resubmit with the correction.
>
> Okay. I'll do this soon.
Here it is.
Changesets, on top of 2.6.18-rc2, are available on
branch "addr-lifetime-20060728b" at:
git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.18-rc2-addr-lifetime
Regards,
HEADLINES
---------
[IPV6] ADDRCONF: Check payload length for IFA_LOCAL attribute in RTM_{ADD,DEL}MSG message
[IPV6] ADDRCONF: Allow user-space to specify address lifetime
[IPV6] ADDRCONF: Do not verify an address with infinity lifetime
[IPV6] ADDRCONF: Support get operation of single address
[IPV6] ADDRCONF: NLM_F_REPLACE support for RTM_NEWADDR
DIFFSTAT
--------
net/ipv6/addrconf.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 166 insertions(+), 8 deletions(-)
CHANGESETS
----------
commit 27fb40230b30534bdc08736d64cab179038591bc
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Fri Jul 28 18:12:09 2006 +0900
[IPV6] ADDRCONF: Check payload length for IFA_LOCAL attribute in RTM_{ADD,DEL}MSG message
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2316a43..81702b9 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2853,7 +2853,8 @@ inet6_rtm_deladdr(struct sk_buff *skb, s
pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
}
if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+ (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
return -EINVAL;
pfx = RTA_DATA(rta[IFA_LOCAL-1]);
}
@@ -2877,7 +2878,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
}
if (rta[IFA_LOCAL-1]) {
- if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+ (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
return -EINVAL;
pfx = RTA_DATA(rta[IFA_LOCAL-1]);
}
---
commit 336f472519a05ea493c5ad24de2c39e2c80003a0
Author: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Fri Jul 28 18:12:10 2006 +0900
[IPV6] ADDRCONF: Allow user-space to specify address lifetime
Based on MIPL2 kernel patch.
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 81702b9..c064188 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1869,15 +1869,21 @@ err_exit:
/*
* Manual configuration of address on an interface
*/
-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
+static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+ __u32 prefered_lft, __u32 valid_lft)
{
struct inet6_ifaddr *ifp;
struct inet6_dev *idev;
struct net_device *dev;
+ __u8 ifa_flags = 0;
int scope;
ASSERT_RTNL();
+ /* check the lifetime */
+ if (!valid_lft || prefered_lft > valid_lft)
+ return -EINVAL;
+
if ((dev = __dev_get_by_index(ifindex)) == NULL)
return -ENODEV;
@@ -1889,10 +1895,29 @@ static int inet6_addr_add(int ifindex, s
scope = ipv6_addr_scope(pfx);
- ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT);
+ if (valid_lft == INFINITY_LIFE_TIME)
+ ifa_flags |= IFA_F_PERMANENT;
+ else if (valid_lft >= 0x7FFFFFFF/HZ)
+ valid_lft = 0x7FFFFFFF/HZ;
+
+ if (prefered_lft == 0)
+ ifa_flags |= IFA_F_DEPRECATED;
+ else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+ (prefered_lft != INFINITY_LIFE_TIME))
+ prefered_lft = 0x7FFFFFFF/HZ;
+
+ ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
+
if (!IS_ERR(ifp)) {
+ spin_lock(&ifp->lock);
+ ifp->valid_lft = valid_lft;
+ ifp->prefered_lft = prefered_lft;
+ ifp->tstamp = jiffies;
+ spin_unlock(&ifp->lock);
+
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
+ addrconf_verify(0);
return 0;
}
@@ -1945,7 +1970,8 @@ int addrconf_add_ifaddr(void __user *arg
return -EFAULT;
rtnl_lock();
- err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
+ err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
+ INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
rtnl_unlock();
return err;
}
@@ -2870,6 +2896,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
struct rtattr **rta = arg;
struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
struct in6_addr *pfx;
+ __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME;
pfx = NULL;
if (rta[IFA_ADDRESS-1]) {
@@ -2886,7 +2913,18 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
if (pfx == NULL)
return -EINVAL;
- return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
+ if (rta[IFA_CACHEINFO-1]) {
+ struct ifa_cacheinfo *ci;
+ if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci))
+ return -EINVAL;
+ ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
+ valid_lft = ci->ifa_valid;
+ prefered_lft = ci->ifa_prefered;
+ }
+
+ return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
+ prefered_lft, valid_lft);
+
}
/* Maximum length of ifa_cacheinfo attributes */
---
commit 28a22216f2d553020e2d15d3b1a9ab9306623e6b
Author: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Fri Jul 28 18:12:11 2006 +0900
[IPV6] ADDRCONF: Do not verify an address with infinity lifetime
We also do not try regenarating new temporary address corresponding to an
address with infinite preferred lifetime.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c064188..93a40a8 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2797,12 +2797,16 @@ #ifdef CONFIG_IPV6_PRIVACY
ifp->idev->nd_parms->retrans_time / HZ;
#endif
- if (age >= ifp->valid_lft) {
+ if (ifp->valid_lft != INFINITY_LIFE_TIME &&
+ age >= ifp->valid_lft) {
spin_unlock(&ifp->lock);
in6_ifa_hold(ifp);
read_unlock(&addrconf_hash_lock);
ipv6_del_addr(ifp);
goto restart;
+ } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
+ spin_unlock(&ifp->lock);
+ continue;
} else if (age >= ifp->prefered_lft) {
/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
int deprecate = 0;
---
commit eb682da0e66556e23c7c4da73e4808d0b7a29484
Author: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Fri Jul 28 18:12:12 2006 +0900
[IPV6] ADDRCONF: Support get operation of single address
Based on MIPL2 kernel patch.
Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 93a40a8..3ef3fe2 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3165,6 +3165,62 @@ static int inet6_dump_ifacaddr(struct sk
return inet6_dump_addr(skb, cb, type);
}
+static int inet6_rtm_getaddr(struct sk_buff *in_skb,
+ struct nlmsghdr* nlh, void *arg)
+{
+ struct rtattr **rta = arg;
+ struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct in6_addr *addr = NULL;
+ struct net_device *dev = NULL;
+ struct inet6_ifaddr *ifa;
+ struct sk_buff *skb;
+ int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
+ int err;
+
+ if (rta[IFA_ADDRESS-1]) {
+ if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr))
+ return -EINVAL;
+ addr = RTA_DATA(rta[IFA_ADDRESS-1]);
+ }
+ if (rta[IFA_LOCAL-1]) {
+ if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) ||
+ (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr))))
+ return -EINVAL;
+ addr = RTA_DATA(rta[IFA_LOCAL-1]);
+ }
+ if (addr == NULL)
+ return -EINVAL;
+
+ if (ifm->ifa_index)
+ dev = __dev_get_by_index(ifm->ifa_index);
+
+ if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL)
+ return -EADDRNOTAVAIL;
+
+ if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) {
+ err = -ENOBUFS;
+ goto out;
+ }
+
+ NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+ err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
+ nlh->nlmsg_seq, RTM_NEWADDR, 0);
+ if (err < 0) {
+ err = -EMSGSIZE;
+ goto out_free;
+ }
+
+ err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
+ if (err > 0)
+ err = 0;
+out:
+ in6_ifa_put(ifa);
+ return err;
+out_free:
+ kfree_skb(skb);
+ goto out;
+}
+
static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
{
struct sk_buff *skb;
@@ -3407,7 +3463,8 @@ static struct rtnetlink_link inet6_rtnet
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
[RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, },
- [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, },
+ [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr,
+ .dumpit = inet6_dump_ifaddr, },
[RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, },
[RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, },
[RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, },
---
commit 1a4b3b795b8d5d3b4a746b038b6ba4ddddf9d32c
Author: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Fri Jul 28 18:12:13 2006 +0900
[IPV6] ADDRCONF: NLM_F_REPLACE support for RTM_NEWADDR
Based on MIPL2 kernel patch.
Signed-off-by: Noriaki YAKAMIYA <takamiya@po.ntts.co.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3ef3fe2..8ea1e36 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2895,6 +2895,55 @@ inet6_rtm_deladdr(struct sk_buff *skb, s
}
static int
+inet6_addr_modify(int ifindex, struct in6_addr *pfx,
+ __u32 prefered_lft, __u32 valid_lft)
+{
+ struct inet6_ifaddr *ifp = NULL;
+ struct net_device *dev;
+ int ifa_flags = 0;
+
+ if ((dev = __dev_get_by_index(ifindex)) == NULL)
+ return -ENODEV;
+
+ if (!(dev->flags&IFF_UP))
+ return -ENETDOWN;
+
+ if (!valid_lft || (prefered_lft > valid_lft))
+ return -EINVAL;
+
+ ifp = ipv6_get_ifaddr(pfx, dev, 1);
+ if (ifp == NULL)
+ return -ENOENT;
+
+ if (valid_lft == INFINITY_LIFE_TIME)
+ ifa_flags = IFA_F_PERMANENT;
+ else if (valid_lft >= 0x7FFFFFFF/HZ)
+ valid_lft = 0x7FFFFFFF/HZ;
+
+ if (prefered_lft == 0)
+ ifa_flags = IFA_F_DEPRECATED;
+ else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+ (prefered_lft != INFINITY_LIFE_TIME))
+ prefered_lft = 0x7FFFFFFF/HZ;
+
+ spin_lock_bh(&ifp->lock);
+ ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags;
+
+ ifp->tstamp = jiffies;
+ ifp->valid_lft = valid_lft;
+ ifp->prefered_lft = prefered_lft;
+
+ spin_unlock_bh(&ifp->lock);
+ if (!(ifp->flags&IFA_F_TENTATIVE))
+ ipv6_ifa_notify(0, ifp);
+ in6_ifa_put(ifp);
+
+ addrconf_verify(0);
+
+ return 0;
+}
+
+static int
inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct rtattr **rta = arg;
@@ -2926,6 +2975,14 @@ inet6_rtm_newaddr(struct sk_buff *skb, s
prefered_lft = ci->ifa_prefered;
}
+ if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+ int ret;
+ ret = inet6_addr_modify(ifm->ifa_index, pfx,
+ prefered_lft, valid_lft);
+ if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
+ return ret;
+ }
+
return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
prefered_lft, valid_lft);
---
--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC] [IPV6] ADDRCONF: Lifetime handling fixes
2006-07-28 9:25 ` YOSHIFUJI Hideaki / 吉藤英明
@ 2006-07-31 3:32 ` David Miller
0 siblings, 0 replies; 7+ messages in thread
From: David Miller @ 2006-07-31 3:32 UTC (permalink / raw)
To: yoshfuji; +Cc: takamiya, hsantos, vnuorval, anttit, netdev, usagi-core
From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Fri, 28 Jul 2006 18:25:34 +0900 (JST)
> Changesets, on top of 2.6.18-rc2, are available on
> branch "addr-lifetime-20060728b" at:
> git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.18-rc2-addr-lifetime
Pulled, thank you very much.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2006-07-31 3:32 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-07-27 9:57 [RFC] [IPV6] ADDRCONF: Lifetime handling fixes YOSHIFUJI Hideaki / 吉藤英明
2006-07-27 10:28 ` Hugo Santos
2006-07-27 10:49 ` Noriaki TAKAMIYA
2006-07-28 8:11 ` David Miller
2006-07-28 8:18 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-28 9:25 ` YOSHIFUJI Hideaki / 吉藤英明
2006-07-31 3:32 ` David Miller
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).