return ip6_route_add(&cfg);
 }
 
-static inline size_t rt6_nlmsg_size(struct rt6_info *rt)
+static size_t rt6_nlmsg_size(struct rt6_info *rt)
 {
+       int nexthop_len = 0;
+
+       if (rt->rt6i_nsiblings) {
+               nexthop_len = nla_total_size(0)  /* RTA_MULTIPATH */
+                           + NLA_ALIGN(sizeof(struct rtnexthop))
+                           + nla_total_size(16) /* RTA_GATEWAY */
+                           + nla_total_size(4)  /* RTA_OIF */
+                           + lwtunnel_get_encap_size(rt->dst.lwtstate);
+
+               nexthop_len *= rt->rt6i_nsiblings;
+       }
+
        return NLMSG_ALIGN(sizeof(struct rtmsg))
               + nla_total_size(16) /* RTA_SRC */
               + nla_total_size(16) /* RTA_DST */
               + nla_total_size(sizeof(struct rta_cacheinfo))
               + nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
               + nla_total_size(1) /* RTA_PREF */
-              + lwtunnel_get_encap_size(rt->dst.lwtstate);
+              + lwtunnel_get_encap_size(rt->dst.lwtstate)
+              + nexthop_len;
+}
+
+static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
+                           unsigned int *flags)
+{
+       if (!netif_running(rt->dst.dev) || !netif_carrier_ok(rt->dst.dev)) {
+               *flags |= RTNH_F_LINKDOWN;
+               if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
+                       *flags |= RTNH_F_DEAD;
+       }
+
+       if (rt->rt6i_flags & RTF_GATEWAY) {
+               if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
+                       goto nla_put_failure;
+       }
+
+       if (rt->dst.dev &&
+           nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
+               goto nla_put_failure;
+
+       if (rt->dst.lwtstate &&
+           lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
+               goto nla_put_failure;
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
+static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
+{
+       struct rtnexthop *rtnh;
+       unsigned int flags = 0;
+
+       rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
+       if (!rtnh)
+               goto nla_put_failure;
+
+       rtnh->rtnh_hops = 0;
+       rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
+
+       if (rt6_nexthop_info(skb, rt, &flags) < 0)
+               goto nla_put_failure;
+
+       rtnh->rtnh_flags = flags;
+
+       /* length of rtnetlink header + attributes */
+       rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh;
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
 }
 
 static int rt6_fill_node(struct net *net,
        else
                rtm->rtm_type = RTN_UNICAST;
        rtm->rtm_flags = 0;
-       if (!netif_running(rt->dst.dev) || !netif_carrier_ok(rt->dst.dev)) {
-               rtm->rtm_flags |= RTNH_F_LINKDOWN;
-               if (rt->rt6i_idev->cnf.ignore_routes_with_linkdown)
-                       rtm->rtm_flags |= RTNH_F_DEAD;
-       }
        rtm->rtm_scope = RT_SCOPE_UNIVERSE;
        rtm->rtm_protocol = rt->rt6i_protocol;
        if (rt->rt6i_flags & RTF_DYNAMIC)
        if (rtnetlink_put_metrics(skb, metrics) < 0)
                goto nla_put_failure;
 
-       if (rt->rt6i_flags & RTF_GATEWAY) {
-               if (nla_put_in6_addr(skb, RTA_GATEWAY, &rt->rt6i_gateway) < 0)
-                       goto nla_put_failure;
-       }
-
-       if (rt->dst.dev &&
-           nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
-               goto nla_put_failure;
        if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric))
                goto nla_put_failure;
 
+       /* For multipath routes, walk the siblings list and add
+        * each as a nexthop within RTA_MULTIPATH.
+        */
+       if (rt->rt6i_nsiblings) {
+               struct rt6_info *sibling, *next_sibling;
+               struct nlattr *mp;
+
+               mp = nla_nest_start(skb, RTA_MULTIPATH);
+               if (!mp)
+                       goto nla_put_failure;
+
+               if (rt6_add_nexthop(skb, rt) < 0)
+                       goto nla_put_failure;
+
+               list_for_each_entry_safe(sibling, next_sibling,
+                                        &rt->rt6i_siblings, rt6i_siblings) {
+                       if (rt6_add_nexthop(skb, sibling) < 0)
+                               goto nla_put_failure;
+               }
+
+               nla_nest_end(skb, mp);
+       } else {
+               if (rt6_nexthop_info(skb, rt, &rtm->rtm_flags) < 0)
+                       goto nla_put_failure;
+       }
+
        expires = (rt->rt6i_flags & RTF_EXPIRES) ? rt->dst.expires - jiffies : 0;
 
        if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0)
        if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
                goto nla_put_failure;
 
-       if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
-               goto nla_put_failure;
 
        nlmsg_end(skb, nlh);
        return 0;