| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * INET An implementation of the TCP/IP protocol suite for the LINUX |
|---|
| 3 | 4 | * operating system. INET is implemented using the BSD Socket |
|---|
| .. | .. |
|---|
| 15 | 16 | * Alexey Kuznetsov: Major changes for new routing code. |
|---|
| 16 | 17 | * Mike McLagan : Routing by source |
|---|
| 17 | 18 | * Robert Olsson : Added rt_cache statistics |
|---|
| 18 | | - * |
|---|
| 19 | | - * This program is free software; you can redistribute it and/or |
|---|
| 20 | | - * modify it under the terms of the GNU General Public License |
|---|
| 21 | | - * as published by the Free Software Foundation; either version |
|---|
| 22 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 23 | 19 | */ |
|---|
| 24 | 20 | #ifndef _ROUTE_H |
|---|
| 25 | 21 | #define _ROUTE_H |
|---|
| .. | .. |
|---|
| 29 | 25 | #include <net/flow.h> |
|---|
| 30 | 26 | #include <net/inet_sock.h> |
|---|
| 31 | 27 | #include <net/ip_fib.h> |
|---|
| 28 | +#include <net/arp.h> |
|---|
| 29 | +#include <net/ndisc.h> |
|---|
| 32 | 30 | #include <linux/in_route.h> |
|---|
| 33 | 31 | #include <linux/rtnetlink.h> |
|---|
| 34 | 32 | #include <linux/rcupdate.h> |
|---|
| .. | .. |
|---|
| 59 | 57 | |
|---|
| 60 | 58 | int rt_iif; |
|---|
| 61 | 59 | |
|---|
| 60 | + u8 rt_gw_family; |
|---|
| 62 | 61 | /* Info on neighbour */ |
|---|
| 63 | | - __be32 rt_gateway; |
|---|
| 62 | + union { |
|---|
| 63 | + __be32 rt_gw4; |
|---|
| 64 | + struct in6_addr rt_gw6; |
|---|
| 65 | + }; |
|---|
| 64 | 66 | |
|---|
| 65 | 67 | /* Miscellaneous cached information */ |
|---|
| 66 | 68 | u32 rt_mtu_locked:1, |
|---|
| .. | .. |
|---|
| 82 | 84 | |
|---|
| 83 | 85 | static inline __be32 rt_nexthop(const struct rtable *rt, __be32 daddr) |
|---|
| 84 | 86 | { |
|---|
| 85 | | - if (rt->rt_gateway) |
|---|
| 86 | | - return rt->rt_gateway; |
|---|
| 87 | + if (rt->rt_gw_family == AF_INET) |
|---|
| 88 | + return rt->rt_gw4; |
|---|
| 87 | 89 | return daddr; |
|---|
| 88 | 90 | } |
|---|
| 89 | 91 | |
|---|
| .. | .. |
|---|
| 126 | 128 | |
|---|
| 127 | 129 | struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, |
|---|
| 128 | 130 | const struct sock *sk); |
|---|
| 131 | +struct rtable *ip_route_output_tunnel(struct sk_buff *skb, |
|---|
| 132 | + struct net_device *dev, |
|---|
| 133 | + struct net *net, __be32 *saddr, |
|---|
| 134 | + const struct ip_tunnel_info *info, |
|---|
| 135 | + u8 protocol, bool use_cache); |
|---|
| 136 | + |
|---|
| 129 | 137 | struct dst_entry *ipv4_blackhole_route(struct net *net, |
|---|
| 130 | 138 | struct dst_entry *dst_orig); |
|---|
| 131 | 139 | |
|---|
| .. | .. |
|---|
| 157 | 165 | sk ? inet_sk_flowi_flags(sk) : 0, |
|---|
| 158 | 166 | daddr, saddr, dport, sport, sock_net_uid(net, sk)); |
|---|
| 159 | 167 | if (sk) |
|---|
| 160 | | - security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
|---|
| 168 | + security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); |
|---|
| 161 | 169 | return ip_route_output_flow(net, fl4, sk); |
|---|
| 162 | 170 | } |
|---|
| 163 | 171 | |
|---|
| .. | .. |
|---|
| 183 | 191 | u8 tos, struct net_device *devin, |
|---|
| 184 | 192 | struct fib_result *res); |
|---|
| 185 | 193 | |
|---|
| 194 | +int ip_route_use_hint(struct sk_buff *skb, __be32 dst, __be32 src, |
|---|
| 195 | + u8 tos, struct net_device *devin, |
|---|
| 196 | + const struct sk_buff *hint); |
|---|
| 197 | + |
|---|
| 186 | 198 | static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, |
|---|
| 187 | 199 | u8 tos, struct net_device *devin) |
|---|
| 188 | 200 | { |
|---|
| .. | .. |
|---|
| 201 | 213 | } |
|---|
| 202 | 214 | |
|---|
| 203 | 215 | void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, int oif, |
|---|
| 204 | | - u32 mark, u8 protocol, int flow_flags); |
|---|
| 216 | + u8 protocol); |
|---|
| 205 | 217 | void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); |
|---|
| 206 | | -void ipv4_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, |
|---|
| 207 | | - u8 protocol, int flow_flags); |
|---|
| 218 | +void ipv4_redirect(struct sk_buff *skb, struct net *net, int oif, u8 protocol); |
|---|
| 208 | 219 | void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk); |
|---|
| 209 | 220 | void ip_rt_send_redirect(struct sk_buff *skb); |
|---|
| 210 | 221 | |
|---|
| .. | .. |
|---|
| 220 | 231 | void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); |
|---|
| 221 | 232 | struct rtable *rt_dst_alloc(struct net_device *dev, |
|---|
| 222 | 233 | unsigned int flags, u16 type, |
|---|
| 223 | | - bool nopolicy, bool noxfrm, bool will_cache); |
|---|
| 234 | + bool nopolicy, bool noxfrm); |
|---|
| 235 | +struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt); |
|---|
| 224 | 236 | |
|---|
| 225 | 237 | struct in_ifaddr; |
|---|
| 226 | 238 | void fib_add_ifaddr(struct in_ifaddr *); |
|---|
| .. | .. |
|---|
| 229 | 241 | |
|---|
| 230 | 242 | void rt_add_uncached_list(struct rtable *rt); |
|---|
| 231 | 243 | void rt_del_uncached_list(struct rtable *rt); |
|---|
| 244 | + |
|---|
| 245 | +int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb, |
|---|
| 246 | + u32 table_id, struct fib_info *fi, |
|---|
| 247 | + int *fa_index, int fa_start, unsigned int flags); |
|---|
| 232 | 248 | |
|---|
| 233 | 249 | static inline void ip_rt_put(struct rtable *rt) |
|---|
| 234 | 250 | { |
|---|
| .. | .. |
|---|
| 306 | 322 | ip_rt_put(rt); |
|---|
| 307 | 323 | flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr); |
|---|
| 308 | 324 | } |
|---|
| 309 | | - security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
|---|
| 325 | + security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); |
|---|
| 310 | 326 | return ip_route_output_flow(net, fl4, sk); |
|---|
| 311 | 327 | } |
|---|
| 312 | 328 | |
|---|
| .. | .. |
|---|
| 322 | 338 | flowi4_update_output(fl4, sk->sk_bound_dev_if, |
|---|
| 323 | 339 | RT_CONN_FLAGS(sk), fl4->daddr, |
|---|
| 324 | 340 | fl4->saddr); |
|---|
| 325 | | - security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
|---|
| 341 | + security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); |
|---|
| 326 | 342 | return ip_route_output_flow(sock_net(sk), fl4, sk); |
|---|
| 327 | 343 | } |
|---|
| 328 | 344 | return rt; |
|---|
| .. | .. |
|---|
| 348 | 364 | return hoplimit; |
|---|
| 349 | 365 | } |
|---|
| 350 | 366 | |
|---|
| 367 | +static inline struct neighbour *ip_neigh_gw4(struct net_device *dev, |
|---|
| 368 | + __be32 daddr) |
|---|
| 369 | +{ |
|---|
| 370 | + struct neighbour *neigh; |
|---|
| 371 | + |
|---|
| 372 | + neigh = __ipv4_neigh_lookup_noref(dev, (__force u32)daddr); |
|---|
| 373 | + if (unlikely(!neigh)) |
|---|
| 374 | + neigh = __neigh_create(&arp_tbl, &daddr, dev, false); |
|---|
| 375 | + |
|---|
| 376 | + return neigh; |
|---|
| 377 | +} |
|---|
| 378 | + |
|---|
| 379 | +static inline struct neighbour *ip_neigh_for_gw(struct rtable *rt, |
|---|
| 380 | + struct sk_buff *skb, |
|---|
| 381 | + bool *is_v6gw) |
|---|
| 382 | +{ |
|---|
| 383 | + struct net_device *dev = rt->dst.dev; |
|---|
| 384 | + struct neighbour *neigh; |
|---|
| 385 | + |
|---|
| 386 | + if (likely(rt->rt_gw_family == AF_INET)) { |
|---|
| 387 | + neigh = ip_neigh_gw4(dev, rt->rt_gw4); |
|---|
| 388 | + } else if (rt->rt_gw_family == AF_INET6) { |
|---|
| 389 | + neigh = ip_neigh_gw6(dev, &rt->rt_gw6); |
|---|
| 390 | + *is_v6gw = true; |
|---|
| 391 | + } else { |
|---|
| 392 | + neigh = ip_neigh_gw4(dev, ip_hdr(skb)->daddr); |
|---|
| 393 | + } |
|---|
| 394 | + return neigh; |
|---|
| 395 | +} |
|---|
| 396 | + |
|---|
| 351 | 397 | #endif /* _ROUTE_H */ |
|---|