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 @@ | |||
| 49 | 49 | ||
| 50 | struct fib_nh; | 50 | struct fib_nh; |
| 51 | struct inet_peer; | 51 | struct inet_peer; |
| 52 | struct fib_info; | ||
| 52 | struct rtable { | 53 | struct rtable { |
| 53 | struct dst_entry dst; | 54 | struct dst_entry dst; |
| 54 | 55 | ||
| 55 | /* Cache lookup keys */ | 56 | /* Lookup key. */ |
| 56 | struct flowi fl; | 57 | __be32 rt_key_dst; |
| 58 | __be32 rt_key_src; | ||
| 57 | 59 | ||
| 58 | int rt_genid; | 60 | int rt_genid; |
| 59 | unsigned rt_flags; | 61 | unsigned rt_flags; |
| 60 | __u16 rt_type; | 62 | __u16 rt_type; |
| 63 | __u8 rt_tos; | ||
| 61 | 64 | ||
| 62 | __be32 rt_dst; /* Path destination */ | 65 | __be32 rt_dst; /* Path destination */ |
| 63 | __be32 rt_src; /* Path source */ | 66 | __be32 rt_src; /* Path source */ |
| 64 | int rt_iif; | 67 | int rt_iif; |
| 68 | int rt_oif; | ||
| 69 | __u32 rt_mark; | ||
| 65 | 70 | ||
| 66 | /* Info on neighbour */ | 71 | /* Info on neighbour */ |
| 67 | __be32 rt_gateway; | 72 | __be32 rt_gateway; |
| 68 | 73 | ||
| 69 | /* Miscellaneous cached information */ | 74 | /* Miscellaneous cached information */ |
| 70 | __be32 rt_spec_dst; /* RFC1122 specific destination */ | 75 | __be32 rt_spec_dst; /* RFC1122 specific destination */ |
| 76 | u32 rt_peer_genid; | ||
| 71 | struct inet_peer *peer; /* long-living peer info */ | 77 | struct inet_peer *peer; /* long-living peer info */ |
| 78 | struct fib_info *fi; /* for client ref to shared metrics */ | ||
| 72 | }; | 79 | }; |
| 73 | 80 | ||
| 74 | static inline bool rt_is_input_route(struct rtable *rt) | 81 | static inline bool rt_is_input_route(struct rtable *rt) |
| 75 | { | 82 | { |
| 76 | return rt->fl.iif != 0; | 83 | return rt->rt_iif != 0; |
| 77 | } | 84 | } |
| 78 | 85 | ||
| 79 | static inline bool rt_is_output_route(struct rtable *rt) | 86 | static inline bool rt_is_output_route(struct rtable *rt) |
| 80 | { | 87 | { |
| 81 | return rt->fl.iif == 0; | 88 | return rt->rt_iif == 0; |
| 82 | } | 89 | } |
| 83 | 90 | ||
| 84 | struct ip_rt_acct { | 91 | struct ip_rt_acct { |
| @@ -115,9 +122,63 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, | |||
| 115 | __be32 src, struct net_device *dev); | 122 | __be32 src, struct net_device *dev); |
| 116 | extern void rt_cache_flush(struct net *net, int how); | 123 | extern void rt_cache_flush(struct net *net, int how); |
| 117 | extern void rt_cache_flush_batch(struct net *net); | 124 | extern void rt_cache_flush_batch(struct net *net); |
| 118 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); | 125 | extern struct rtable *__ip_route_output_key(struct net *, const struct flowi4 *flp); |
| 119 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); | 126 | extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, |
| 120 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); | 127 | struct sock *sk); |
| 128 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); | ||
| 129 | |||
| 130 | static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp) | ||
| 131 | { | ||
| 132 | return ip_route_output_flow(net, flp, NULL); | ||
| 133 | } | ||
| 134 | |||
| 135 | static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, | ||
| 136 | __be32 saddr, u8 tos, int oif) | ||
| 137 | { | ||
| 138 | struct flowi4 fl4 = { | ||
| 139 | .flowi4_oif = oif, | ||
| 140 | .daddr = daddr, | ||
| 141 | .saddr = saddr, | ||
| 142 | .flowi4_tos = tos, | ||
| 143 | }; | ||
| 144 | return ip_route_output_key(net, &fl4); | ||
| 145 | } | ||
| 146 | |||
| 147 | static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk, | ||
| 148 | __be32 daddr, __be32 saddr, | ||
| 149 | __be16 dport, __be16 sport, | ||
| 150 | __u8 proto, __u8 tos, int oif) | ||
| 151 | { | ||
| 152 | struct flowi4 fl4 = { | ||
| 153 | .flowi4_oif = oif, | ||
| 154 | .flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0, | ||
| 155 | .flowi4_mark = sk ? sk->sk_mark : 0, | ||
| 156 | .daddr = daddr, | ||
| 157 | .saddr = saddr, | ||
| 158 | .flowi4_tos = tos, | ||
| 159 | .flowi4_proto = proto, | ||
| 160 | .fl4_dport = dport, | ||
| 161 | .fl4_sport = sport, | ||
| 162 | }; | ||
| 163 | if (sk) | ||
| 164 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | ||
| 165 | return ip_route_output_flow(net, &fl4, sk); | ||
| 166 | } | ||
| 167 | |||
| 168 | static inline struct rtable *ip_route_output_gre(struct net *net, | ||
| 169 | __be32 daddr, __be32 saddr, | ||
| 170 | __be32 gre_key, __u8 tos, int oif) | ||
| 171 | { | ||
| 172 | struct flowi4 fl4 = { | ||
| 173 | .flowi4_oif = oif, | ||
| 174 | .daddr = daddr, | ||
| 175 | .saddr = saddr, | ||
| 176 | .flowi4_tos = tos, | ||
| 177 | .flowi4_proto = IPPROTO_GRE, | ||
| 178 | .fl4_gre_key = gre_key, | ||
| 179 | }; | ||
| 180 | return ip_route_output_key(net, &fl4); | ||
| 181 | } | ||
| 121 | 182 | ||
| 122 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, | 183 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, |
| 123 | u8 tos, struct net_device *devin, bool noref); | 184 | u8 tos, struct net_device *devin, bool noref); |
| @@ -162,57 +223,68 @@ static inline char rt_tos2priority(u8 tos) | |||
| 162 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; | 223 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; |
| 163 | } | 224 | } |
| 164 | 225 | ||
| 165 | static inline int ip_route_connect(struct rtable **rp, __be32 dst, | 226 | static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, |
| 166 | __be32 src, u32 tos, int oif, u8 protocol, | 227 | int oif, u8 protocol, |
| 167 | __be16 sport, __be16 dport, struct sock *sk, | 228 | __be16 sport, __be16 dport, |
| 168 | int flags) | 229 | struct sock *sk, bool can_sleep) |
| 169 | { | 230 | { |
| 170 | struct flowi fl = { .oif = oif, | 231 | struct flowi4 fl4 = { |
| 171 | .mark = sk->sk_mark, | 232 | .flowi4_oif = oif, |
| 172 | .fl4_dst = dst, | 233 | .flowi4_mark = sk->sk_mark, |
| 173 | .fl4_src = src, | 234 | .daddr = dst, |
| 174 | .fl4_tos = tos, | 235 | .saddr = src, |
| 175 | .proto = protocol, | 236 | .flowi4_tos = tos, |
| 176 | .fl_ip_sport = sport, | 237 | .flowi4_proto = protocol, |
| 177 | .fl_ip_dport = dport }; | 238 | .fl4_sport = sport, |
| 178 | int err; | 239 | .fl4_dport = dport, |
| 240 | }; | ||
| 179 | struct net *net = sock_net(sk); | 241 | struct net *net = sock_net(sk); |
| 242 | struct rtable *rt; | ||
| 180 | 243 | ||
| 181 | if (inet_sk(sk)->transparent) | 244 | if (inet_sk(sk)->transparent) |
| 182 | fl.flags |= FLOWI_FLAG_ANYSRC; | 245 | fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; |
| 246 | if (protocol == IPPROTO_TCP) | ||
| 247 | fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; | ||
| 248 | if (can_sleep) | ||
| 249 | fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
| 183 | 250 | ||
| 184 | if (!dst || !src) { | 251 | if (!dst || !src) { |
| 185 | err = __ip_route_output_key(net, rp, &fl); | 252 | rt = __ip_route_output_key(net, &fl4); |
| 186 | if (err) | 253 | if (IS_ERR(rt)) |
| 187 | return err; | 254 | return rt; |
| 188 | fl.fl4_dst = (*rp)->rt_dst; | 255 | fl4.daddr = rt->rt_dst; |
| 189 | fl.fl4_src = (*rp)->rt_src; | 256 | fl4.saddr = rt->rt_src; |
| 190 | ip_rt_put(*rp); | 257 | ip_rt_put(rt); |
| 191 | *rp = NULL; | ||
| 192 | } | 258 | } |
| 193 | security_sk_classify_flow(sk, &fl); | 259 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); |
| 194 | return ip_route_output_flow(net, rp, &fl, sk, flags); | 260 | return ip_route_output_flow(net, &fl4, sk); |
| 195 | } | 261 | } |
| 196 | 262 | ||
| 197 | static inline int ip_route_newports(struct rtable **rp, u8 protocol, | 263 | static inline struct rtable *ip_route_newports(struct rtable *rt, |
| 198 | __be16 sport, __be16 dport, struct sock *sk) | 264 | u8 protocol, __be16 orig_sport, |
| 265 | __be16 orig_dport, __be16 sport, | ||
| 266 | __be16 dport, struct sock *sk) | ||
| 199 | { | 267 | { |
| 200 | if (sport != (*rp)->fl.fl_ip_sport || | 268 | if (sport != orig_sport || dport != orig_dport) { |
| 201 | dport != (*rp)->fl.fl_ip_dport) { | 269 | struct flowi4 fl4 = { |
| 202 | struct flowi fl; | 270 | .flowi4_oif = rt->rt_oif, |
| 203 | 271 | .flowi4_mark = rt->rt_mark, | |
| 204 | memcpy(&fl, &(*rp)->fl, sizeof(fl)); | 272 | .daddr = rt->rt_key_dst, |
| 205 | fl.fl_ip_sport = sport; | 273 | .saddr = rt->rt_key_src, |
| 206 | fl.fl_ip_dport = dport; | 274 | .flowi4_tos = rt->rt_tos, |
| 207 | fl.proto = protocol; | 275 | .flowi4_proto = protocol, |
| 276 | .fl4_sport = sport, | ||
| 277 | .fl4_dport = dport | ||
| 278 | }; | ||
| 208 | if (inet_sk(sk)->transparent) | 279 | if (inet_sk(sk)->transparent) |
| 209 | fl.flags |= FLOWI_FLAG_ANYSRC; | 280 | fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; |
| 210 | ip_rt_put(*rp); | 281 | if (protocol == IPPROTO_TCP) |
| 211 | *rp = NULL; | 282 | fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; |
| 212 | security_sk_classify_flow(sk, &fl); | 283 | ip_rt_put(rt); |
| 213 | return ip_route_output_flow(sock_net(sk), rp, &fl, sk, 0); | 284 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); |
| 285 | return ip_route_output_flow(sock_net(sk), &fl4, sk); | ||
| 214 | } | 286 | } |
| 215 | return 0; | 287 | return rt; |
| 216 | } | 288 | } |
| 217 | 289 | ||
| 218 | extern void rt_bind_peer(struct rtable *rt, int create); | 290 | extern void rt_bind_peer(struct rtable *rt, int create); |
