diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1f5b226c3573..878789b3122d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -384,12 +384,13 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, | |||
384 | be destroyed. | 384 | be destroyed. |
385 | */ | 385 | */ |
386 | 386 | ||
387 | int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) | 387 | int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, |
388 | void *_rtattr, struct netlink_skb_parms *req) | ||
388 | { | 389 | { |
389 | int err; | 390 | int err; |
390 | 391 | ||
391 | write_lock_bh(&rt6_lock); | 392 | write_lock_bh(&rt6_lock); |
392 | err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr); | 393 | err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req); |
393 | write_unlock_bh(&rt6_lock); | 394 | write_unlock_bh(&rt6_lock); |
394 | 395 | ||
395 | return err; | 396 | return err; |
@@ -400,7 +401,7 @@ int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) | |||
400 | */ | 401 | */ |
401 | 402 | ||
402 | static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, | 403 | static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, |
403 | struct in6_addr *saddr) | 404 | struct in6_addr *saddr, struct netlink_skb_parms *req) |
404 | { | 405 | { |
405 | int err; | 406 | int err; |
406 | struct rt6_info *rt; | 407 | struct rt6_info *rt; |
@@ -432,7 +433,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, | |||
432 | 433 | ||
433 | dst_hold(&rt->u.dst); | 434 | dst_hold(&rt->u.dst); |
434 | 435 | ||
435 | err = ip6_ins_rt(rt, NULL, NULL); | 436 | err = ip6_ins_rt(rt, NULL, NULL, req); |
436 | if (err == 0) | 437 | if (err == 0) |
437 | return rt; | 438 | return rt; |
438 | 439 | ||
@@ -491,7 +492,8 @@ restart: | |||
491 | read_unlock_bh(&rt6_lock); | 492 | read_unlock_bh(&rt6_lock); |
492 | 493 | ||
493 | nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr, | 494 | nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr, |
494 | &skb->nh.ipv6h->saddr); | 495 | &skb->nh.ipv6h->saddr, |
496 | &NETLINK_CB(skb)); | ||
495 | 497 | ||
496 | dst_release(&rt->u.dst); | 498 | dst_release(&rt->u.dst); |
497 | rt = nrt; | 499 | rt = nrt; |
@@ -551,7 +553,7 @@ restart: | |||
551 | dst_hold(&rt->u.dst); | 553 | dst_hold(&rt->u.dst); |
552 | read_unlock_bh(&rt6_lock); | 554 | read_unlock_bh(&rt6_lock); |
553 | 555 | ||
554 | nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src); | 556 | nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL); |
555 | 557 | ||
556 | dst_release(&rt->u.dst); | 558 | dst_release(&rt->u.dst); |
557 | rt = nrt; | 559 | rt = nrt; |
@@ -598,7 +600,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) | |||
598 | 600 | ||
599 | if (rt) { | 601 | if (rt) { |
600 | if (rt->rt6i_flags & RTF_CACHE) | 602 | if (rt->rt6i_flags & RTF_CACHE) |
601 | ip6_del_rt(rt, NULL, NULL); | 603 | ip6_del_rt(rt, NULL, NULL, NULL); |
602 | else | 604 | else |
603 | dst_release(dst); | 605 | dst_release(dst); |
604 | } | 606 | } |
@@ -787,7 +789,8 @@ int ipv6_get_hoplimit(struct net_device *dev) | |||
787 | * | 789 | * |
788 | */ | 790 | */ |
789 | 791 | ||
790 | int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) | 792 | int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, |
793 | void *_rtattr, struct netlink_skb_parms *req) | ||
791 | { | 794 | { |
792 | int err; | 795 | int err; |
793 | struct rtmsg *r; | 796 | struct rtmsg *r; |
@@ -974,7 +977,7 @@ install_route: | |||
974 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); | 977 | rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); |
975 | rt->u.dst.dev = dev; | 978 | rt->u.dst.dev = dev; |
976 | rt->rt6i_idev = idev; | 979 | rt->rt6i_idev = idev; |
977 | return ip6_ins_rt(rt, nlh, _rtattr); | 980 | return ip6_ins_rt(rt, nlh, _rtattr, req); |
978 | 981 | ||
979 | out: | 982 | out: |
980 | if (dev) | 983 | if (dev) |
@@ -986,7 +989,7 @@ out: | |||
986 | return err; | 989 | return err; |
987 | } | 990 | } |
988 | 991 | ||
989 | int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) | 992 | int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) |
990 | { | 993 | { |
991 | int err; | 994 | int err; |
992 | 995 | ||
@@ -994,7 +997,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) | |||
994 | 997 | ||
995 | rt6_reset_dflt_pointer(NULL); | 998 | rt6_reset_dflt_pointer(NULL); |
996 | 999 | ||
997 | err = fib6_del(rt, nlh, _rtattr); | 1000 | err = fib6_del(rt, nlh, _rtattr, req); |
998 | dst_release(&rt->u.dst); | 1001 | dst_release(&rt->u.dst); |
999 | 1002 | ||
1000 | write_unlock_bh(&rt6_lock); | 1003 | write_unlock_bh(&rt6_lock); |
@@ -1002,7 +1005,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) | |||
1002 | return err; | 1005 | return err; |
1003 | } | 1006 | } |
1004 | 1007 | ||
1005 | static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) | 1008 | static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) |
1006 | { | 1009 | { |
1007 | struct fib6_node *fn; | 1010 | struct fib6_node *fn; |
1008 | struct rt6_info *rt; | 1011 | struct rt6_info *rt; |
@@ -1029,7 +1032,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r | |||
1029 | dst_hold(&rt->u.dst); | 1032 | dst_hold(&rt->u.dst); |
1030 | read_unlock_bh(&rt6_lock); | 1033 | read_unlock_bh(&rt6_lock); |
1031 | 1034 | ||
1032 | return ip6_del_rt(rt, nlh, _rtattr); | 1035 | return ip6_del_rt(rt, nlh, _rtattr, req); |
1033 | } | 1036 | } |
1034 | } | 1037 | } |
1035 | read_unlock_bh(&rt6_lock); | 1038 | read_unlock_bh(&rt6_lock); |
@@ -1136,11 +1139,11 @@ source_ok: | |||
1136 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1139 | nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); |
1137 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); | 1140 | nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); |
1138 | 1141 | ||
1139 | if (ip6_ins_rt(nrt, NULL, NULL)) | 1142 | if (ip6_ins_rt(nrt, NULL, NULL, NULL)) |
1140 | goto out; | 1143 | goto out; |
1141 | 1144 | ||
1142 | if (rt->rt6i_flags&RTF_CACHE) { | 1145 | if (rt->rt6i_flags&RTF_CACHE) { |
1143 | ip6_del_rt(rt, NULL, NULL); | 1146 | ip6_del_rt(rt, NULL, NULL, NULL); |
1144 | return; | 1147 | return; |
1145 | } | 1148 | } |
1146 | 1149 | ||
@@ -1204,7 +1207,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1204 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. | 1207 | 2. It is gatewayed route or NONEXTHOP route. Action: clone it. |
1205 | */ | 1208 | */ |
1206 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { | 1209 | if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { |
1207 | nrt = rt6_cow(rt, daddr, saddr); | 1210 | nrt = rt6_cow(rt, daddr, saddr, NULL); |
1208 | if (!nrt->u.dst.error) { | 1211 | if (!nrt->u.dst.error) { |
1209 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1212 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; |
1210 | if (allfrag) | 1213 | if (allfrag) |
@@ -1232,7 +1235,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1232 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; | 1235 | nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; |
1233 | if (allfrag) | 1236 | if (allfrag) |
1234 | nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1237 | nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; |
1235 | ip6_ins_rt(nrt, NULL, NULL); | 1238 | ip6_ins_rt(nrt, NULL, NULL, NULL); |
1236 | } | 1239 | } |
1237 | 1240 | ||
1238 | out: | 1241 | out: |
@@ -1305,7 +1308,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | |||
1305 | 1308 | ||
1306 | rtmsg.rtmsg_ifindex = dev->ifindex; | 1309 | rtmsg.rtmsg_ifindex = dev->ifindex; |
1307 | 1310 | ||
1308 | ip6_route_add(&rtmsg, NULL, NULL); | 1311 | ip6_route_add(&rtmsg, NULL, NULL, NULL); |
1309 | return rt6_get_dflt_router(gwaddr, dev); | 1312 | return rt6_get_dflt_router(gwaddr, dev); |
1310 | } | 1313 | } |
1311 | 1314 | ||
@@ -1323,7 +1326,7 @@ restart: | |||
1323 | 1326 | ||
1324 | read_unlock_bh(&rt6_lock); | 1327 | read_unlock_bh(&rt6_lock); |
1325 | 1328 | ||
1326 | ip6_del_rt(rt, NULL, NULL); | 1329 | ip6_del_rt(rt, NULL, NULL, NULL); |
1327 | 1330 | ||
1328 | goto restart; | 1331 | goto restart; |
1329 | } | 1332 | } |
@@ -1349,10 +1352,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1349 | rtnl_lock(); | 1352 | rtnl_lock(); |
1350 | switch (cmd) { | 1353 | switch (cmd) { |
1351 | case SIOCADDRT: | 1354 | case SIOCADDRT: |
1352 | err = ip6_route_add(&rtmsg, NULL, NULL); | 1355 | err = ip6_route_add(&rtmsg, NULL, NULL, NULL); |
1353 | break; | 1356 | break; |
1354 | case SIOCDELRT: | 1357 | case SIOCDELRT: |
1355 | err = ip6_route_del(&rtmsg, NULL, NULL); | 1358 | err = ip6_route_del(&rtmsg, NULL, NULL, NULL); |
1356 | break; | 1359 | break; |
1357 | default: | 1360 | default: |
1358 | err = -EINVAL; | 1361 | err = -EINVAL; |
@@ -1546,7 +1549,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
1546 | 1549 | ||
1547 | if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) | 1550 | if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) |
1548 | return -EINVAL; | 1551 | return -EINVAL; |
1549 | return ip6_route_del(&rtmsg, nlh, arg); | 1552 | return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb)); |
1550 | } | 1553 | } |
1551 | 1554 | ||
1552 | int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 1555 | int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
@@ -1556,7 +1559,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
1556 | 1559 | ||
1557 | if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) | 1560 | if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) |
1558 | return -EINVAL; | 1561 | return -EINVAL; |
1559 | return ip6_route_add(&rtmsg, nlh, arg); | 1562 | return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb)); |
1560 | } | 1563 | } |
1561 | 1564 | ||
1562 | struct rt6_rtnl_dump_arg | 1565 | struct rt6_rtnl_dump_arg |
@@ -1566,12 +1569,9 @@ struct rt6_rtnl_dump_arg | |||
1566 | }; | 1569 | }; |
1567 | 1570 | ||
1568 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | 1571 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, |
1569 | struct in6_addr *dst, | 1572 | struct in6_addr *dst, struct in6_addr *src, |
1570 | struct in6_addr *src, | 1573 | int iif, int type, u32 pid, u32 seq, |
1571 | int iif, | 1574 | int prefix, unsigned int flags) |
1572 | int type, u32 pid, u32 seq, | ||
1573 | struct nlmsghdr *in_nlh, int prefix, | ||
1574 | unsigned int flags) | ||
1575 | { | 1575 | { |
1576 | struct rtmsg *rtm; | 1576 | struct rtmsg *rtm; |
1577 | struct nlmsghdr *nlh; | 1577 | struct nlmsghdr *nlh; |
@@ -1585,10 +1585,6 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
1585 | } | 1585 | } |
1586 | } | 1586 | } |
1587 | 1587 | ||
1588 | if (!pid && in_nlh) { | ||
1589 | pid = in_nlh->nlmsg_pid; | ||
1590 | } | ||
1591 | |||
1592 | nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); | 1588 | nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); |
1593 | rtm = NLMSG_DATA(nlh); | 1589 | rtm = NLMSG_DATA(nlh); |
1594 | rtm->rtm_family = AF_INET6; | 1590 | rtm->rtm_family = AF_INET6; |
@@ -1675,7 +1671,7 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
1675 | 1671 | ||
1676 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, | 1672 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, |
1677 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, | 1673 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, |
1678 | NULL, prefix, NLM_F_MULTI); | 1674 | prefix, NLM_F_MULTI); |
1679 | } | 1675 | } |
1680 | 1676 | ||
1681 | static int fib6_dump_node(struct fib6_walker_t *w) | 1677 | static int fib6_dump_node(struct fib6_walker_t *w) |
@@ -1823,7 +1819,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | |||
1823 | &fl.fl6_dst, &fl.fl6_src, | 1819 | &fl.fl6_dst, &fl.fl6_src, |
1824 | iif, | 1820 | iif, |
1825 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 1821 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
1826 | nlh->nlmsg_seq, nlh, 0, 0); | 1822 | nlh->nlmsg_seq, 0, 0); |
1827 | if (err < 0) { | 1823 | if (err < 0) { |
1828 | err = -EMSGSIZE; | 1824 | err = -EMSGSIZE; |
1829 | goto out_free; | 1825 | goto out_free; |
@@ -1839,17 +1835,25 @@ out_free: | |||
1839 | goto out; | 1835 | goto out; |
1840 | } | 1836 | } |
1841 | 1837 | ||
1842 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh) | 1838 | void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, |
1839 | struct netlink_skb_parms *req) | ||
1843 | { | 1840 | { |
1844 | struct sk_buff *skb; | 1841 | struct sk_buff *skb; |
1845 | int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); | 1842 | int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); |
1843 | u32 pid = current->pid; | ||
1844 | u32 seq = 0; | ||
1846 | 1845 | ||
1846 | if (req) | ||
1847 | pid = req->pid; | ||
1848 | if (nlh) | ||
1849 | seq = nlh->nlmsg_seq; | ||
1850 | |||
1847 | skb = alloc_skb(size, gfp_any()); | 1851 | skb = alloc_skb(size, gfp_any()); |
1848 | if (!skb) { | 1852 | if (!skb) { |
1849 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); | 1853 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); |
1850 | return; | 1854 | return; |
1851 | } | 1855 | } |
1852 | if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0, 0) < 0) { | 1856 | if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { |
1853 | kfree_skb(skb); | 1857 | kfree_skb(skb); |
1854 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); | 1858 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); |
1855 | return; | 1859 | return; |