aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c97
1 files changed, 44 insertions, 53 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b39ae99122d5..9f80518aacbd 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -440,7 +440,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
440 if (pref == ICMPV6_ROUTER_PREF_INVALID) 440 if (pref == ICMPV6_ROUTER_PREF_INVALID)
441 pref = ICMPV6_ROUTER_PREF_MEDIUM; 441 pref = ICMPV6_ROUTER_PREF_MEDIUM;
442 442
443 lifetime = htonl(rinfo->lifetime); 443 lifetime = ntohl(rinfo->lifetime);
444 if (lifetime == 0xffffffff) { 444 if (lifetime == 0xffffffff) {
445 /* infinity */ 445 /* infinity */
446 } else if (lifetime > 0x7fffffff/HZ) { 446 } else if (lifetime > 0x7fffffff/HZ) {
@@ -711,12 +711,10 @@ void ip6_route_input(struct sk_buff *skb)
711 .ip6_u = { 711 .ip6_u = {
712 .daddr = iph->daddr, 712 .daddr = iph->daddr,
713 .saddr = iph->saddr, 713 .saddr = iph->saddr,
714#ifdef CONFIG_IPV6_ROUTE_FWMARK 714 .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
715 .fwmark = skb->nfmark,
716#endif
717 .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK,
718 }, 715 },
719 }, 716 },
717 .mark = skb->mark,
720 .proto = iph->nexthdr, 718 .proto = iph->nexthdr,
721 }; 719 };
722 720
@@ -942,7 +940,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
942 fib6_force_start_gc(); 940 fib6_force_start_gc();
943 941
944out: 942out:
945 return (struct dst_entry *)rt; 943 return &rt->u.dst;
946} 944}
947 945
948int ndisc_dst_gc(int *more) 946int ndisc_dst_gc(int *more)
@@ -1225,7 +1223,7 @@ out:
1225 if (idev) 1223 if (idev)
1226 in6_dev_put(idev); 1224 in6_dev_put(idev);
1227 if (rt) 1225 if (rt)
1228 dst_free((struct dst_entry *) rt); 1226 dst_free(&rt->u.dst);
1229 return err; 1227 return err;
1230} 1228}
1231 1229
@@ -1751,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code)
1751{ 1749{
1752 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); 1750 int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
1753 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) 1751 if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
1754 IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); 1752 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS);
1755 1753
1756 IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); 1754 IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES);
1757 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); 1755 icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev);
1758 kfree_skb(skb); 1756 kfree_skb(skb);
1759 return 0; 1757 return 0;
@@ -1824,7 +1822,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
1824 rt->rt6i_flags |= RTF_LOCAL; 1822 rt->rt6i_flags |= RTF_LOCAL;
1825 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); 1823 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
1826 if (rt->rt6i_nexthop == NULL) { 1824 if (rt->rt6i_nexthop == NULL) {
1827 dst_free((struct dst_entry *) rt); 1825 dst_free(&rt->u.dst);
1828 return ERR_PTR(-ENOMEM); 1826 return ERR_PTR(-ENOMEM);
1829 } 1827 }
1830 1828
@@ -2008,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
2008 return ip6_route_add(&cfg); 2006 return ip6_route_add(&cfg);
2009} 2007}
2010 2008
2009static inline size_t rt6_nlmsg_size(void)
2010{
2011 return NLMSG_ALIGN(sizeof(struct rtmsg))
2012 + nla_total_size(16) /* RTA_SRC */
2013 + nla_total_size(16) /* RTA_DST */
2014 + nla_total_size(16) /* RTA_GATEWAY */
2015 + nla_total_size(16) /* RTA_PREFSRC */
2016 + nla_total_size(4) /* RTA_TABLE */
2017 + nla_total_size(4) /* RTA_IIF */
2018 + nla_total_size(4) /* RTA_OIF */
2019 + nla_total_size(4) /* RTA_PRIORITY */
2020 + nla_total_size(sizeof(struct rta_cacheinfo));
2021}
2022
2011static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, 2023static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
2012 struct in6_addr *dst, struct in6_addr *src, 2024 struct in6_addr *dst, struct in6_addr *src,
2013 int iif, int type, u32 pid, u32 seq, 2025 int iif, int type, u32 pid, u32 seq,
@@ -2015,7 +2027,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
2015{ 2027{
2016 struct rtmsg *rtm; 2028 struct rtmsg *rtm;
2017 struct nlmsghdr *nlh; 2029 struct nlmsghdr *nlh;
2018 struct rta_cacheinfo ci; 2030 long expires;
2019 u32 table; 2031 u32 table;
2020 2032
2021 if (prefix) { /* user wants prefix routes only */ 2033 if (prefix) { /* user wants prefix routes only */
@@ -2089,18 +2101,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
2089 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); 2101 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
2090 2102
2091 NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); 2103 NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
2092 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); 2104
2093 if (rt->rt6i_expires) 2105 expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0;
2094 ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); 2106 if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
2095 else 2107 expires, rt->u.dst.error) < 0)
2096 ci.rta_expires = 0; 2108 goto nla_put_failure;
2097 ci.rta_used = rt->u.dst.__use;
2098 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
2099 ci.rta_error = rt->u.dst.error;
2100 ci.rta_id = 0;
2101 ci.rta_ts = 0;
2102 ci.rta_tsage = 0;
2103 NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
2104 2109
2105 return nlmsg_end(skb, nlh); 2110 return nlmsg_end(skb, nlh);
2106 2111
@@ -2202,7 +2207,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2202 struct sk_buff *skb; 2207 struct sk_buff *skb;
2203 u32 pid = 0, seq = 0; 2208 u32 pid = 0, seq = 0;
2204 struct nlmsghdr *nlh = NULL; 2209 struct nlmsghdr *nlh = NULL;
2205 int payload = sizeof(struct rtmsg) + 256;
2206 int err = -ENOBUFS; 2210 int err = -ENOBUFS;
2207 2211
2208 if (info) { 2212 if (info) {
@@ -2212,15 +2216,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2212 seq = nlh->nlmsg_seq; 2216 seq = nlh->nlmsg_seq;
2213 } 2217 }
2214 2218
2215 skb = nlmsg_new(nlmsg_total_size(payload), gfp_any()); 2219 skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
2216 if (skb == NULL) 2220 if (skb == NULL)
2217 goto errout; 2221 goto errout;
2218 2222
2219 err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); 2223 err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
2220 if (err < 0) { 2224 /* failure implies BUG in rt6_nlmsg_size() */
2221 kfree_skb(skb); 2225 BUG_ON(err < 0);
2222 goto errout;
2223 }
2224 2226
2225 err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); 2227 err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
2226errout: 2228errout:
@@ -2248,7 +2250,6 @@ struct rt6_proc_arg
2248static int rt6_info_route(struct rt6_info *rt, void *p_arg) 2250static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2249{ 2251{
2250 struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg; 2252 struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg;
2251 int i;
2252 2253
2253 if (arg->skip < arg->offset / RT6_INFO_LEN) { 2254 if (arg->skip < arg->offset / RT6_INFO_LEN) {
2254 arg->skip++; 2255 arg->skip++;
@@ -2258,38 +2259,28 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2258 if (arg->len >= arg->length) 2259 if (arg->len >= arg->length)
2259 return 0; 2260 return 0;
2260 2261
2261 for (i=0; i<16; i++) { 2262 arg->len += sprintf(arg->buffer + arg->len,
2262 sprintf(arg->buffer + arg->len, "%02x", 2263 NIP6_SEQFMT " %02x ",
2263 rt->rt6i_dst.addr.s6_addr[i]); 2264 NIP6(rt->rt6i_dst.addr),
2264 arg->len += 2;
2265 }
2266 arg->len += sprintf(arg->buffer + arg->len, " %02x ",
2267 rt->rt6i_dst.plen); 2265 rt->rt6i_dst.plen);
2268 2266
2269#ifdef CONFIG_IPV6_SUBTREES 2267#ifdef CONFIG_IPV6_SUBTREES
2270 for (i=0; i<16; i++) { 2268 arg->len += sprintf(arg->buffer + arg->len,
2271 sprintf(arg->buffer + arg->len, "%02x", 2269 NIP6_SEQFMT " %02x ",
2272 rt->rt6i_src.addr.s6_addr[i]); 2270 NIP6(rt->rt6i_src.addr),
2273 arg->len += 2;
2274 }
2275 arg->len += sprintf(arg->buffer + arg->len, " %02x ",
2276 rt->rt6i_src.plen); 2271 rt->rt6i_src.plen);
2277#else 2272#else
2278 sprintf(arg->buffer + arg->len, 2273 arg->len += sprintf(arg->buffer + arg->len,
2279 "00000000000000000000000000000000 00 "); 2274 "00000000000000000000000000000000 00 ");
2280 arg->len += 36;
2281#endif 2275#endif
2282 2276
2283 if (rt->rt6i_nexthop) { 2277 if (rt->rt6i_nexthop) {
2284 for (i=0; i<16; i++) { 2278 arg->len += sprintf(arg->buffer + arg->len,
2285 sprintf(arg->buffer + arg->len, "%02x", 2279 NIP6_SEQFMT,
2286 rt->rt6i_nexthop->primary_key[i]); 2280 NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key)));
2287 arg->len += 2;
2288 }
2289 } else { 2281 } else {
2290 sprintf(arg->buffer + arg->len, 2282 arg->len += sprintf(arg->buffer + arg->len,
2291 "00000000000000000000000000000000"); 2283 "00000000000000000000000000000000");
2292 arg->len += 32;
2293 } 2284 }
2294 arg->len += sprintf(arg->buffer + arg->len, 2285 arg->len += sprintf(arg->buffer + arg->len,
2295 " %08x %08x %08x %08x %8s\n", 2286 " %08x %08x %08x %08x %8s\n",