struct nlmsghdr *nlh, gfp_t flags);
 extern void rtnl_set_sk_err(u32 group, int error);
 extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics);
+extern int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst,
+                             u32 id, u32 ts, u32 tsage, long expires,
+                             u32 error);
 
 extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
 
 
        return nla_nest_cancel(skb, mx);
 }
 
+int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
+                      u32 ts, u32 tsage, long expires, u32 error)
+{
+       struct rta_cacheinfo ci = {
+               .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse),
+               .rta_used = dst->__use,
+               .rta_clntref = atomic_read(&(dst->__refcnt)),
+               .rta_error = error,
+               .rta_id =  id,
+               .rta_ts = ts,
+               .rta_tsage = tsage,
+       };
+
+       if (expires)
+               ci.rta_expires = jiffies_to_clock_t(expires);
+
+       return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+}
+
+EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
 
 static void set_operstate(struct net_device *dev, unsigned char transition)
 {
 
        struct rtmsg *r;
        struct nlmsghdr *nlh;
        unsigned char *b = skb->tail;
-       struct rta_cacheinfo ci;
+       long expires;
 
        nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
        r = NLMSG_DATA(nlh);
                RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
        if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
                goto rtattr_failure;
-       ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
-       ci.rta_used     = rt->u.dst.__use;
-       ci.rta_clntref  = atomic_read(&rt->u.dst.__refcnt);
-       if (rt->u.dst.expires)
-               ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
-       else
-               ci.rta_expires = 0;
-       ci.rta_error    = rt->u.dst.error;
-       ci.rta_id       = ci.rta_ts = ci.rta_tsage = 0;
-       RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+       expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
+       if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, expires,
+                              rt->u.dst.error) < 0)
+               goto rtattr_failure;
        if (rt->fl.iif)
                RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);
 
 
        struct rtable *rt = (struct rtable*)skb->dst;
        struct rtmsg *r;
        struct nlmsghdr *nlh;
-       struct rta_cacheinfo ci;
+       long expires;
+       u32 id = 0, ts = 0, tsage = 0, error;
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
        if (nlh == NULL)
        if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
                goto nla_put_failure;
 
-       ci.rta_lastuse  = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
-       ci.rta_used     = rt->u.dst.__use;
-       ci.rta_clntref  = atomic_read(&rt->u.dst.__refcnt);
-       if (rt->u.dst.expires)
-               ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
-       else
-               ci.rta_expires = 0;
-       ci.rta_error    = rt->u.dst.error;
-       ci.rta_id       = ci.rta_ts = ci.rta_tsage = 0;
+       error = rt->u.dst.error;
+       expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
        if (rt->peer) {
-               ci.rta_id = rt->peer->ip_id_count;
+               id = rt->peer->ip_id_count;
                if (rt->peer->tcp_ts_stamp) {
-                       ci.rta_ts = rt->peer->tcp_ts;
-                       ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
+                       ts = rt->peer->tcp_ts;
+                       tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
                }
        }
 
                                } else {
                                        if (err == -EMSGSIZE)
                                                goto nla_put_failure;
-                                       ci.rta_error = err;
+                                       error = err;
                                }
                        }
                } else
                        NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
        }
 
-       NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+       if (rtnl_put_cacheinfo(skb, &rt->u.dst, id, ts, tsage,
+                              expires, error) < 0)
+               goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
 
 
 {
        struct rtmsg *rtm;
        struct nlmsghdr *nlh;
-       struct rta_cacheinfo ci;
+       long expires;
        u32 table;
 
        if (prefix) {   /* user wants prefix routes only */
                NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
 
        NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
-       ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
-       if (rt->rt6i_expires)
-               ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);
-       else
-               ci.rta_expires = 0;
-       ci.rta_used = rt->u.dst.__use;
-       ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
-       ci.rta_error = rt->u.dst.error;
-       ci.rta_id = 0;
-       ci.rta_ts = 0;
-       ci.rta_tsage = 0;
-       NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
+
+       expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0;
+       if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
+                              expires, rt->u.dst.error) < 0)
+               goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);