route.c (fae6ec69c84d71b1d5bda9ede1a262c1681684aa) route.c (0d51aa80a9b1db43920c0770c3bb842dd823c005)
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $

--- 370 unchanged lines hidden (view full) ---

379}
380
381/* ip6_ins_rt is called with FREE rt6_lock.
382 It takes new route entry, the addition fails by any reason the
383 route is freed. In any case, if caller does not hold it, it may
384 be destroyed.
385 */
386
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $

--- 370 unchanged lines hidden (view full) ---

379}
380
381/* ip6_ins_rt is called with FREE rt6_lock.
382 It takes new route entry, the addition fails by any reason the
383 route is freed. In any case, if caller does not hold it, it may
384 be destroyed.
385 */
386
387int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
387int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
388 void *_rtattr, struct netlink_skb_parms *req)
388{
389 int err;
390
391 write_lock_bh(&rt6_lock);
389{
390 int err;
391
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
395 return err;
396}
397
398/* No rt6_lock! If COW failed, the function returns dead route entry
399 with dst->error set to errno value.
400 */
401
402static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
394 write_unlock_bh(&rt6_lock);
395
396 return err;
397}
398
399/* No rt6_lock! If COW failed, the function returns dead route entry
400 with dst->error set to errno value.
401 */
402
403static 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 int err;
406 struct rt6_info *rt;
407
408 /*
409 * Clone the route.
410 */
411

--- 15 unchanged lines hidden (view full) ---

427 rt->rt6i_src.plen = 128;
428 }
429#endif
430
431 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
432
433 dst_hold(&rt->u.dst);
434
405{
406 int err;
407 struct rt6_info *rt;
408
409 /*
410 * Clone the route.
411 */
412

--- 15 unchanged lines hidden (view full) ---

428 rt->rt6i_src.plen = 128;
429 }
430#endif
431
432 rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
433
434 dst_hold(&rt->u.dst);
435
435 err = ip6_ins_rt(rt, NULL, NULL);
436 err = ip6_ins_rt(rt, NULL, NULL, req);
436 if (err == 0)
437 return rt;
438
439 rt->u.dst.error = err;
440
441 return rt;
442 }
443 dst_hold(&ip6_null_entry.u.dst);

--- 42 unchanged lines hidden (view full) ---

486 BACKTRACK();
487
488 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
489 struct rt6_info *nrt;
490 dst_hold(&rt->u.dst);
491 read_unlock_bh(&rt6_lock);
492
493 nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
437 if (err == 0)
438 return rt;
439
440 rt->u.dst.error = err;
441
442 return rt;
443 }
444 dst_hold(&ip6_null_entry.u.dst);

--- 42 unchanged lines hidden (view full) ---

487 BACKTRACK();
488
489 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
490 struct rt6_info *nrt;
491 dst_hold(&rt->u.dst);
492 read_unlock_bh(&rt6_lock);
493
494 nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
494 &skb->nh.ipv6h->saddr);
495 &skb->nh.ipv6h->saddr,
496 &NETLINK_CB(skb));
495
496 dst_release(&rt->u.dst);
497 rt = nrt;
498
499 if (rt->u.dst.error != -EEXIST || --attempts <= 0)
500 goto out2;
501
502 /* Race condition! In the gap, when rt6_lock was

--- 43 unchanged lines hidden (view full) ---

546 BACKTRACK();
547 }
548
549 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
550 struct rt6_info *nrt;
551 dst_hold(&rt->u.dst);
552 read_unlock_bh(&rt6_lock);
553
497
498 dst_release(&rt->u.dst);
499 rt = nrt;
500
501 if (rt->u.dst.error != -EEXIST || --attempts <= 0)
502 goto out2;
503
504 /* Race condition! In the gap, when rt6_lock was

--- 43 unchanged lines hidden (view full) ---

548 BACKTRACK();
549 }
550
551 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
552 struct rt6_info *nrt;
553 dst_hold(&rt->u.dst);
554 read_unlock_bh(&rt6_lock);
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
556 dst_release(&rt->u.dst);
557 rt = nrt;
558
559 if (rt->u.dst.error != -EEXIST || --attempts <= 0)
560 goto out2;
561
562 /* Race condition! In the gap, when rt6_lock was

--- 30 unchanged lines hidden (view full) ---

593}
594
595static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
596{
597 struct rt6_info *rt = (struct rt6_info *) dst;
598
599 if (rt) {
600 if (rt->rt6i_flags & RTF_CACHE)
557
558 dst_release(&rt->u.dst);
559 rt = nrt;
560
561 if (rt->u.dst.error != -EEXIST || --attempts <= 0)
562 goto out2;
563
564 /* Race condition! In the gap, when rt6_lock was

--- 30 unchanged lines hidden (view full) ---

595}
596
597static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
598{
599 struct rt6_info *rt = (struct rt6_info *) dst;
600
601 if (rt) {
602 if (rt->rt6i_flags & RTF_CACHE)
601 ip6_del_rt(rt, NULL, NULL);
603 ip6_del_rt(rt, NULL, NULL, NULL);
602 else
603 dst_release(dst);
604 }
605 return NULL;
606}
607
608static void ip6_link_failure(struct sk_buff *skb)
609{

--- 172 unchanged lines hidden (view full) ---

782 }
783 return hoplimit;
784}
785
786/*
787 *
788 */
789
604 else
605 dst_release(dst);
606 }
607 return NULL;
608}
609
610static void ip6_link_failure(struct sk_buff *skb)
611{

--- 172 unchanged lines hidden (view full) ---

784 }
785 return hoplimit;
786}
787
788/*
789 *
790 */
791
790int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
792int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
793 void *_rtattr, struct netlink_skb_parms *req)
791{
792 int err;
793 struct rtmsg *r;
794 struct rtattr **rta;
795 struct rt6_info *rt = NULL;
796 struct net_device *dev = NULL;
797 struct inet6_dev *idev = NULL;
798 int addr_type;

--- 170 unchanged lines hidden (view full) ---

969 if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
970 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
971 if (!rt->u.dst.metrics[RTAX_MTU-1])
972 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
973 if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
974 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
975 rt->u.dst.dev = dev;
976 rt->rt6i_idev = idev;
794{
795 int err;
796 struct rtmsg *r;
797 struct rtattr **rta;
798 struct rt6_info *rt = NULL;
799 struct net_device *dev = NULL;
800 struct inet6_dev *idev = NULL;
801 int addr_type;

--- 170 unchanged lines hidden (view full) ---

972 if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
973 rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
974 if (!rt->u.dst.metrics[RTAX_MTU-1])
975 rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
976 if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
977 rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
978 rt->u.dst.dev = dev;
979 rt->rt6i_idev = idev;
977 return ip6_ins_rt(rt, nlh, _rtattr);
980 return ip6_ins_rt(rt, nlh, _rtattr, req);
978
979out:
980 if (dev)
981 dev_put(dev);
982 if (idev)
983 in6_dev_put(idev);
984 if (rt)
985 dst_free((struct dst_entry *) rt);
986 return err;
987}
988
981
982out:
983 if (dev)
984 dev_put(dev);
985 if (idev)
986 in6_dev_put(idev);
987 if (rt)
988 dst_free((struct dst_entry *) rt);
989 return err;
990}
991
989int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
992int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
990{
991 int err;
992
993 write_lock_bh(&rt6_lock);
994
995 rt6_reset_dflt_pointer(NULL);
996
993{
994 int err;
995
996 write_lock_bh(&rt6_lock);
997
998 rt6_reset_dflt_pointer(NULL);
999
997 err = fib6_del(rt, nlh, _rtattr);
1000 err = fib6_del(rt, nlh, _rtattr, req);
998 dst_release(&rt->u.dst);
999
1000 write_unlock_bh(&rt6_lock);
1001
1002 return err;
1003}
1004
1001 dst_release(&rt->u.dst);
1002
1003 write_unlock_bh(&rt6_lock);
1004
1005 return err;
1006}
1007
1005static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
1008static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
1006{
1007 struct fib6_node *fn;
1008 struct rt6_info *rt;
1009 int err = -ESRCH;
1010
1011 read_lock_bh(&rt6_lock);
1012
1013 fn = fib6_locate(&ip6_routing_table,

--- 10 unchanged lines hidden (view full) ---

1024 !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway))
1025 continue;
1026 if (rtmsg->rtmsg_metric &&
1027 rtmsg->rtmsg_metric != rt->rt6i_metric)
1028 continue;
1029 dst_hold(&rt->u.dst);
1030 read_unlock_bh(&rt6_lock);
1031
1009{
1010 struct fib6_node *fn;
1011 struct rt6_info *rt;
1012 int err = -ESRCH;
1013
1014 read_lock_bh(&rt6_lock);
1015
1016 fn = fib6_locate(&ip6_routing_table,

--- 10 unchanged lines hidden (view full) ---

1027 !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway))
1028 continue;
1029 if (rtmsg->rtmsg_metric &&
1030 rtmsg->rtmsg_metric != rt->rt6i_metric)
1031 continue;
1032 dst_hold(&rt->u.dst);
1033 read_unlock_bh(&rt6_lock);
1034
1032 return ip6_del_rt(rt, nlh, _rtattr);
1035 return ip6_del_rt(rt, nlh, _rtattr, req);
1033 }
1034 }
1035 read_unlock_bh(&rt6_lock);
1036
1037 return err;
1038}
1039
1040/*

--- 90 unchanged lines hidden (view full) ---

1131 nrt->u.dst.flags |= DST_HOST;
1132
1133 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
1134 nrt->rt6i_nexthop = neigh_clone(neigh);
1135 /* Reset pmtu, it may be better */
1136 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));
1138
1036 }
1037 }
1038 read_unlock_bh(&rt6_lock);
1039
1040 return err;
1041}
1042
1043/*

--- 90 unchanged lines hidden (view full) ---

1134 nrt->u.dst.flags |= DST_HOST;
1135
1136 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
1137 nrt->rt6i_nexthop = neigh_clone(neigh);
1138 /* Reset pmtu, it may be better */
1139 nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
1140 nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
1141
1139 if (ip6_ins_rt(nrt, NULL, NULL))
1142 if (ip6_ins_rt(nrt, NULL, NULL, NULL))
1140 goto out;
1141
1142 if (rt->rt6i_flags&RTF_CACHE) {
1143 goto out;
1144
1145 if (rt->rt6i_flags&RTF_CACHE) {
1143 ip6_del_rt(rt, NULL, NULL);
1146 ip6_del_rt(rt, NULL, NULL, NULL);
1144 return;
1145 }
1146
1147out:
1148 dst_release(&rt->u.dst);
1149 return;
1150}
1151

--- 47 unchanged lines hidden (view full) ---

1199 }
1200
1201 /* Network route.
1202 Two cases are possible:
1203 1. It is connected route. Action: COW
1204 2. It is gatewayed route or NONEXTHOP route. Action: clone it.
1205 */
1206 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
1147 return;
1148 }
1149
1150out:
1151 dst_release(&rt->u.dst);
1152 return;
1153}
1154

--- 47 unchanged lines hidden (view full) ---

1202 }
1203
1204 /* Network route.
1205 Two cases are possible:
1206 1. It is connected route. Action: COW
1207 2. It is gatewayed route or NONEXTHOP route. Action: clone it.
1208 */
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) {
1209 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
1210 if (allfrag)
1211 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
1212 /* According to RFC 1981, detecting PMTU increase shouldn't be
1213 happened within 5 mins, the recommended timer is 10 mins.
1214 Here this route expiration time is set to ip6_rt_mtu_expires
1215 which is 10 mins. After 10 mins the decreased pmtu is expired

--- 11 unchanged lines hidden (view full) ---

1227 nrt->rt6i_dst.plen = 128;
1228 nrt->u.dst.flags |= DST_HOST;
1229 nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop);
1230 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1231 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
1232 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
1233 if (allfrag)
1234 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
1211 if (!nrt->u.dst.error) {
1212 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
1213 if (allfrag)
1214 nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
1215 /* According to RFC 1981, detecting PMTU increase shouldn't be
1216 happened within 5 mins, the recommended timer is 10 mins.
1217 Here this route expiration time is set to ip6_rt_mtu_expires
1218 which is 10 mins. After 10 mins the decreased pmtu is expired

--- 11 unchanged lines hidden (view full) ---

1230 nrt->rt6i_dst.plen = 128;
1231 nrt->u.dst.flags |= DST_HOST;
1232 nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop);
1233 dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
1234 nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
1235 nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
1236 if (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 }
1237
1238out:
1239 dst_release(&rt->u.dst);
1240}
1241
1242/*
1243 * Misc support functions

--- 56 unchanged lines hidden (view full) ---

1300 memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
1301 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1302 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1303 rtmsg.rtmsg_metric = 1024;
1304 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES;
1305
1306 rtmsg.rtmsg_ifindex = dev->ifindex;
1307
1239 }
1240
1241out:
1242 dst_release(&rt->u.dst);
1243}
1244
1245/*
1246 * Misc support functions

--- 56 unchanged lines hidden (view full) ---

1303 memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
1304 rtmsg.rtmsg_type = RTMSG_NEWROUTE;
1305 ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
1306 rtmsg.rtmsg_metric = 1024;
1307 rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES;
1308
1309 rtmsg.rtmsg_ifindex = dev->ifindex;
1310
1308 ip6_route_add(&rtmsg, NULL, NULL);
1311 ip6_route_add(&rtmsg, NULL, NULL, NULL);
1309 return rt6_get_dflt_router(gwaddr, dev);
1310}
1311
1312void rt6_purge_dflt_routers(void)
1313{
1314 struct rt6_info *rt;
1315
1316restart:
1317 read_lock_bh(&rt6_lock);
1318 for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) {
1319 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
1320 dst_hold(&rt->u.dst);
1321
1322 rt6_reset_dflt_pointer(NULL);
1323
1324 read_unlock_bh(&rt6_lock);
1325
1312 return rt6_get_dflt_router(gwaddr, dev);
1313}
1314
1315void rt6_purge_dflt_routers(void)
1316{
1317 struct rt6_info *rt;
1318
1319restart:
1320 read_lock_bh(&rt6_lock);
1321 for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) {
1322 if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
1323 dst_hold(&rt->u.dst);
1324
1325 rt6_reset_dflt_pointer(NULL);
1326
1327 read_unlock_bh(&rt6_lock);
1328
1326 ip6_del_rt(rt, NULL, NULL);
1329 ip6_del_rt(rt, NULL, NULL, NULL);
1327
1328 goto restart;
1329 }
1330 }
1331 read_unlock_bh(&rt6_lock);
1332}
1333
1334int ipv6_route_ioctl(unsigned int cmd, void __user *arg)

--- 9 unchanged lines hidden (view full) ---

1344 err = copy_from_user(&rtmsg, arg,
1345 sizeof(struct in6_rtmsg));
1346 if (err)
1347 return -EFAULT;
1348
1349 rtnl_lock();
1350 switch (cmd) {
1351 case SIOCADDRT:
1330
1331 goto restart;
1332 }
1333 }
1334 read_unlock_bh(&rt6_lock);
1335}
1336
1337int ipv6_route_ioctl(unsigned int cmd, void __user *arg)

--- 9 unchanged lines hidden (view full) ---

1347 err = copy_from_user(&rtmsg, arg,
1348 sizeof(struct in6_rtmsg));
1349 if (err)
1350 return -EFAULT;
1351
1352 rtnl_lock();
1353 switch (cmd) {
1354 case SIOCADDRT:
1352 err = ip6_route_add(&rtmsg, NULL, NULL);
1355 err = ip6_route_add(&rtmsg, NULL, NULL, NULL);
1353 break;
1354 case SIOCDELRT:
1356 break;
1357 case SIOCDELRT:
1355 err = ip6_route_del(&rtmsg, NULL, NULL);
1358 err = ip6_route_del(&rtmsg, NULL, NULL, NULL);
1356 break;
1357 default:
1358 err = -EINVAL;
1359 }
1360 rtnl_unlock();
1361
1362 return err;
1363 };

--- 177 unchanged lines hidden (view full) ---

1541
1542int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1543{
1544 struct rtmsg *r = NLMSG_DATA(nlh);
1545 struct in6_rtmsg rtmsg;
1546
1547 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1548 return -EINVAL;
1359 break;
1360 default:
1361 err = -EINVAL;
1362 }
1363 rtnl_unlock();
1364
1365 return err;
1366 };

--- 177 unchanged lines hidden (view full) ---

1544
1545int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1546{
1547 struct rtmsg *r = NLMSG_DATA(nlh);
1548 struct in6_rtmsg rtmsg;
1549
1550 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1551 return -EINVAL;
1549 return ip6_route_del(&rtmsg, nlh, arg);
1552 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb));
1550}
1551
1552int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1553{
1554 struct rtmsg *r = NLMSG_DATA(nlh);
1555 struct in6_rtmsg rtmsg;
1556
1557 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1558 return -EINVAL;
1553}
1554
1555int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1556{
1557 struct rtmsg *r = NLMSG_DATA(nlh);
1558 struct in6_rtmsg rtmsg;
1559
1560 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1561 return -EINVAL;
1559 return ip6_route_add(&rtmsg, nlh, arg);
1562 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb));
1560}
1561
1562struct rt6_rtnl_dump_arg
1563{
1564 struct sk_buff *skb;
1565 struct netlink_callback *cb;
1566};
1567
1568static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1563}
1564
1565struct rt6_rtnl_dump_arg
1566{
1567 struct sk_buff *skb;
1568 struct netlink_callback *cb;
1569};
1570
1571static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1569 struct in6_addr *dst,
1570 struct in6_addr *src,
1571 int iif,
1572 int type, u32 pid, u32 seq,
1573 struct nlmsghdr *in_nlh, int prefix,
1574 unsigned int flags)
1572 struct in6_addr *dst, struct in6_addr *src,
1573 int iif, int type, u32 pid, u32 seq,
1574 int prefix, unsigned int flags)
1575{
1576 struct rtmsg *rtm;
1577 struct nlmsghdr *nlh;
1578 unsigned char *b = skb->tail;
1579 struct rta_cacheinfo ci;
1580
1581 if (prefix) { /* user wants prefix routes only */
1582 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
1583 /* success since this is not a prefix route */
1584 return 1;
1585 }
1586 }
1587
1575{
1576 struct rtmsg *rtm;
1577 struct nlmsghdr *nlh;
1578 unsigned char *b = skb->tail;
1579 struct rta_cacheinfo ci;
1580
1581 if (prefix) { /* user wants prefix routes only */
1582 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
1583 /* success since this is not a prefix route */
1584 return 1;
1585 }
1586 }
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);
1593 rtm = NLMSG_DATA(nlh);
1594 rtm->rtm_family = AF_INET6;
1595 rtm->rtm_dst_len = rt->rt6i_dst.plen;
1596 rtm->rtm_src_len = rt->rt6i_src.plen;
1597 rtm->rtm_tos = 0;
1598 rtm->rtm_table = RT_TABLE_MAIN;
1599 if (rt->rt6i_flags&RTF_REJECT)

--- 70 unchanged lines hidden (view full) ---

1670 if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) {
1671 struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh);
1672 prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
1673 } else
1674 prefix = 0;
1675
1676 return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
1677 NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
1588 nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags);
1589 rtm = NLMSG_DATA(nlh);
1590 rtm->rtm_family = AF_INET6;
1591 rtm->rtm_dst_len = rt->rt6i_dst.plen;
1592 rtm->rtm_src_len = rt->rt6i_src.plen;
1593 rtm->rtm_tos = 0;
1594 rtm->rtm_table = RT_TABLE_MAIN;
1595 if (rt->rt6i_flags&RTF_REJECT)

--- 70 unchanged lines hidden (view full) ---

1666 if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) {
1667 struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh);
1668 prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
1669 } else
1670 prefix = 0;
1671
1672 return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
1673 NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
1678 NULL, prefix, NLM_F_MULTI);
1674 prefix, NLM_F_MULTI);
1679}
1680
1681static int fib6_dump_node(struct fib6_walker_t *w)
1682{
1683 int res;
1684 struct rt6_info *rt;
1685
1686 for (rt = w->leaf; rt; rt = rt->u.next) {

--- 131 unchanged lines hidden (view full) ---

1818
1819 skb->dst = &rt->u.dst;
1820
1821 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
1822 err = rt6_fill_node(skb, rt,
1823 &fl.fl6_dst, &fl.fl6_src,
1824 iif,
1825 RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
1675}
1676
1677static int fib6_dump_node(struct fib6_walker_t *w)
1678{
1679 int res;
1680 struct rt6_info *rt;
1681
1682 for (rt = w->leaf; rt; rt = rt->u.next) {

--- 131 unchanged lines hidden (view full) ---

1814
1815 skb->dst = &rt->u.dst;
1816
1817 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
1818 err = rt6_fill_node(skb, rt,
1819 &fl.fl6_dst, &fl.fl6_src,
1820 iif,
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) {
1828 err = -EMSGSIZE;
1829 goto out_free;
1830 }
1831
1832 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
1833 if (err > 0)
1834 err = 0;
1835out:
1836 return err;
1837out_free:
1838 kfree_skb(skb);
1839 goto out;
1840}
1841
1823 if (err < 0) {
1824 err = -EMSGSIZE;
1825 goto out_free;
1826 }
1827
1828 err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
1829 if (err > 0)
1830 err = 0;
1831out:
1832 return err;
1833out_free:
1834 kfree_skb(skb);
1835 goto out;
1836}
1837
1842void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
1838void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh,
1839 struct netlink_skb_parms *req)
1843{
1844 struct sk_buff *skb;
1845 int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
1840{
1841 struct sk_buff *skb;
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());
1848 if (!skb) {
1849 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
1850 return;
1851 }
1851 skb = alloc_skb(size, gfp_any());
1852 if (!skb) {
1853 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
1854 return;
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);
1854 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
1855 return;
1856 }
1857 NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_ROUTE;
1858 netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_ROUTE, gfp_any());
1859}
1860

--- 272 unchanged lines hidden ---
1857 kfree_skb(skb);
1858 netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
1859 return;
1860 }
1861 NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_ROUTE;
1862 netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_ROUTE, gfp_any());
1863}
1864

--- 272 unchanged lines hidden ---