route.c (9a2a537acc75dfd19c4358bc9cb6042bdc60698c) route.c (b75cc8f90f07342467b3bd51dbc0054f185032c9)
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

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

447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
448 rt6_check_expired(rt->from);
449 }
450 return false;
451}
452
453static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
454 struct flowi6 *fl6, int oif,
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

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

447 return rt->dst.obsolete != DST_OBSOLETE_FORCE_CHK ||
448 rt6_check_expired(rt->from);
449 }
450 return false;
451}
452
453static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
454 struct flowi6 *fl6, int oif,
455 const struct sk_buff *skb,
455 int strict)
456{
457 struct rt6_info *sibling, *next_sibling;
458
459 /* We might have already computed the hash for ICMPv6 errors. In such
460 * case it will always be non-zero. Otherwise now is the time to do it.
461 */
462 if (!fl6->mp_hash)
456 int strict)
457{
458 struct rt6_info *sibling, *next_sibling;
459
460 /* We might have already computed the hash for ICMPv6 errors. In such
461 * case it will always be non-zero. Otherwise now is the time to do it.
462 */
463 if (!fl6->mp_hash)
463 fl6->mp_hash = rt6_multipath_hash(fl6, NULL, NULL);
464 fl6->mp_hash = rt6_multipath_hash(fl6, skb, NULL);
464
465 if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
466 return match;
467
468 list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
469 rt6i_siblings) {
470 if (fl6->mp_hash > atomic_read(&sibling->rt6i_nh_upper_bound))
471 continue;

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

909 rt = NULL;
910 }
911 *prt = rt;
912 return false;
913}
914
915static struct rt6_info *ip6_pol_route_lookup(struct net *net,
916 struct fib6_table *table,
465
466 if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
467 return match;
468
469 list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
470 rt6i_siblings) {
471 if (fl6->mp_hash > atomic_read(&sibling->rt6i_nh_upper_bound))
472 continue;

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

910 rt = NULL;
911 }
912 *prt = rt;
913 return false;
914}
915
916static struct rt6_info *ip6_pol_route_lookup(struct net *net,
917 struct fib6_table *table,
917 struct flowi6 *fl6, int flags)
918 struct flowi6 *fl6,
919 const struct sk_buff *skb,
920 int flags)
918{
919 struct rt6_info *rt, *rt_cache;
920 struct fib6_node *fn;
921
922 rcu_read_lock();
923 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
924restart:
925 rt = rcu_dereference(fn->leaf);
926 if (!rt) {
927 rt = net->ipv6.ip6_null_entry;
928 } else {
929 rt = rt6_device_match(net, rt, &fl6->saddr,
930 fl6->flowi6_oif, flags);
931 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
921{
922 struct rt6_info *rt, *rt_cache;
923 struct fib6_node *fn;
924
925 rcu_read_lock();
926 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
927restart:
928 rt = rcu_dereference(fn->leaf);
929 if (!rt) {
930 rt = net->ipv6.ip6_null_entry;
931 } else {
932 rt = rt6_device_match(net, rt, &fl6->saddr,
933 fl6->flowi6_oif, flags);
934 if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
932 rt = rt6_multipath_select(rt, fl6,
933 fl6->flowi6_oif, flags);
935 rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif,
936 skb, flags);
934 }
935 if (rt == net->ipv6.ip6_null_entry) {
936 fn = fib6_backtrack(fn, &fl6->saddr);
937 if (fn)
938 goto restart;
939 }
940 /* Search through exception table */
941 rt_cache = rt6_find_cached_rt(rt, &fl6->daddr, &fl6->saddr);

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

949
950 trace_fib6_table_lookup(net, rt, table, fl6);
951
952 return rt;
953
954}
955
956struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
937 }
938 if (rt == net->ipv6.ip6_null_entry) {
939 fn = fib6_backtrack(fn, &fl6->saddr);
940 if (fn)
941 goto restart;
942 }
943 /* Search through exception table */
944 rt_cache = rt6_find_cached_rt(rt, &fl6->daddr, &fl6->saddr);

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

952
953 trace_fib6_table_lookup(net, rt, table, fl6);
954
955 return rt;
956
957}
958
959struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
957 int flags)
960 const struct sk_buff *skb, int flags)
958{
961{
959 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
962 return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_lookup);
960}
961EXPORT_SYMBOL_GPL(ip6_route_lookup);
962
963struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
963}
964EXPORT_SYMBOL_GPL(ip6_route_lookup);
965
966struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
964 const struct in6_addr *saddr, int oif, int strict)
967 const struct in6_addr *saddr, int oif,
968 const struct sk_buff *skb, int strict)
965{
966 struct flowi6 fl6 = {
967 .flowi6_oif = oif,
968 .daddr = *daddr,
969 };
970 struct dst_entry *dst;
971 int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
972
973 if (saddr) {
974 memcpy(&fl6.saddr, saddr, sizeof(*saddr));
975 flags |= RT6_LOOKUP_F_HAS_SADDR;
976 }
977
969{
970 struct flowi6 fl6 = {
971 .flowi6_oif = oif,
972 .daddr = *daddr,
973 };
974 struct dst_entry *dst;
975 int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
976
977 if (saddr) {
978 memcpy(&fl6.saddr, saddr, sizeof(*saddr));
979 flags |= RT6_LOOKUP_F_HAS_SADDR;
980 }
981
978 dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
982 dst = fib6_rule_lookup(net, &fl6, skb, flags, ip6_pol_route_lookup);
979 if (dst->error == 0)
980 return (struct rt6_info *) dst;
981
982 dst_release(dst);
983
984 return NULL;
985}
986EXPORT_SYMBOL(rt6_lookup);

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

1642 }
1643 bucket++;
1644 }
1645 }
1646 spin_unlock_bh(&rt6_exception_lock);
1647}
1648
1649struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
983 if (dst->error == 0)
984 return (struct rt6_info *) dst;
985
986 dst_release(dst);
987
988 return NULL;
989}
990EXPORT_SYMBOL(rt6_lookup);

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

1646 }
1647 bucket++;
1648 }
1649 }
1650 spin_unlock_bh(&rt6_exception_lock);
1651}
1652
1653struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
1650 int oif, struct flowi6 *fl6, int flags)
1654 int oif, struct flowi6 *fl6,
1655 const struct sk_buff *skb, int flags)
1651{
1652 struct fib6_node *fn, *saved_fn;
1653 struct rt6_info *rt, *rt_cache;
1654 int strict = 0;
1655
1656 strict |= flags & RT6_LOOKUP_F_IFACE;
1657 strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
1658 if (net->ipv6.devconf_all->forwarding == 0)

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

1664 saved_fn = fn;
1665
1666 if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
1667 oif = 0;
1668
1669redo_rt6_select:
1670 rt = rt6_select(net, fn, oif, strict);
1671 if (rt->rt6i_nsiblings)
1656{
1657 struct fib6_node *fn, *saved_fn;
1658 struct rt6_info *rt, *rt_cache;
1659 int strict = 0;
1660
1661 strict |= flags & RT6_LOOKUP_F_IFACE;
1662 strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
1663 if (net->ipv6.devconf_all->forwarding == 0)

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

1669 saved_fn = fn;
1670
1671 if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
1672 oif = 0;
1673
1674redo_rt6_select:
1675 rt = rt6_select(net, fn, oif, strict);
1676 if (rt->rt6i_nsiblings)
1672 rt = rt6_multipath_select(rt, fl6, oif, strict);
1677 rt = rt6_multipath_select(rt, fl6, oif, skb, strict);
1673 if (rt == net->ipv6.ip6_null_entry) {
1674 fn = fib6_backtrack(fn, &fl6->saddr);
1675 if (fn)
1676 goto redo_rt6_select;
1677 else if (strict & RT6_LOOKUP_F_REACHABLE) {
1678 /* also consider unreachable route */
1679 strict &= ~RT6_LOOKUP_F_REACHABLE;
1680 fn = saved_fn;

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

1763 local_bh_enable();
1764 rcu_read_unlock();
1765 trace_fib6_table_lookup(net, pcpu_rt, table, fl6);
1766 return pcpu_rt;
1767 }
1768}
1769EXPORT_SYMBOL_GPL(ip6_pol_route);
1770
1678 if (rt == net->ipv6.ip6_null_entry) {
1679 fn = fib6_backtrack(fn, &fl6->saddr);
1680 if (fn)
1681 goto redo_rt6_select;
1682 else if (strict & RT6_LOOKUP_F_REACHABLE) {
1683 /* also consider unreachable route */
1684 strict &= ~RT6_LOOKUP_F_REACHABLE;
1685 fn = saved_fn;

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

1768 local_bh_enable();
1769 rcu_read_unlock();
1770 trace_fib6_table_lookup(net, pcpu_rt, table, fl6);
1771 return pcpu_rt;
1772 }
1773}
1774EXPORT_SYMBOL_GPL(ip6_pol_route);
1775
1771static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
1772 struct flowi6 *fl6, int flags)
1776static struct rt6_info *ip6_pol_route_input(struct net *net,
1777 struct fib6_table *table,
1778 struct flowi6 *fl6,
1779 const struct sk_buff *skb,
1780 int flags)
1773{
1781{
1774 return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
1782 return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, skb, flags);
1775}
1776
1777struct dst_entry *ip6_route_input_lookup(struct net *net,
1778 struct net_device *dev,
1783}
1784
1785struct dst_entry *ip6_route_input_lookup(struct net *net,
1786 struct net_device *dev,
1779 struct flowi6 *fl6, int flags)
1787 struct flowi6 *fl6,
1788 const struct sk_buff *skb,
1789 int flags)
1780{
1781 if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
1782 flags |= RT6_LOOKUP_F_IFACE;
1783
1790{
1791 if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
1792 flags |= RT6_LOOKUP_F_IFACE;
1793
1784 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
1794 return fib6_rule_lookup(net, fl6, skb, flags, ip6_pol_route_input);
1785}
1786EXPORT_SYMBOL_GPL(ip6_route_input_lookup);
1787
1788static void ip6_multipath_l3_keys(const struct sk_buff *skb,
1789 struct flow_keys *keys,
1790 struct flow_keys *flkeys)
1791{
1792 const struct ipv6hdr *outer_iph = ipv6_hdr(skb);

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

1871 fl6.flowi6_tun_key.tun_id = tun_info->key.tun_id;
1872
1873 if (fib6_rules_early_flow_dissect(net, skb, &fl6, &_flkeys))
1874 flkeys = &_flkeys;
1875
1876 if (unlikely(fl6.flowi6_proto == IPPROTO_ICMPV6))
1877 fl6.mp_hash = rt6_multipath_hash(&fl6, skb, flkeys);
1878 skb_dst_drop(skb);
1795}
1796EXPORT_SYMBOL_GPL(ip6_route_input_lookup);
1797
1798static void ip6_multipath_l3_keys(const struct sk_buff *skb,
1799 struct flow_keys *keys,
1800 struct flow_keys *flkeys)
1801{
1802 const struct ipv6hdr *outer_iph = ipv6_hdr(skb);

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

1881 fl6.flowi6_tun_key.tun_id = tun_info->key.tun_id;
1882
1883 if (fib6_rules_early_flow_dissect(net, skb, &fl6, &_flkeys))
1884 flkeys = &_flkeys;
1885
1886 if (unlikely(fl6.flowi6_proto == IPPROTO_ICMPV6))
1887 fl6.mp_hash = rt6_multipath_hash(&fl6, skb, flkeys);
1888 skb_dst_drop(skb);
1879 skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
1889 skb_dst_set(skb,
1890 ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags));
1880}
1881
1891}
1892
1882static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
1883 struct flowi6 *fl6, int flags)
1893static struct rt6_info *ip6_pol_route_output(struct net *net,
1894 struct fib6_table *table,
1895 struct flowi6 *fl6,
1896 const struct sk_buff *skb,
1897 int flags)
1884{
1898{
1885 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
1899 return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, skb, flags);
1886}
1887
1888struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
1889 struct flowi6 *fl6, int flags)
1890{
1891 bool any_src;
1892
1893 if (rt6_need_strict(&fl6->daddr)) {

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

1905 (fl6->flowi6_oif && any_src))
1906 flags |= RT6_LOOKUP_F_IFACE;
1907
1908 if (!any_src)
1909 flags |= RT6_LOOKUP_F_HAS_SADDR;
1910 else if (sk)
1911 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
1912
1900}
1901
1902struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
1903 struct flowi6 *fl6, int flags)
1904{
1905 bool any_src;
1906
1907 if (rt6_need_strict(&fl6->daddr)) {

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

1919 (fl6->flowi6_oif && any_src))
1920 flags |= RT6_LOOKUP_F_IFACE;
1921
1922 if (!any_src)
1923 flags |= RT6_LOOKUP_F_HAS_SADDR;
1924 else if (sk)
1925 flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
1926
1913 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
1927 return fib6_rule_lookup(net, fl6, NULL, flags, ip6_pol_route_output);
1914}
1915EXPORT_SYMBOL_GPL(ip6_route_output_flags);
1916
1917struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
1918{
1919 struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
1920 struct net_device *loopback_dev = net->loopback_dev;
1921 struct dst_entry *new = NULL;

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

2154struct ip6rd_flowi {
2155 struct flowi6 fl6;
2156 struct in6_addr gateway;
2157};
2158
2159static struct rt6_info *__ip6_route_redirect(struct net *net,
2160 struct fib6_table *table,
2161 struct flowi6 *fl6,
1928}
1929EXPORT_SYMBOL_GPL(ip6_route_output_flags);
1930
1931struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
1932{
1933 struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
1934 struct net_device *loopback_dev = net->loopback_dev;
1935 struct dst_entry *new = NULL;

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

2168struct ip6rd_flowi {
2169 struct flowi6 fl6;
2170 struct in6_addr gateway;
2171};
2172
2173static struct rt6_info *__ip6_route_redirect(struct net *net,
2174 struct fib6_table *table,
2175 struct flowi6 *fl6,
2176 const struct sk_buff *skb,
2162 int flags)
2163{
2164 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
2165 struct rt6_info *rt, *rt_cache;
2166 struct fib6_node *fn;
2167
2168 /* Get the "current" route for this destination and
2169 * check if the redirect has come from appropriate router.

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

2227
2228 rcu_read_unlock();
2229
2230 trace_fib6_table_lookup(net, rt, table, fl6);
2231 return rt;
2232};
2233
2234static struct dst_entry *ip6_route_redirect(struct net *net,
2177 int flags)
2178{
2179 struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
2180 struct rt6_info *rt, *rt_cache;
2181 struct fib6_node *fn;
2182
2183 /* Get the "current" route for this destination and
2184 * check if the redirect has come from appropriate router.

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

2242
2243 rcu_read_unlock();
2244
2245 trace_fib6_table_lookup(net, rt, table, fl6);
2246 return rt;
2247};
2248
2249static struct dst_entry *ip6_route_redirect(struct net *net,
2235 const struct flowi6 *fl6,
2236 const struct in6_addr *gateway)
2250 const struct flowi6 *fl6,
2251 const struct sk_buff *skb,
2252 const struct in6_addr *gateway)
2237{
2238 int flags = RT6_LOOKUP_F_HAS_SADDR;
2239 struct ip6rd_flowi rdfl;
2240
2241 rdfl.fl6 = *fl6;
2242 rdfl.gateway = *gateway;
2243
2253{
2254 int flags = RT6_LOOKUP_F_HAS_SADDR;
2255 struct ip6rd_flowi rdfl;
2256
2257 rdfl.fl6 = *fl6;
2258 rdfl.gateway = *gateway;
2259
2244 return fib6_rule_lookup(net, &rdfl.fl6,
2260 return fib6_rule_lookup(net, &rdfl.fl6, skb,
2245 flags, __ip6_route_redirect);
2246}
2247
2248void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
2249 kuid_t uid)
2250{
2251 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
2252 struct dst_entry *dst;
2253 struct flowi6 fl6;
2254
2255 memset(&fl6, 0, sizeof(fl6));
2256 fl6.flowi6_iif = LOOPBACK_IFINDEX;
2257 fl6.flowi6_oif = oif;
2258 fl6.flowi6_mark = mark;
2259 fl6.daddr = iph->daddr;
2260 fl6.saddr = iph->saddr;
2261 fl6.flowlabel = ip6_flowinfo(iph);
2262 fl6.flowi6_uid = uid;
2263
2261 flags, __ip6_route_redirect);
2262}
2263
2264void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
2265 kuid_t uid)
2266{
2267 const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
2268 struct dst_entry *dst;
2269 struct flowi6 fl6;
2270
2271 memset(&fl6, 0, sizeof(fl6));
2272 fl6.flowi6_iif = LOOPBACK_IFINDEX;
2273 fl6.flowi6_oif = oif;
2274 fl6.flowi6_mark = mark;
2275 fl6.daddr = iph->daddr;
2276 fl6.saddr = iph->saddr;
2277 fl6.flowlabel = ip6_flowinfo(iph);
2278 fl6.flowi6_uid = uid;
2279
2264 dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
2280 dst = ip6_route_redirect(net, &fl6, skb, &ipv6_hdr(skb)->saddr);
2265 rt6_do_redirect(dst, NULL, skb);
2266 dst_release(dst);
2267}
2268EXPORT_SYMBOL_GPL(ip6_redirect);
2269
2270void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
2271 u32 mark)
2272{

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

2278 memset(&fl6, 0, sizeof(fl6));
2279 fl6.flowi6_iif = LOOPBACK_IFINDEX;
2280 fl6.flowi6_oif = oif;
2281 fl6.flowi6_mark = mark;
2282 fl6.daddr = msg->dest;
2283 fl6.saddr = iph->daddr;
2284 fl6.flowi6_uid = sock_net_uid(net, NULL);
2285
2281 rt6_do_redirect(dst, NULL, skb);
2282 dst_release(dst);
2283}
2284EXPORT_SYMBOL_GPL(ip6_redirect);
2285
2286void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
2287 u32 mark)
2288{

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

2294 memset(&fl6, 0, sizeof(fl6));
2295 fl6.flowi6_iif = LOOPBACK_IFINDEX;
2296 fl6.flowi6_oif = oif;
2297 fl6.flowi6_mark = mark;
2298 fl6.daddr = msg->dest;
2299 fl6.saddr = iph->daddr;
2300 fl6.flowi6_uid = sock_net_uid(net, NULL);
2301
2286 dst = ip6_route_redirect(net, &fl6, &iph->saddr);
2302 dst = ip6_route_redirect(net, &fl6, skb, &iph->saddr);
2287 rt6_do_redirect(dst, NULL, skb);
2288 dst_release(dst);
2289}
2290
2291void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
2292{
2293 ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
2294 sk->sk_uid);

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

2480 table = fib6_get_table(net, tbid);
2481 if (!table)
2482 return NULL;
2483
2484 if (!ipv6_addr_any(&cfg->fc_prefsrc))
2485 flags |= RT6_LOOKUP_F_HAS_SADDR;
2486
2487 flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE;
2303 rt6_do_redirect(dst, NULL, skb);
2304 dst_release(dst);
2305}
2306
2307void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
2308{
2309 ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
2310 sk->sk_uid);

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

2496 table = fib6_get_table(net, tbid);
2497 if (!table)
2498 return NULL;
2499
2500 if (!ipv6_addr_any(&cfg->fc_prefsrc))
2501 flags |= RT6_LOOKUP_F_HAS_SADDR;
2502
2503 flags |= RT6_LOOKUP_F_IGNORE_LINKSTATE;
2488 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags);
2504 rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, NULL, flags);
2489
2490 /* if table lookup failed, fall back to full lookup */
2491 if (rt == net->ipv6.ip6_null_entry) {
2492 ip6_rt_put(rt);
2493 rt = NULL;
2494 }
2495
2496 return rt;

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

2543 (dev && dev != grt->dst.dev)) {
2544 ip6_rt_put(grt);
2545 grt = NULL;
2546 }
2547 }
2548 }
2549
2550 if (!grt)
2505
2506 /* if table lookup failed, fall back to full lookup */
2507 if (rt == net->ipv6.ip6_null_entry) {
2508 ip6_rt_put(rt);
2509 rt = NULL;
2510 }
2511
2512 return rt;

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

2559 (dev && dev != grt->dst.dev)) {
2560 ip6_rt_put(grt);
2561 grt = NULL;
2562 }
2563 }
2564 }
2565
2566 if (!grt)
2551 grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
2567 grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, NULL, 1);
2552
2553 if (!grt)
2554 goto out;
2555
2556 if (dev) {
2557 if (dev != grt->dst.dev) {
2558 ip6_rt_put(grt);
2559 goto out;

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

4608 goto errout;
4609 }
4610
4611 fl6.flowi6_iif = iif;
4612
4613 if (!ipv6_addr_any(&fl6.saddr))
4614 flags |= RT6_LOOKUP_F_HAS_SADDR;
4615
2568
2569 if (!grt)
2570 goto out;
2571
2572 if (dev) {
2573 if (dev != grt->dst.dev) {
2574 ip6_rt_put(grt);
2575 goto out;

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

4624 goto errout;
4625 }
4626
4627 fl6.flowi6_iif = iif;
4628
4629 if (!ipv6_addr_any(&fl6.saddr))
4630 flags |= RT6_LOOKUP_F_HAS_SADDR;
4631
4616 dst = ip6_route_input_lookup(net, dev, &fl6, flags);
4632 dst = ip6_route_input_lookup(net, dev, &fl6, NULL, flags);
4617
4618 rcu_read_unlock();
4619 } else {
4620 fl6.flowi6_oif = oif;
4621
4622 dst = ip6_route_output(net, NULL, &fl6);
4623 }
4624

--- 531 unchanged lines hidden ---
4633
4634 rcu_read_unlock();
4635 } else {
4636 fl6.flowi6_oif = oif;
4637
4638 dst = ip6_route_output(net, NULL, &fl6);
4639 }
4640

--- 531 unchanged lines hidden ---