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 --- |