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