diff options
-rw-r--r-- | net/ipv6/addrconf.c | 72 |
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 | ||
3003 | static 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 | ||