diff options
Diffstat (limited to 'include/net/route.h')
-rw-r--r-- | include/net/route.h | 163 |
1 files changed, 82 insertions, 81 deletions
diff --git a/include/net/route.h b/include/net/route.h index 8fce0621cad1..db7b3432f07c 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -35,16 +35,8 @@ | |||
35 | #include <linux/cache.h> | 35 | #include <linux/cache.h> |
36 | #include <linux/security.h> | 36 | #include <linux/security.h> |
37 | 37 | ||
38 | #ifndef __KERNEL__ | ||
39 | #warning This file is not supposed to be used outside of kernel. | ||
40 | #endif | ||
41 | |||
42 | #define RTO_ONLINK 0x01 | 38 | #define RTO_ONLINK 0x01 |
43 | 39 | ||
44 | #define RTO_CONN 0 | ||
45 | /* RTO_CONN is not used (being alias for 0), but preserved not to break | ||
46 | * some modules referring to it. */ | ||
47 | |||
48 | #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) | 40 | #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) |
49 | 41 | ||
50 | struct fib_nh; | 42 | struct fib_nh; |
@@ -60,7 +52,7 @@ struct rtable { | |||
60 | int rt_genid; | 52 | int rt_genid; |
61 | unsigned rt_flags; | 53 | unsigned rt_flags; |
62 | __u16 rt_type; | 54 | __u16 rt_type; |
63 | __u8 rt_tos; | 55 | __u8 rt_key_tos; |
64 | 56 | ||
65 | __be32 rt_dst; /* Path destination */ | 57 | __be32 rt_dst; /* Path destination */ |
66 | __be32 rt_src; /* Path source */ | 58 | __be32 rt_src; /* Path source */ |
@@ -123,7 +115,7 @@ extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, | |||
123 | __be32 src, struct net_device *dev); | 115 | __be32 src, struct net_device *dev); |
124 | extern void rt_cache_flush(struct net *net, int how); | 116 | extern void rt_cache_flush(struct net *net, int how); |
125 | extern void rt_cache_flush_batch(struct net *net); | 117 | extern void rt_cache_flush_batch(struct net *net); |
126 | extern struct rtable *__ip_route_output_key(struct net *, const struct flowi4 *flp); | 118 | extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); |
127 | extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, | 119 | extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, |
128 | struct sock *sk); | 120 | struct sock *sk); |
129 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); | 121 | extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); |
@@ -145,40 +137,33 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, | |||
145 | return ip_route_output_key(net, &fl4); | 137 | return ip_route_output_key(net, &fl4); |
146 | } | 138 | } |
147 | 139 | ||
148 | static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk, | 140 | static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi4 *fl4, |
141 | struct sock *sk, | ||
149 | __be32 daddr, __be32 saddr, | 142 | __be32 daddr, __be32 saddr, |
150 | __be16 dport, __be16 sport, | 143 | __be16 dport, __be16 sport, |
151 | __u8 proto, __u8 tos, int oif) | 144 | __u8 proto, __u8 tos, int oif) |
152 | { | 145 | { |
153 | struct flowi4 fl4 = { | 146 | flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos, |
154 | .flowi4_oif = oif, | 147 | RT_SCOPE_UNIVERSE, proto, |
155 | .flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0, | 148 | sk ? inet_sk_flowi_flags(sk) : 0, |
156 | .flowi4_mark = sk ? sk->sk_mark : 0, | 149 | daddr, saddr, dport, sport); |
157 | .daddr = daddr, | ||
158 | .saddr = saddr, | ||
159 | .flowi4_tos = tos, | ||
160 | .flowi4_proto = proto, | ||
161 | .fl4_dport = dport, | ||
162 | .fl4_sport = sport, | ||
163 | }; | ||
164 | if (sk) | 150 | if (sk) |
165 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | 151 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
166 | return ip_route_output_flow(net, &fl4, sk); | 152 | return ip_route_output_flow(net, fl4, sk); |
167 | } | 153 | } |
168 | 154 | ||
169 | static inline struct rtable *ip_route_output_gre(struct net *net, | 155 | static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 *fl4, |
170 | __be32 daddr, __be32 saddr, | 156 | __be32 daddr, __be32 saddr, |
171 | __be32 gre_key, __u8 tos, int oif) | 157 | __be32 gre_key, __u8 tos, int oif) |
172 | { | 158 | { |
173 | struct flowi4 fl4 = { | 159 | memset(fl4, 0, sizeof(*fl4)); |
174 | .flowi4_oif = oif, | 160 | fl4->flowi4_oif = oif; |
175 | .daddr = daddr, | 161 | fl4->daddr = daddr; |
176 | .saddr = saddr, | 162 | fl4->saddr = saddr; |
177 | .flowi4_tos = tos, | 163 | fl4->flowi4_tos = tos; |
178 | .flowi4_proto = IPPROTO_GRE, | 164 | fl4->flowi4_proto = IPPROTO_GRE; |
179 | .fl4_gre_key = gre_key, | 165 | fl4->fl4_gre_key = gre_key; |
180 | }; | 166 | return ip_route_output_key(net, fl4); |
181 | return ip_route_output_key(net, &fl4); | ||
182 | } | 167 | } |
183 | 168 | ||
184 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, | 169 | extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, |
@@ -196,14 +181,15 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s | |||
196 | return ip_route_input_common(skb, dst, src, tos, devin, true); | 181 | return ip_route_input_common(skb, dst, src, tos, devin, true); |
197 | } | 182 | } |
198 | 183 | ||
199 | extern unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, unsigned short new_mtu, struct net_device *dev); | 184 | extern unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, |
185 | unsigned short new_mtu, struct net_device *dev); | ||
200 | extern void ip_rt_send_redirect(struct sk_buff *skb); | 186 | extern void ip_rt_send_redirect(struct sk_buff *skb); |
201 | 187 | ||
202 | extern unsigned inet_addr_type(struct net *net, __be32 addr); | 188 | extern unsigned inet_addr_type(struct net *net, __be32 addr); |
203 | extern unsigned inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); | 189 | extern unsigned inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); |
204 | extern void ip_rt_multicast_event(struct in_device *); | 190 | extern void ip_rt_multicast_event(struct in_device *); |
205 | extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); | 191 | extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); |
206 | extern void ip_rt_get_source(u8 *src, struct rtable *rt); | 192 | extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); |
207 | extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); | 193 | extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); |
208 | 194 | ||
209 | struct in_ifaddr; | 195 | struct in_ifaddr; |
@@ -225,78 +211,93 @@ static inline char rt_tos2priority(u8 tos) | |||
225 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; | 211 | return ip_tos2prio[IPTOS_TOS(tos)>>1]; |
226 | } | 212 | } |
227 | 213 | ||
228 | static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos, | 214 | /* ip_route_connect() and ip_route_newports() work in tandem whilst |
215 | * binding a socket for a new outgoing connection. | ||
216 | * | ||
217 | * In order to use IPSEC properly, we must, in the end, have a | ||
218 | * route that was looked up using all available keys including source | ||
219 | * and destination ports. | ||
220 | * | ||
221 | * However, if a source port needs to be allocated (the user specified | ||
222 | * a wildcard source port) we need to obtain addressing information | ||
223 | * in order to perform that allocation. | ||
224 | * | ||
225 | * So ip_route_connect() looks up a route using wildcarded source and | ||
226 | * destination ports in the key, simply so that we can get a pair of | ||
227 | * addresses to use for port allocation. | ||
228 | * | ||
229 | * Later, once the ports are allocated, ip_route_newports() will make | ||
230 | * another route lookup if needed to make sure we catch any IPSEC | ||
231 | * rules keyed on the port information. | ||
232 | * | ||
233 | * The callers allocate the flow key on their stack, and must pass in | ||
234 | * the same flowi4 object to both the ip_route_connect() and the | ||
235 | * ip_route_newports() calls. | ||
236 | */ | ||
237 | |||
238 | static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 src, | ||
239 | u32 tos, int oif, u8 protocol, | ||
240 | __be16 sport, __be16 dport, | ||
241 | struct sock *sk, bool can_sleep) | ||
242 | { | ||
243 | __u8 flow_flags = 0; | ||
244 | |||
245 | if (inet_sk(sk)->transparent) | ||
246 | flow_flags |= FLOWI_FLAG_ANYSRC; | ||
247 | if (protocol == IPPROTO_TCP) | ||
248 | flow_flags |= FLOWI_FLAG_PRECOW_METRICS; | ||
249 | if (can_sleep) | ||
250 | flow_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
251 | |||
252 | flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, | ||
253 | protocol, flow_flags, dst, src, dport, sport); | ||
254 | } | ||
255 | |||
256 | static inline struct rtable *ip_route_connect(struct flowi4 *fl4, | ||
257 | __be32 dst, __be32 src, u32 tos, | ||
229 | int oif, u8 protocol, | 258 | int oif, u8 protocol, |
230 | __be16 sport, __be16 dport, | 259 | __be16 sport, __be16 dport, |
231 | struct sock *sk, bool can_sleep) | 260 | struct sock *sk, bool can_sleep) |
232 | { | 261 | { |
233 | struct flowi4 fl4 = { | ||
234 | .flowi4_oif = oif, | ||
235 | .flowi4_mark = sk->sk_mark, | ||
236 | .daddr = dst, | ||
237 | .saddr = src, | ||
238 | .flowi4_tos = tos, | ||
239 | .flowi4_proto = protocol, | ||
240 | .fl4_sport = sport, | ||
241 | .fl4_dport = dport, | ||
242 | }; | ||
243 | struct net *net = sock_net(sk); | 262 | struct net *net = sock_net(sk); |
244 | struct rtable *rt; | 263 | struct rtable *rt; |
245 | 264 | ||
246 | if (inet_sk(sk)->transparent) | 265 | ip_route_connect_init(fl4, dst, src, tos, oif, protocol, |
247 | fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; | 266 | sport, dport, sk, can_sleep); |
248 | if (protocol == IPPROTO_TCP) | ||
249 | fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; | ||
250 | if (can_sleep) | ||
251 | fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP; | ||
252 | 267 | ||
253 | if (!dst || !src) { | 268 | if (!dst || !src) { |
254 | rt = __ip_route_output_key(net, &fl4); | 269 | rt = __ip_route_output_key(net, fl4); |
255 | if (IS_ERR(rt)) | 270 | if (IS_ERR(rt)) |
256 | return rt; | 271 | return rt; |
257 | fl4.daddr = rt->rt_dst; | ||
258 | fl4.saddr = rt->rt_src; | ||
259 | ip_rt_put(rt); | 272 | ip_rt_put(rt); |
260 | } | 273 | } |
261 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | 274 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
262 | return ip_route_output_flow(net, &fl4, sk); | 275 | return ip_route_output_flow(net, fl4, sk); |
263 | } | 276 | } |
264 | 277 | ||
265 | static inline struct rtable *ip_route_newports(struct rtable *rt, | 278 | static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable *rt, |
266 | u8 protocol, __be16 orig_sport, | 279 | __be16 orig_sport, __be16 orig_dport, |
267 | __be16 orig_dport, __be16 sport, | 280 | __be16 sport, __be16 dport, |
268 | __be16 dport, struct sock *sk) | 281 | struct sock *sk) |
269 | { | 282 | { |
270 | if (sport != orig_sport || dport != orig_dport) { | 283 | if (sport != orig_sport || dport != orig_dport) { |
271 | struct flowi4 fl4 = { | 284 | fl4->fl4_dport = dport; |
272 | .flowi4_oif = rt->rt_oif, | 285 | fl4->fl4_sport = sport; |
273 | .flowi4_mark = rt->rt_mark, | ||
274 | .daddr = rt->rt_dst, | ||
275 | .saddr = rt->rt_src, | ||
276 | .flowi4_tos = rt->rt_tos, | ||
277 | .flowi4_proto = protocol, | ||
278 | .fl4_sport = sport, | ||
279 | .fl4_dport = dport | ||
280 | }; | ||
281 | if (inet_sk(sk)->transparent) | ||
282 | fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC; | ||
283 | if (protocol == IPPROTO_TCP) | ||
284 | fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS; | ||
285 | ip_rt_put(rt); | 286 | ip_rt_put(rt); |
286 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | 287 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); |
287 | return ip_route_output_flow(sock_net(sk), &fl4, sk); | 288 | return ip_route_output_flow(sock_net(sk), fl4, sk); |
288 | } | 289 | } |
289 | return rt; | 290 | return rt; |
290 | } | 291 | } |
291 | 292 | ||
292 | extern void rt_bind_peer(struct rtable *rt, int create); | 293 | extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); |
293 | 294 | ||
294 | static inline struct inet_peer *rt_get_peer(struct rtable *rt) | 295 | static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) |
295 | { | 296 | { |
296 | if (rt->peer) | 297 | if (rt->peer) |
297 | return rt->peer; | 298 | return rt->peer; |
298 | 299 | ||
299 | rt_bind_peer(rt, 0); | 300 | rt_bind_peer(rt, daddr, 0); |
300 | return rt->peer; | 301 | return rt->peer; |
301 | } | 302 | } |
302 | 303 | ||