route.c (4e1a606d552de03aec2b1fd157011bf012fcc870) | route.c (dac9c9790e542777079999900594fd069ba10489) |
---|---|
1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * This program is free software; you can redistribute it and/or --- 350 unchanged lines hidden (view full) --- 359 } 360 361 return rt; 362} 363EXPORT_SYMBOL(ip6_dst_alloc); 364 365static void ip6_dst_destroy(struct dst_entry *dst) 366{ | 1/* 2 * Linux INET6 implementation 3 * FIB front-end. 4 * 5 * Authors: 6 * Pedro Roque <roque@di.fc.ul.pt> 7 * 8 * This program is free software; you can redistribute it and/or --- 350 unchanged lines hidden (view full) --- 359 } 360 361 return rt; 362} 363EXPORT_SYMBOL(ip6_dst_alloc); 364 365static void ip6_dst_destroy(struct dst_entry *dst) 366{ |
367 struct dst_metrics *p = (struct dst_metrics *)DST_METRICS_PTR(dst); | |
368 struct rt6_info *rt = (struct rt6_info *)dst; 369 struct fib6_info *from; 370 struct inet6_dev *idev; 371 | 367 struct rt6_info *rt = (struct rt6_info *)dst; 368 struct fib6_info *from; 369 struct inet6_dev *idev; 370 |
372 if (p != &dst_default_metrics && refcount_dec_and_test(&p->refcnt)) 373 kfree(p); 374 | 371 ip_dst_metrics_put(dst); |
375 rt6_uncached_list_del(rt); 376 377 idev = rt->rt6i_idev; 378 if (idev) { 379 rt->rt6i_idev = NULL; 380 in6_dev_put(idev); 381 } 382 --- 590 unchanged lines hidden (view full) --- 973 rt->dst.lastuse = jiffies; 974} 975 976/* Caller must already hold reference to @from */ 977static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from) 978{ 979 rt->rt6i_flags &= ~RTF_EXPIRES; 980 rcu_assign_pointer(rt->from, from); | 372 rt6_uncached_list_del(rt); 373 374 idev = rt->rt6i_idev; 375 if (idev) { 376 rt->rt6i_idev = NULL; 377 in6_dev_put(idev); 378 } 379 --- 590 unchanged lines hidden (view full) --- 970 rt->dst.lastuse = jiffies; 971} 972 973/* Caller must already hold reference to @from */ 974static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from) 975{ 976 rt->rt6i_flags &= ~RTF_EXPIRES; 977 rcu_assign_pointer(rt->from, from); |
981 dst_init_metrics(&rt->dst, from->fib6_metrics->metrics, true); 982 if (from->fib6_metrics != &dst_default_metrics) { 983 rt->dst._metrics |= DST_METRICS_REFCOUNTED; 984 refcount_inc(&from->fib6_metrics->refcnt); 985 } | 978 ip_dst_init_metrics(&rt->dst, from->fib6_metrics); |
986} 987 988/* Caller must already hold reference to @ort */ 989static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort) 990{ 991 struct net_device *dev = fib6_info_nh_dev(ort); 992 993 ip6_rt_init_dst(rt, ort); 994 995 rt->rt6i_dst = ort->fib6_dst; 996 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL; 997 rt->rt6i_gateway = ort->fib6_nh.nh_gw; 998 rt->rt6i_flags = ort->fib6_flags; 999 rt6_set_from(rt, ort); 1000#ifdef CONFIG_IPV6_SUBTREES 1001 rt->rt6i_src = ort->fib6_src; 1002#endif | 979} 980 981/* Caller must already hold reference to @ort */ 982static void ip6_rt_copy_init(struct rt6_info *rt, struct fib6_info *ort) 983{ 984 struct net_device *dev = fib6_info_nh_dev(ort); 985 986 ip6_rt_init_dst(rt, ort); 987 988 rt->rt6i_dst = ort->fib6_dst; 989 rt->rt6i_idev = dev ? in6_dev_get(dev) : NULL; 990 rt->rt6i_gateway = ort->fib6_nh.nh_gw; 991 rt->rt6i_flags = ort->fib6_flags; 992 rt6_set_from(rt, ort); 993#ifdef CONFIG_IPV6_SUBTREES 994 rt->rt6i_src = ort->fib6_src; 995#endif |
1003 rt->rt6i_prefsrc = ort->fib6_prefsrc; | |
1004} 1005 1006static struct fib6_node* fib6_backtrack(struct fib6_node *fn, 1007 struct in6_addr *saddr) 1008{ 1009 struct fib6_node *pn, *sn; 1010 while (1) { 1011 if (fn->fn_flags & RTN_TL_ROOT) --- 437 unchanged lines hidden (view full) --- 1449 * and exception table is indexed by a hash of 1450 * both rt6i_dst and rt6i_src. 1451 * Otherwise, the exception table is indexed by 1452 * a hash of only rt6i_dst. 1453 */ 1454 if (ort->fib6_src.plen) 1455 src_key = &nrt->rt6i_src.addr; 1456#endif | 996} 997 998static struct fib6_node* fib6_backtrack(struct fib6_node *fn, 999 struct in6_addr *saddr) 1000{ 1001 struct fib6_node *pn, *sn; 1002 while (1) { 1003 if (fn->fn_flags & RTN_TL_ROOT) --- 437 unchanged lines hidden (view full) --- 1441 * and exception table is indexed by a hash of 1442 * both rt6i_dst and rt6i_src. 1443 * Otherwise, the exception table is indexed by 1444 * a hash of only rt6i_dst. 1445 */ 1446 if (ort->fib6_src.plen) 1447 src_key = &nrt->rt6i_src.addr; 1448#endif |
1457 1458 /* Update rt6i_prefsrc as it could be changed 1459 * in rt6_remove_prefsrc() 1460 */ 1461 nrt->rt6i_prefsrc = ort->fib6_prefsrc; | |
1462 /* rt6_mtu_change() might lower mtu on ort. 1463 * Only insert this exception route if its mtu 1464 * is less than ort's mtu value. 1465 */ 1466 if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(ort)) { 1467 err = -EINVAL; 1468 goto out; 1469 } --- 165 unchanged lines hidden (view full) --- 1635 &rt->rt6i_dst.addr, 1636 src_key); 1637 if (rt6_ex) 1638 rt6_ex->stamp = jiffies; 1639 1640 rcu_read_unlock(); 1641} 1642 | 1449 /* rt6_mtu_change() might lower mtu on ort. 1450 * Only insert this exception route if its mtu 1451 * is less than ort's mtu value. 1452 */ 1453 if (dst_metric_raw(&nrt->dst, RTAX_MTU) >= fib6_mtu(ort)) { 1454 err = -EINVAL; 1455 goto out; 1456 } --- 165 unchanged lines hidden (view full) --- 1622 &rt->rt6i_dst.addr, 1623 src_key); 1624 if (rt6_ex) 1625 rt6_ex->stamp = jiffies; 1626 1627 rcu_read_unlock(); 1628} 1629 |
1643static void rt6_exceptions_remove_prefsrc(struct fib6_info *rt) 1644{ 1645 struct rt6_exception_bucket *bucket; 1646 struct rt6_exception *rt6_ex; 1647 int i; 1648 1649 bucket = rcu_dereference_protected(rt->rt6i_exception_bucket, 1650 lockdep_is_held(&rt6_exception_lock)); 1651 1652 if (bucket) { 1653 for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) { 1654 hlist_for_each_entry(rt6_ex, &bucket->chain, hlist) { 1655 rt6_ex->rt6i->rt6i_prefsrc.plen = 0; 1656 } 1657 bucket++; 1658 } 1659 } 1660} 1661 | |
1662static bool rt6_mtu_change_route_allowed(struct inet6_dev *idev, 1663 struct rt6_info *rt, int mtu) 1664{ 1665 /* If the new MTU is lower than the route PMTU, this new MTU will be the 1666 * lowest MTU in the path: always allow updating the route PMTU to 1667 * reflect PMTU decreases. 1668 * 1669 * If the new MTU is higher, and the route PMTU is equal to the local --- 428 unchanged lines hidden (view full) --- 2098 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags); 2099} 2100 2101struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, 2102 struct flowi6 *fl6, int flags) 2103{ 2104 bool any_src; 2105 | 1630static bool rt6_mtu_change_route_allowed(struct inet6_dev *idev, 1631 struct rt6_info *rt, int mtu) 1632{ 1633 /* If the new MTU is lower than the route PMTU, this new MTU will be the 1634 * lowest MTU in the path: always allow updating the route PMTU to 1635 * reflect PMTU decreases. 1636 * 1637 * If the new MTU is higher, and the route PMTU is equal to the local --- 428 unchanged lines hidden (view full) --- 2066 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags); 2067} 2068 2069struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, 2070 struct flowi6 *fl6, int flags) 2071{ 2072 bool any_src; 2073 |
2106 if (rt6_need_strict(&fl6->daddr)) { | 2074 if (ipv6_addr_type(&fl6->daddr) & 2075 (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)) { |
2107 struct dst_entry *dst; 2108 2109 dst = l3mdev_link_scope_lookup(net, fl6); 2110 if (dst) 2111 return dst; 2112 } 2113 2114 fl6->flowi6_iif = LOOPBACK_IFINDEX; --- 253 unchanged lines hidden (view full) --- 2368 __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu); 2369} 2370 2371void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, 2372 int oif, u32 mark, kuid_t uid) 2373{ 2374 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; 2375 struct dst_entry *dst; | 2076 struct dst_entry *dst; 2077 2078 dst = l3mdev_link_scope_lookup(net, fl6); 2079 if (dst) 2080 return dst; 2081 } 2082 2083 fl6->flowi6_iif = LOOPBACK_IFINDEX; --- 253 unchanged lines hidden (view full) --- 2337 __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu); 2338} 2339 2340void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, 2341 int oif, u32 mark, kuid_t uid) 2342{ 2343 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; 2344 struct dst_entry *dst; |
2376 struct flowi6 fl6; | 2345 struct flowi6 fl6 = { 2346 .flowi6_oif = oif, 2347 .flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark), 2348 .daddr = iph->daddr, 2349 .saddr = iph->saddr, 2350 .flowlabel = ip6_flowinfo(iph), 2351 .flowi6_uid = uid, 2352 }; |
2377 | 2353 |
2378 memset(&fl6, 0, sizeof(fl6)); 2379 fl6.flowi6_oif = oif; 2380 fl6.flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark); 2381 fl6.daddr = iph->daddr; 2382 fl6.saddr = iph->saddr; 2383 fl6.flowlabel = ip6_flowinfo(iph); 2384 fl6.flowi6_uid = uid; 2385 | |
2386 dst = ip6_route_output(net, NULL, &fl6); 2387 if (!dst->error) 2388 __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu)); 2389 dst_release(dst); 2390} 2391EXPORT_SYMBOL_GPL(ip6_update_pmtu); 2392 2393void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) --- 133 unchanged lines hidden (view full) --- 2527 flags, __ip6_route_redirect); 2528} 2529 2530void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, 2531 kuid_t uid) 2532{ 2533 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; 2534 struct dst_entry *dst; | 2354 dst = ip6_route_output(net, NULL, &fl6); 2355 if (!dst->error) 2356 __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu)); 2357 dst_release(dst); 2358} 2359EXPORT_SYMBOL_GPL(ip6_update_pmtu); 2360 2361void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) --- 133 unchanged lines hidden (view full) --- 2495 flags, __ip6_route_redirect); 2496} 2497 2498void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, 2499 kuid_t uid) 2500{ 2501 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; 2502 struct dst_entry *dst; |
2535 struct flowi6 fl6; | 2503 struct flowi6 fl6 = { 2504 .flowi6_iif = LOOPBACK_IFINDEX, 2505 .flowi6_oif = oif, 2506 .flowi6_mark = mark, 2507 .daddr = iph->daddr, 2508 .saddr = iph->saddr, 2509 .flowlabel = ip6_flowinfo(iph), 2510 .flowi6_uid = uid, 2511 }; |
2536 | 2512 |
2537 memset(&fl6, 0, sizeof(fl6)); 2538 fl6.flowi6_iif = LOOPBACK_IFINDEX; 2539 fl6.flowi6_oif = oif; 2540 fl6.flowi6_mark = mark; 2541 fl6.daddr = iph->daddr; 2542 fl6.saddr = iph->saddr; 2543 fl6.flowlabel = ip6_flowinfo(iph); 2544 fl6.flowi6_uid = uid; 2545 | |
2546 dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr); 2547 rt6_do_redirect(dst, NULL, skb); 2548 dst_release(dst); 2549} 2550EXPORT_SYMBOL_GPL(ip6_redirect); 2551 | 2513 dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr); 2514 rt6_do_redirect(dst, NULL, skb); 2515 dst_release(dst); 2516} 2517EXPORT_SYMBOL_GPL(ip6_redirect); 2518 |
2552void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, 2553 u32 mark) | 2519void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif) |
2554{ 2555 const struct ipv6hdr *iph = ipv6_hdr(skb); 2556 const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb); 2557 struct dst_entry *dst; | 2520{ 2521 const struct ipv6hdr *iph = ipv6_hdr(skb); 2522 const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb); 2523 struct dst_entry *dst; |
2558 struct flowi6 fl6; | 2524 struct flowi6 fl6 = { 2525 .flowi6_iif = LOOPBACK_IFINDEX, 2526 .flowi6_oif = oif, 2527 .daddr = msg->dest, 2528 .saddr = iph->daddr, 2529 .flowi6_uid = sock_net_uid(net, NULL), 2530 }; |
2559 | 2531 |
2560 memset(&fl6, 0, sizeof(fl6)); 2561 fl6.flowi6_iif = LOOPBACK_IFINDEX; 2562 fl6.flowi6_oif = oif; 2563 fl6.flowi6_mark = mark; 2564 fl6.daddr = msg->dest; 2565 fl6.saddr = iph->daddr; 2566 fl6.flowi6_uid = sock_net_uid(net, NULL); 2567 | |
2568 dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr); 2569 rt6_do_redirect(dst, NULL, skb); 2570 dst_release(dst); 2571} 2572 2573void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) 2574{ 2575 ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark, --- 153 unchanged lines hidden (view full) --- 2729 entries = dst_entries_get_slow(ops); 2730 if (entries < ops->gc_thresh) 2731 net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; 2732out: 2733 net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity; 2734 return entries > rt_max_size; 2735} 2736 | 2532 dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr); 2533 rt6_do_redirect(dst, NULL, skb); 2534 dst_release(dst); 2535} 2536 2537void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) 2538{ 2539 ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark, --- 153 unchanged lines hidden (view full) --- 2693 entries = dst_entries_get_slow(ops); 2694 if (entries < ops->gc_thresh) 2695 net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; 2696out: 2697 net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity; 2698 return entries > rt_max_size; 2699} 2700 |
2737static int ip6_convert_metrics(struct net *net, struct fib6_info *rt, 2738 struct fib6_config *cfg) 2739{ 2740 struct dst_metrics *p; 2741 2742 if (!cfg->fc_mx) 2743 return 0; 2744 2745 p = kzalloc(sizeof(*rt->fib6_metrics), GFP_KERNEL); 2746 if (unlikely(!p)) 2747 return -ENOMEM; 2748 2749 refcount_set(&p->refcnt, 1); 2750 rt->fib6_metrics = p; 2751 2752 return ip_metrics_convert(net, cfg->fc_mx, cfg->fc_mx_len, p->metrics); 2753} 2754 | |
2755static struct rt6_info *ip6_nh_lookup_table(struct net *net, 2756 struct fib6_config *cfg, 2757 const struct in6_addr *gw_addr, 2758 u32 tbid, int flags) 2759{ 2760 struct flowi6 fl6 = { 2761 .flowi6_oif = cfg->fc_ifindex, 2762 .daddr = *gw_addr, --- 259 unchanged lines hidden (view full) --- 3022 if (!table) 3023 goto out; 3024 3025 err = -ENOMEM; 3026 rt = fib6_info_alloc(gfp_flags); 3027 if (!rt) 3028 goto out; 3029 | 2701static struct rt6_info *ip6_nh_lookup_table(struct net *net, 2702 struct fib6_config *cfg, 2703 const struct in6_addr *gw_addr, 2704 u32 tbid, int flags) 2705{ 2706 struct flowi6 fl6 = { 2707 .flowi6_oif = cfg->fc_ifindex, 2708 .daddr = *gw_addr, --- 259 unchanged lines hidden (view full) --- 2968 if (!table) 2969 goto out; 2970 2971 err = -ENOMEM; 2972 rt = fib6_info_alloc(gfp_flags); 2973 if (!rt) 2974 goto out; 2975 |
2976 rt->fib6_metrics = ip_fib_metrics_init(net, cfg->fc_mx, cfg->fc_mx_len); 2977 if (IS_ERR(rt->fib6_metrics)) { 2978 err = PTR_ERR(rt->fib6_metrics); 2979 /* Do not leave garbage there. */ 2980 rt->fib6_metrics = (struct dst_metrics *)&dst_default_metrics; 2981 goto out; 2982 } 2983 |
|
3030 if (cfg->fc_flags & RTF_ADDRCONF) 3031 rt->dst_nocount = true; 3032 | 2984 if (cfg->fc_flags & RTF_ADDRCONF) 2985 rt->dst_nocount = true; 2986 |
3033 err = ip6_convert_metrics(net, rt, cfg); 3034 if (err < 0) 3035 goto out; 3036 | |
3037 if (cfg->fc_flags & RTF_EXPIRES) 3038 fib6_set_expires(rt, jiffies + 3039 clock_t_to_jiffies(cfg->fc_expires)); 3040 else 3041 fib6_clean_expires(rt); 3042 3043 if (cfg->fc_protocol == RTPROT_UNSPEC) 3044 cfg->fc_protocol = RTPROT_BOOT; --- 92 unchanged lines hidden (view full) --- 3137install_route: 3138 if (!(rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) && 3139 !netif_carrier_ok(dev)) 3140 rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN; 3141 rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK); 3142 rt->fib6_nh.nh_dev = dev; 3143 rt->fib6_table = table; 3144 | 2987 if (cfg->fc_flags & RTF_EXPIRES) 2988 fib6_set_expires(rt, jiffies + 2989 clock_t_to_jiffies(cfg->fc_expires)); 2990 else 2991 fib6_clean_expires(rt); 2992 2993 if (cfg->fc_protocol == RTPROT_UNSPEC) 2994 cfg->fc_protocol = RTPROT_BOOT; --- 92 unchanged lines hidden (view full) --- 3087install_route: 3088 if (!(rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST)) && 3089 !netif_carrier_ok(dev)) 3090 rt->fib6_nh.nh_flags |= RTNH_F_LINKDOWN; 3091 rt->fib6_nh.nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK); 3092 rt->fib6_nh.nh_dev = dev; 3093 rt->fib6_table = table; 3094 |
3145 cfg->fc_nlinfo.nl_net = dev_net(dev); 3146 | |
3147 if (idev) 3148 in6_dev_put(idev); 3149 3150 return rt; 3151out: 3152 if (dev) 3153 dev_put(dev); 3154 if (idev) --- 475 unchanged lines hidden (view full) --- 3630 3631 rcu_read_unlock(); 3632} 3633 3634static void rtmsg_to_fib6_config(struct net *net, 3635 struct in6_rtmsg *rtmsg, 3636 struct fib6_config *cfg) 3637{ | 3095 if (idev) 3096 in6_dev_put(idev); 3097 3098 return rt; 3099out: 3100 if (dev) 3101 dev_put(dev); 3102 if (idev) --- 475 unchanged lines hidden (view full) --- 3578 3579 rcu_read_unlock(); 3580} 3581 3582static void rtmsg_to_fib6_config(struct net *net, 3583 struct in6_rtmsg *rtmsg, 3584 struct fib6_config *cfg) 3585{ |
3638 memset(cfg, 0, sizeof(*cfg)); | 3586 *cfg = (struct fib6_config){ 3587 .fc_table = l3mdev_fib_table_by_index(net, rtmsg->rtmsg_ifindex) ? 3588 : RT6_TABLE_MAIN, 3589 .fc_ifindex = rtmsg->rtmsg_ifindex, 3590 .fc_metric = rtmsg->rtmsg_metric, 3591 .fc_expires = rtmsg->rtmsg_info, 3592 .fc_dst_len = rtmsg->rtmsg_dst_len, 3593 .fc_src_len = rtmsg->rtmsg_src_len, 3594 .fc_flags = rtmsg->rtmsg_flags, 3595 .fc_type = rtmsg->rtmsg_type, |
3639 | 3596 |
3640 cfg->fc_table = l3mdev_fib_table_by_index(net, rtmsg->rtmsg_ifindex) ? 3641 : RT6_TABLE_MAIN; 3642 cfg->fc_ifindex = rtmsg->rtmsg_ifindex; 3643 cfg->fc_metric = rtmsg->rtmsg_metric; 3644 cfg->fc_expires = rtmsg->rtmsg_info; 3645 cfg->fc_dst_len = rtmsg->rtmsg_dst_len; 3646 cfg->fc_src_len = rtmsg->rtmsg_src_len; 3647 cfg->fc_flags = rtmsg->rtmsg_flags; 3648 cfg->fc_type = rtmsg->rtmsg_type; | 3597 .fc_nlinfo.nl_net = net, |
3649 | 3598 |
3650 cfg->fc_nlinfo.nl_net = net; 3651 3652 cfg->fc_dst = rtmsg->rtmsg_dst; 3653 cfg->fc_src = rtmsg->rtmsg_src; 3654 cfg->fc_gateway = rtmsg->rtmsg_gateway; | 3599 .fc_dst = rtmsg->rtmsg_dst, 3600 .fc_src = rtmsg->rtmsg_src, 3601 .fc_gateway = rtmsg->rtmsg_gateway, 3602 }; |
3655} 3656 3657int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) 3658{ 3659 struct fib6_config cfg; 3660 struct in6_rtmsg rtmsg; 3661 int err; 3662 --- 90 unchanged lines hidden (view full) --- 3753 u32 tb_id; 3754 struct net_device *dev = idev->dev; 3755 struct fib6_info *f6i; 3756 3757 f6i = fib6_info_alloc(gfp_flags); 3758 if (!f6i) 3759 return ERR_PTR(-ENOMEM); 3760 | 3603} 3604 3605int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) 3606{ 3607 struct fib6_config cfg; 3608 struct in6_rtmsg rtmsg; 3609 int err; 3610 --- 90 unchanged lines hidden (view full) --- 3701 u32 tb_id; 3702 struct net_device *dev = idev->dev; 3703 struct fib6_info *f6i; 3704 3705 f6i = fib6_info_alloc(gfp_flags); 3706 if (!f6i) 3707 return ERR_PTR(-ENOMEM); 3708 |
3709 f6i->fib6_metrics = ip_fib_metrics_init(net, NULL, 0); |
|
3761 f6i->dst_nocount = true; 3762 f6i->dst_host = true; 3763 f6i->fib6_protocol = RTPROT_KERNEL; 3764 f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP; 3765 if (anycast) { 3766 f6i->fib6_type = RTN_ANYCAST; 3767 f6i->fib6_flags |= RTF_ANYCAST; 3768 } else { --- 26 unchanged lines hidden (view full) --- 3795 struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; 3796 3797 if (((void *)rt->fib6_nh.nh_dev == dev || !dev) && 3798 rt != net->ipv6.fib6_null_entry && 3799 ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) { 3800 spin_lock_bh(&rt6_exception_lock); 3801 /* remove prefsrc entry */ 3802 rt->fib6_prefsrc.plen = 0; | 3710 f6i->dst_nocount = true; 3711 f6i->dst_host = true; 3712 f6i->fib6_protocol = RTPROT_KERNEL; 3713 f6i->fib6_flags = RTF_UP | RTF_NONEXTHOP; 3714 if (anycast) { 3715 f6i->fib6_type = RTN_ANYCAST; 3716 f6i->fib6_flags |= RTF_ANYCAST; 3717 } else { --- 26 unchanged lines hidden (view full) --- 3744 struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; 3745 3746 if (((void *)rt->fib6_nh.nh_dev == dev || !dev) && 3747 rt != net->ipv6.fib6_null_entry && 3748 ipv6_addr_equal(addr, &rt->fib6_prefsrc.addr)) { 3749 spin_lock_bh(&rt6_exception_lock); 3750 /* remove prefsrc entry */ 3751 rt->fib6_prefsrc.plen = 0; |
3803 /* need to update cache as well */ 3804 rt6_exceptions_remove_prefsrc(rt); | |
3805 spin_unlock_bh(&rt6_exception_lock); 3806 } 3807 return 0; 3808} 3809 3810void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) 3811{ 3812 struct net *net = dev_net(ifp->idev->dev); --- 352 unchanged lines hidden (view full) --- 4165 struct netlink_ext_ack *extack) 4166{ 4167 struct rtmsg *rtm; 4168 struct nlattr *tb[RTA_MAX+1]; 4169 unsigned int pref; 4170 int err; 4171 4172 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy, | 3752 spin_unlock_bh(&rt6_exception_lock); 3753 } 3754 return 0; 3755} 3756 3757void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) 3758{ 3759 struct net *net = dev_net(ifp->idev->dev); --- 352 unchanged lines hidden (view full) --- 4112 struct netlink_ext_ack *extack) 4113{ 4114 struct rtmsg *rtm; 4115 struct nlattr *tb[RTA_MAX+1]; 4116 unsigned int pref; 4117 int err; 4118 4119 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy, |
4173 NULL); | 4120 extack); |
4174 if (err < 0) 4175 goto errout; 4176 4177 err = -EINVAL; 4178 rtm = nlmsg_data(nlh); | 4121 if (err < 0) 4122 goto errout; 4123 4124 err = -EINVAL; 4125 rtm = nlmsg_data(nlh); |
4179 memset(cfg, 0, sizeof(*cfg)); | |
4180 | 4126 |
4181 cfg->fc_table = rtm->rtm_table; 4182 cfg->fc_dst_len = rtm->rtm_dst_len; 4183 cfg->fc_src_len = rtm->rtm_src_len; 4184 cfg->fc_flags = RTF_UP; 4185 cfg->fc_protocol = rtm->rtm_protocol; 4186 cfg->fc_type = rtm->rtm_type; | 4127 *cfg = (struct fib6_config){ 4128 .fc_table = rtm->rtm_table, 4129 .fc_dst_len = rtm->rtm_dst_len, 4130 .fc_src_len = rtm->rtm_src_len, 4131 .fc_flags = RTF_UP, 4132 .fc_protocol = rtm->rtm_protocol, 4133 .fc_type = rtm->rtm_type, |
4187 | 4134 |
4135 .fc_nlinfo.portid = NETLINK_CB(skb).portid, 4136 .fc_nlinfo.nlh = nlh, 4137 .fc_nlinfo.nl_net = sock_net(skb->sk), 4138 }; 4139 |
|
4188 if (rtm->rtm_type == RTN_UNREACHABLE || 4189 rtm->rtm_type == RTN_BLACKHOLE || 4190 rtm->rtm_type == RTN_PROHIBIT || 4191 rtm->rtm_type == RTN_THROW) 4192 cfg->fc_flags |= RTF_REJECT; 4193 4194 if (rtm->rtm_type == RTN_LOCAL) 4195 cfg->fc_flags |= RTF_LOCAL; 4196 4197 if (rtm->rtm_flags & RTM_F_CLONED) 4198 cfg->fc_flags |= RTF_CACHE; 4199 4200 cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK); 4201 | 4140 if (rtm->rtm_type == RTN_UNREACHABLE || 4141 rtm->rtm_type == RTN_BLACKHOLE || 4142 rtm->rtm_type == RTN_PROHIBIT || 4143 rtm->rtm_type == RTN_THROW) 4144 cfg->fc_flags |= RTF_REJECT; 4145 4146 if (rtm->rtm_type == RTN_LOCAL) 4147 cfg->fc_flags |= RTF_LOCAL; 4148 4149 if (rtm->rtm_flags & RTM_F_CLONED) 4150 cfg->fc_flags |= RTF_CACHE; 4151 4152 cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK); 4153 |
4202 cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid; 4203 cfg->fc_nlinfo.nlh = nlh; 4204 cfg->fc_nlinfo.nl_net = sock_net(skb->sk); 4205 | |
4206 if (tb[RTA_GATEWAY]) { 4207 cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]); 4208 cfg->fc_flags |= RTF_GATEWAY; 4209 } 4210 4211 if (tb[RTA_DST]) { 4212 int plen = (rtm->rtm_dst_len + 7) >> 3; 4213 --- 631 unchanged lines hidden (view full) --- 4845 struct net *net = sock_net(in_skb->sk); 4846 struct nlattr *tb[RTA_MAX+1]; 4847 int err, iif = 0, oif = 0; 4848 struct fib6_info *from; 4849 struct dst_entry *dst; 4850 struct rt6_info *rt; 4851 struct sk_buff *skb; 4852 struct rtmsg *rtm; | 4154 if (tb[RTA_GATEWAY]) { 4155 cfg->fc_gateway = nla_get_in6_addr(tb[RTA_GATEWAY]); 4156 cfg->fc_flags |= RTF_GATEWAY; 4157 } 4158 4159 if (tb[RTA_DST]) { 4160 int plen = (rtm->rtm_dst_len + 7) >> 3; 4161 --- 631 unchanged lines hidden (view full) --- 4793 struct net *net = sock_net(in_skb->sk); 4794 struct nlattr *tb[RTA_MAX+1]; 4795 int err, iif = 0, oif = 0; 4796 struct fib6_info *from; 4797 struct dst_entry *dst; 4798 struct rt6_info *rt; 4799 struct sk_buff *skb; 4800 struct rtmsg *rtm; |
4853 struct flowi6 fl6; | 4801 struct flowi6 fl6 = {}; |
4854 bool fibmatch; 4855 4856 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy, 4857 extack); 4858 if (err < 0) 4859 goto errout; 4860 4861 err = -EINVAL; | 4802 bool fibmatch; 4803 4804 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy, 4805 extack); 4806 if (err < 0) 4807 goto errout; 4808 4809 err = -EINVAL; |
4862 memset(&fl6, 0, sizeof(fl6)); | |
4863 rtm = nlmsg_data(nlh); 4864 fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0); 4865 fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH); 4866 4867 if (tb[RTA_SRC]) { 4868 if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) 4869 goto errout; 4870 --- 585 unchanged lines hidden --- | 4810 rtm = nlmsg_data(nlh); 4811 fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0); 4812 fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH); 4813 4814 if (tb[RTA_SRC]) { 4815 if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) 4816 goto errout; 4817 --- 585 unchanged lines hidden --- |