aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c72
1 files changed, 38 insertions, 34 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b2c38b3edb39..d546f0e74530 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3000,6 +3000,21 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
3000 preferred_lft, valid_lft); 3000 preferred_lft, valid_lft);
3001} 3001}
3002 3002
3003static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
3004 unsigned long tstamp, u32 preferred, u32 valid)
3005{
3006 struct ifa_cacheinfo ci;
3007
3008 ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
3009 + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3010 ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
3011 + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3012 ci.ifa_prefered = preferred;
3013 ci.ifa_valid = valid;
3014
3015 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3016}
3017
3003/* Maximum length of ifa_cacheinfo attributes */ 3018/* Maximum length of ifa_cacheinfo attributes */
3004#define INET6_IFADDR_RTA_SPACE \ 3019#define INET6_IFADDR_RTA_SPACE \
3005 RTA_SPACE(16) /* IFA_ADDRESS */ + \ 3020 RTA_SPACE(16) /* IFA_ADDRESS */ + \
@@ -3010,8 +3025,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3010{ 3025{
3011 struct ifaddrmsg *ifm; 3026 struct ifaddrmsg *ifm;
3012 struct nlmsghdr *nlh; 3027 struct nlmsghdr *nlh;
3013 struct ifa_cacheinfo ci;
3014 unsigned char *b = skb->tail; 3028 unsigned char *b = skb->tail;
3029 u32 preferred, valid;
3015 3030
3016 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); 3031 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
3017 ifm = NLMSG_DATA(nlh); 3032 ifm = NLMSG_DATA(nlh);
@@ -3028,23 +3043,22 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3028 ifm->ifa_index = ifa->idev->dev->ifindex; 3043 ifm->ifa_index = ifa->idev->dev->ifindex;
3029 RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr); 3044 RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr);
3030 if (!(ifa->flags&IFA_F_PERMANENT)) { 3045 if (!(ifa->flags&IFA_F_PERMANENT)) {
3031 ci.ifa_prefered = ifa->prefered_lft; 3046 preferred = ifa->prefered_lft;
3032 ci.ifa_valid = ifa->valid_lft; 3047 valid = ifa->valid_lft;
3033 if (ci.ifa_prefered != INFINITY_LIFE_TIME) { 3048 if (preferred != INFINITY_LIFE_TIME) {
3034 long tval = (jiffies - ifa->tstamp)/HZ; 3049 long tval = (jiffies - ifa->tstamp)/HZ;
3035 ci.ifa_prefered -= tval; 3050 preferred -= tval;
3036 if (ci.ifa_valid != INFINITY_LIFE_TIME) 3051 if (valid != INFINITY_LIFE_TIME)
3037 ci.ifa_valid -= tval; 3052 valid -= tval;
3038 } 3053 }
3039 } else { 3054 } else {
3040 ci.ifa_prefered = INFINITY_LIFE_TIME; 3055 preferred = INFINITY_LIFE_TIME;
3041 ci.ifa_valid = INFINITY_LIFE_TIME; 3056 valid = INFINITY_LIFE_TIME;
3042 } 3057 }
3043 ci.cstamp = (__u32)(TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) / HZ * 100 3058
3044 + TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); 3059 if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
3045 ci.tstamp = (__u32)(TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) / HZ * 100 3060 goto rtattr_failure;
3046 + TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); 3061
3047 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3048 nlh->nlmsg_len = skb->tail - b; 3062 nlh->nlmsg_len = skb->tail - b;
3049 return skb->len; 3063 return skb->len;
3050 3064
@@ -3059,7 +3073,6 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3059{ 3073{
3060 struct ifaddrmsg *ifm; 3074 struct ifaddrmsg *ifm;
3061 struct nlmsghdr *nlh; 3075 struct nlmsghdr *nlh;
3062 struct ifa_cacheinfo ci;
3063 unsigned char *b = skb->tail; 3076 unsigned char *b = skb->tail;
3064 3077
3065 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); 3078 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
@@ -3072,15 +3085,11 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
3072 ifm->ifa_scope = RT_SCOPE_SITE; 3085 ifm->ifa_scope = RT_SCOPE_SITE;
3073 ifm->ifa_index = ifmca->idev->dev->ifindex; 3086 ifm->ifa_index = ifmca->idev->dev->ifindex;
3074 RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr); 3087 RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr);
3075 ci.cstamp = (__u32)(TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) / HZ 3088
3076 * 100 + TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) % HZ 3089 if (put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
3077 * 100 / HZ); 3090 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
3078 ci.tstamp = (__u32)(TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) / HZ 3091 goto rtattr_failure;
3079 * 100 + TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) % HZ 3092
3080 * 100 / HZ);
3081 ci.ifa_prefered = INFINITY_LIFE_TIME;
3082 ci.ifa_valid = INFINITY_LIFE_TIME;
3083 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3084 nlh->nlmsg_len = skb->tail - b; 3093 nlh->nlmsg_len = skb->tail - b;
3085 return skb->len; 3094 return skb->len;
3086 3095
@@ -3095,7 +3104,6 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3095{ 3104{
3096 struct ifaddrmsg *ifm; 3105 struct ifaddrmsg *ifm;
3097 struct nlmsghdr *nlh; 3106 struct nlmsghdr *nlh;
3098 struct ifa_cacheinfo ci;
3099 unsigned char *b = skb->tail; 3107 unsigned char *b = skb->tail;
3100 3108
3101 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); 3109 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
@@ -3108,15 +3116,11 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
3108 ifm->ifa_scope = RT_SCOPE_SITE; 3116 ifm->ifa_scope = RT_SCOPE_SITE;
3109 ifm->ifa_index = ifaca->aca_idev->dev->ifindex; 3117 ifm->ifa_index = ifaca->aca_idev->dev->ifindex;
3110 RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr); 3118 RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr);
3111 ci.cstamp = (__u32)(TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) / HZ 3119
3112 * 100 + TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) % HZ 3120 if (put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
3113 * 100 / HZ); 3121 INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
3114 ci.tstamp = (__u32)(TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) / HZ 3122 goto rtattr_failure;
3115 * 100 + TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) % HZ 3123
3116 * 100 / HZ);
3117 ci.ifa_prefered = INFINITY_LIFE_TIME;
3118 ci.ifa_valid = INFINITY_LIFE_TIME;
3119 RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci);
3120 nlh->nlmsg_len = skb->tail - b; 3124 nlh->nlmsg_len = skb->tail - b;
3121 return skb->len; 3125 return skb->len;
3122 3126