diff options
Diffstat (limited to 'include/net/route.h')
-rw-r--r-- | include/net/route.h | 164 |
1 files changed, 118 insertions, 46 deletions
diff --git a/include/net/route.h b/include/net/route.h index 93e10c453f6b..30d6cae3841a 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -49,36 +49,43 @@ struct fib_nh; struct inet_peer; +struct fib_info; struct rtable { struct dst_entry dst; - /* Cache lookup keys */ - struct flowi fl; + /* Lookup key. */ + __be32 rt_key_dst; + __be32 rt_key_src; int rt_genid; unsigned rt_flags; __u16 rt_type; + __u8 rt_tos; __be32 rt_dst; /* Path destination */ __be32 rt_src; /* Path source */ int rt_iif; + int rt_oif; + __u32 rt_mark; /* Info on neighbour */ __be32 rt_gateway; /* Miscellaneous cached information */ __be32 rt_spec_dst; /* RFC1122 specific destination */ + u32 rt_peer_genid; struct inet_peer *peer; /* long-living peer info */ + struct fib_info *fi; /* for client ref to shared metrics */ }; static inline bool rt_is_input_route(struct rtable *rt) { - return rt->fl.iif != 0; + return rt->rt_iif != 0; } static inline bool rt_is_output_route(struct rtable *rt) { - return rt->fl.iif == 0; + return rt->rt_iif == 0; } struct ip_rt_acct { @@ -115,9 +122,63 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, __be32 src, struct net_device *dev); extern void rt_cache_flush(struct net *net, int how); extern void rt_cache_flush_batch(struct net *net); -extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); -extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); -extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); +extern struct rtable *__ip_route_output_key(struct net *, const struct flowi4 *flp); +extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, + struct sock *sk); +extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); + +static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp) +{ + return ip_route_output_flow(net, flp, NULL); +} + +static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, + __be32 saddr, u8 tos, int oif) +{ + struct flowi4 fl4 = { + .flowi4_oif = oif, + .daddr = daddr, + .saddr = saddr, + .flowi4_tos = tos, + }; + return ip_route_output_key(net, &fl4); +} + +static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk, + __be32 daddr, __be32 saddr, + __be16 dport, __be16 sport, + __u8 proto, __u8 tos, int oif) +{ + struct flowi4 fl4 = { + .flowi4_oif = oif, + .flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0, + .flowi4_mark = sk ? sk->sk_mark : 0, + .daddr = daddr, + .saddr = saddr, + .flowi4_tos = tos, + .flowi4_proto = proto, + .fl4_dport = dport, + .fl4_sport = sport, + }; + if (sk) + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); + return ip_route_output_flow(net, &fl4, sk); +} + +static inline struct rtable *ip_route_output_gre(struct net *net, + __be32 daddr, __be32 saddr, + __be32 gre_key, __u8 tos, int oif) +{ + struct flowi4 fl4 = { + .flowi4_oif = oif, + .daddr = daddr, + .saddr = saddr, + .flowi4_tos = tos, + .flowi4_proto = IPPROTO_GRE, + .fl4_gre_key = gre_key, + }; + return ip_route_output_key(net, &fl4); +} extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, u8 tos, struct net_device *devin, bool noref); @@ -162,57 +223,68 @@ static inline char rt_tos2priority(u8 tos) return ip_tos2prio[IPTOS_TOS(tos)>>1]; } -static inline int ip_route_connect(struct rtable **rp, __be32 dst, - __be32 src, u32 tos, int oif, u8 protocol, - __be16 sport, __be16 dport, struct sock *sk, - int flags) +static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, + int oif, u8 protocol, + __be16 sport, __be16 dport, + struct sock *sk, bool can_sleep) { - struct flowi fl = { .oif = oif, - .mark = sk->sk_mark, - .fl4_dst = dst, - .fl4_src = src, - .fl4_tos = tos, - .proto = protocol, - .fl_ip_sport = sport, - .fl_ip_dport = dport }; - int err; + struct flowi4 fl4 = { + .flowi4_oif = oif, + .flowi4_mark = sk->sk_mark, + .daddr = dst, + .saddr = src, + .flowi4_tos = tos, + .flowi4_proto = protocol, + .fl4_sport = sport, + .fl4_dport = dport, + }; struct net *net = sock_net(sk); + struct rtable *rt; if (inet_sk(sk)->transparent) - fl.flags |= FLOWI_FLAG_ANYSRC; + fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + if (protocol == IPPROTO_TCP) + fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; + if (can_sleep) + fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP; if (!dst || !src) { - err = __ip_route_output_key(net, rp, &fl); - if (err) - return err; - fl.fl4_dst = (*rp)->rt_dst; - fl.fl4_src = (*rp)->rt_src; - ip_rt_put(*rp); - *rp = NULL; + rt = __ip_route_output_key(net, &fl4); + if (IS_ERR(rt)) + return rt; + fl4.daddr = rt->rt_dst; + fl4.saddr = rt->rt_src; + ip_rt_put(rt); } - security_sk_classify_flow(sk, &fl); - return ip_route_output_flow(net, rp, &fl, sk, flags); + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); + return ip_route_output_flow(net, &fl4, sk); } -static inline int ip_route_newports(struct rtable **rp, u8 protocol, - __be16 sport, __be16 dport, struct sock *sk) +static inline struct rtable *ip_route_newports(struct rtable *rt, + u8 protocol, __be16 orig_sport, + __be16 orig_dport, __be16 sport, + __be16 dport, struct sock *sk) { - if (sport != (*rp)->fl.fl_ip_sport || - dport != (*rp)->fl.fl_ip_dport) { - struct flowi fl; - - memcpy(&fl, &(*rp)->fl, sizeof(fl)); - fl.fl_ip_sport = sport; - fl.fl_ip_dport = dport; - fl.proto = protocol; + if (sport != orig_sport || dport != orig_dport) { + struct flowi4 fl4 = { + .flowi4_oif = rt->rt_oif, + .flowi4_mark = rt->rt_mark, + .daddr = rt->rt_key_dst, + .saddr = rt->rt_key_src, + .flowi4_tos = rt->rt_tos, + .flowi4_proto = protocol, + .fl4_sport = sport, + .fl4_dport = dport + }; if (inet_sk(sk)->transparent) - fl.flags |= FLOWI_FLAG_ANYSRC; - ip_rt_put(*rp); - *rp = NULL; - security_sk_classify_flow(sk, &fl); - return ip_route_output_flow(sock_net(sk), rp, &fl, sk, 0); + fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; + if (protocol == IPPROTO_TCP) + fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; + ip_rt_put(rt); + security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); + return ip_route_output_flow(sock_net(sk), &fl4, sk); } - return 0; + return rt; } extern void rt_bind_peer(struct rtable *rt, int create); |