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); |