[ar71xx] create firmware image for the RouterStation Pro, and add a profile for it...
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.21 / 201-multiple_default_gateways.patch
1 --- a/include/linux/netfilter_ipv4/ip_nat.h
2 +++ b/include/linux/netfilter_ipv4/ip_nat.h
3 @@ -64,6 +64,13 @@ struct ip_nat_info
4
5 struct ip_conntrack;
6
7 +/* Call input routing for SNAT-ed traffic */
8 +extern unsigned int ip_nat_route_input(unsigned int hooknum,
9 + struct sk_buff **pskb,
10 + const struct net_device *in,
11 + const struct net_device *out,
12 + int (*okfn)(struct sk_buff *));
13 +
14 /* Set up the info structure to map into this range. */
15 extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack,
16 const struct ip_nat_range *range,
17 --- a/include/linux/rtnetlink.h
18 +++ b/include/linux/rtnetlink.h
19 @@ -293,6 +293,8 @@ struct rtnexthop
20 #define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
21 #define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
22 #define RTNH_F_ONLINK 4 /* Gateway is forced on link */
23 +#define RTNH_F_SUSPECT 8 /* We don't know the real state */
24 +#define RTNH_F_BADSTATE (RTNH_F_DEAD | RTNH_F_SUSPECT)
25
26 /* Macros to handle hexthops */
27
28 --- a/include/net/flow.h
29 +++ b/include/net/flow.h
30 @@ -19,6 +19,8 @@ struct flowi {
31 struct {
32 __be32 daddr;
33 __be32 saddr;
34 + __u32 lsrc;
35 + __u32 gw;
36 __u8 tos;
37 __u8 scope;
38 } ip4_u;
39 @@ -43,6 +45,8 @@ struct flowi {
40 #define fl6_flowlabel nl_u.ip6_u.flowlabel
41 #define fl4_dst nl_u.ip4_u.daddr
42 #define fl4_src nl_u.ip4_u.saddr
43 +#define fl4_lsrc nl_u.ip4_u.lsrc
44 +#define fl4_gw nl_u.ip4_u.gw
45 #define fl4_tos nl_u.ip4_u.tos
46 #define fl4_scope nl_u.ip4_u.scope
47
48 --- a/net/ipv4/route.c
49 +++ b/net/ipv4/route.c
50 @@ -1208,6 +1208,7 @@ void ip_rt_redirect(__be32 old_gw, __be3
51
52 /* Gateway is different ... */
53 rt->rt_gateway = new_gw;
54 + if (rt->fl.fl4_gw) rt->fl.fl4_gw = new_gw;
55
56 /* Redirect received -> path was valid */
57 dst_confirm(&rth->u.dst);
58 @@ -1643,6 +1644,7 @@ static int ip_route_input_mc(struct sk_b
59 rth->fl.fl4_tos = tos;
60 rth->fl.mark = skb->mark;
61 rth->fl.fl4_src = saddr;
62 + rth->fl.fl4_lsrc = 0;
63 rth->rt_src = saddr;
64 #ifdef CONFIG_NET_CLS_ROUTE
65 rth->u.dst.tclassid = itag;
66 @@ -1653,6 +1655,7 @@ static int ip_route_input_mc(struct sk_b
67 dev_hold(rth->u.dst.dev);
68 rth->idev = in_dev_get(rth->u.dst.dev);
69 rth->fl.oif = 0;
70 + rth->fl.fl4_gw = 0;
71 rth->rt_gateway = daddr;
72 rth->rt_spec_dst= spec_dst;
73 rth->rt_type = RTN_MULTICAST;
74 @@ -1716,7 +1719,7 @@ static void ip_handle_martian_source(str
75 static inline int __mkroute_input(struct sk_buff *skb,
76 struct fib_result* res,
77 struct in_device *in_dev,
78 - __be32 daddr, __be32 saddr, u32 tos,
79 + __be32 daddr, __be32 saddr, u32 tos, u32 lsrc,
80 struct rtable **result)
81 {
82
83 @@ -1751,6 +1754,7 @@ static inline int __mkroute_input(struct
84 flags |= RTCF_DIRECTSRC;
85
86 if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
87 + !lsrc &&
88 (IN_DEV_SHARED_MEDIA(out_dev) ||
89 inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
90 flags |= RTCF_DOREDIRECT;
91 @@ -1788,6 +1792,7 @@ static inline int __mkroute_input(struct
92 rth->fl.mark = skb->mark;
93 rth->fl.fl4_src = saddr;
94 rth->rt_src = saddr;
95 + rth->fl.fl4_lsrc = lsrc;
96 rth->rt_gateway = daddr;
97 rth->rt_iif =
98 rth->fl.iif = in_dev->dev->ifindex;
99 @@ -1795,6 +1800,7 @@ static inline int __mkroute_input(struct
100 dev_hold(rth->u.dst.dev);
101 rth->idev = in_dev_get(rth->u.dst.dev);
102 rth->fl.oif = 0;
103 + rth->fl.fl4_gw = 0;
104 rth->rt_spec_dst= spec_dst;
105
106 rth->u.dst.input = ip_forward;
107 @@ -1816,19 +1822,21 @@ static inline int ip_mkroute_input_def(s
108 struct fib_result* res,
109 const struct flowi *fl,
110 struct in_device *in_dev,
111 - __be32 daddr, __be32 saddr, u32 tos)
112 + __be32 daddr, __be32 saddr, u32 tos,
113 + u32 lsrc)
114 {
115 struct rtable* rth = NULL;
116 int err;
117 unsigned hash;
118
119 + fib_select_default(fl, res);
120 #ifdef CONFIG_IP_ROUTE_MULTIPATH
121 - if (res->fi && res->fi->fib_nhs > 1 && fl->oif == 0)
122 + if (res->fi && res->fi->fib_nhs > 1)
123 fib_select_multipath(fl, res);
124 #endif
125
126 /* create a routing cache entry */
127 - err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
128 + err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, lsrc, &rth);
129 if (err)
130 return err;
131
132 @@ -1841,7 +1849,8 @@ static inline int ip_mkroute_input(struc
133 struct fib_result* res,
134 const struct flowi *fl,
135 struct in_device *in_dev,
136 - __be32 daddr, __be32 saddr, u32 tos)
137 + __be32 daddr, __be32 saddr, u32 tos,
138 + u32 lsrc)
139 {
140 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
141 struct rtable* rth = NULL, *rtres;
142 @@ -1857,7 +1866,7 @@ static inline int ip_mkroute_input(struc
143 /* distinguish between multipath and singlepath */
144 if (hopcount < 2)
145 return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
146 - saddr, tos);
147 + saddr, tos, 0);
148
149 /* add all alternatives to the routing cache */
150 for (hop = 0; hop < hopcount; hop++) {
151 @@ -1869,7 +1878,7 @@ static inline int ip_mkroute_input(struc
152
153 /* create a routing cache entry */
154 err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
155 - &rth);
156 + 0, &rth);
157 if (err)
158 return err;
159
160 @@ -1889,7 +1898,7 @@ static inline int ip_mkroute_input(struc
161 skb->dst = &rtres->u.dst;
162 return err;
163 #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
164 - return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
165 + return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos, lsrc);
166 #endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
167 }
168
169 @@ -1905,18 +1914,18 @@ static inline int ip_mkroute_input(struc
170 */
171
172 static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
173 - u8 tos, struct net_device *dev)
174 + u8 tos, struct net_device *dev, u32 lsrc)
175 {
176 struct fib_result res;
177 struct in_device *in_dev = in_dev_get(dev);
178 struct flowi fl = { .nl_u = { .ip4_u =
179 { .daddr = daddr,
180 - .saddr = saddr,
181 + .saddr = lsrc ? : saddr,
182 .tos = tos,
183 .scope = RT_SCOPE_UNIVERSE,
184 } },
185 .mark = skb->mark,
186 - .iif = dev->ifindex };
187 + .iif = lsrc? loopback_dev.ifindex : dev->ifindex };
188 unsigned flags = 0;
189 u32 itag = 0;
190 struct rtable * rth;
191 @@ -1949,6 +1958,12 @@ static int ip_route_input_slow(struct sk
192 if (BADCLASS(daddr) || ZERONET(daddr) || LOOPBACK(daddr))
193 goto martian_destination;
194
195 + if (lsrc) {
196 + if (MULTICAST(lsrc) || BADCLASS(lsrc) ||
197 + ZERONET(lsrc) || LOOPBACK(lsrc))
198 + goto e_inval;
199 + }
200 +
201 /*
202 * Now we are ready to route packet.
203 */
204 @@ -1958,6 +1973,10 @@ static int ip_route_input_slow(struct sk
205 goto no_route;
206 }
207 free_res = 1;
208 + if (lsrc && res.type != RTN_UNICAST && res.type != RTN_NAT)
209 + goto e_inval;
210 + fl.iif = dev->ifindex;
211 + fl.fl4_src = saddr;
212
213 RT_CACHE_STAT_INC(in_slow_tot);
214
215 @@ -1982,7 +2001,7 @@ static int ip_route_input_slow(struct sk
216 if (res.type != RTN_UNICAST)
217 goto martian_destination;
218
219 - err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
220 + err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos, lsrc);
221 if (err == -ENOBUFS)
222 goto e_nobufs;
223 if (err == -EINVAL)
224 @@ -1997,6 +2016,8 @@ out: return err;
225 brd_input:
226 if (skb->protocol != htons(ETH_P_IP))
227 goto e_inval;
228 + if (lsrc)
229 + goto e_inval;
230
231 if (ZERONET(saddr))
232 spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
233 @@ -2037,6 +2058,7 @@ local_input:
234 rth->u.dst.dev = &loopback_dev;
235 dev_hold(rth->u.dst.dev);
236 rth->idev = in_dev_get(rth->u.dst.dev);
237 + rth->fl.fl4_gw = 0;
238 rth->rt_gateway = daddr;
239 rth->rt_spec_dst= spec_dst;
240 rth->u.dst.input= ip_local_deliver;
241 @@ -2086,8 +2108,9 @@ martian_source:
242 goto e_inval;
243 }
244
245 -int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
246 - u8 tos, struct net_device *dev)
247 +static inline int
248 +ip_route_input_cached(struct sk_buff *skb, __be32 daddr, __be32 saddr,
249 + u8 tos, struct net_device *dev, u32 lsrc)
250 {
251 struct rtable * rth;
252 unsigned hash;
253 @@ -2102,6 +2125,7 @@ int ip_route_input(struct sk_buff *skb,
254 if (rth->fl.fl4_dst == daddr &&
255 rth->fl.fl4_src == saddr &&
256 rth->fl.iif == iif &&
257 + rth->fl.fl4_lsrc == lsrc &&
258 rth->fl.oif == 0 &&
259 rth->fl.mark == skb->mark &&
260 rth->fl.fl4_tos == tos) {
261 @@ -2148,7 +2172,19 @@ int ip_route_input(struct sk_buff *skb,
262 rcu_read_unlock();
263 return -EINVAL;
264 }
265 - return ip_route_input_slow(skb, daddr, saddr, tos, dev);
266 + return ip_route_input_slow(skb, daddr, saddr, tos, dev, lsrc);
267 +}
268 +
269 +int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
270 + u8 tos, struct net_device *dev)
271 +{
272 + return ip_route_input_cached(skb, daddr, saddr, tos, dev, 0);
273 +}
274 +
275 +int ip_route_input_lookup(struct sk_buff *skb, u32 daddr, u32 saddr,
276 + u8 tos, struct net_device *dev, u32 lsrc)
277 +{
278 + return ip_route_input_cached(skb, daddr, saddr, tos, dev, lsrc);
279 }
280
281 static inline int __mkroute_output(struct rtable **result,
282 @@ -2227,6 +2263,7 @@ static inline int __mkroute_output(struc
283 rth->fl.fl4_tos = tos;
284 rth->fl.fl4_src = oldflp->fl4_src;
285 rth->fl.oif = oldflp->oif;
286 + rth->fl.fl4_gw = oldflp->fl4_gw;
287 rth->fl.mark = oldflp->mark;
288 rth->rt_dst = fl->fl4_dst;
289 rth->rt_src = fl->fl4_src;
290 @@ -2367,6 +2404,7 @@ static int ip_route_output_slow(struct r
291 struct flowi fl = { .nl_u = { .ip4_u =
292 { .daddr = oldflp->fl4_dst,
293 .saddr = oldflp->fl4_src,
294 + .gw = oldflp->fl4_gw,
295 .tos = tos & IPTOS_RT_MASK,
296 .scope = ((tos & RTO_ONLINK) ?
297 RT_SCOPE_LINK :
298 @@ -2470,6 +2508,7 @@ static int ip_route_output_slow(struct r
299 dev_out = &loopback_dev;
300 dev_hold(dev_out);
301 fl.oif = loopback_dev.ifindex;
302 + fl.fl4_gw = 0;
303 res.type = RTN_LOCAL;
304 flags |= RTCF_LOCAL;
305 goto make_route;
306 @@ -2477,7 +2516,7 @@ static int ip_route_output_slow(struct r
307
308 if (fib_lookup(&fl, &res)) {
309 res.fi = NULL;
310 - if (oldflp->oif) {
311 + if (oldflp->oif && dev_out->flags & IFF_UP) {
312 /* Apparently, routing tables are wrong. Assume,
313 that the destination is on link.
314
315 @@ -2517,6 +2556,7 @@ static int ip_route_output_slow(struct r
316 dev_out = &loopback_dev;
317 dev_hold(dev_out);
318 fl.oif = dev_out->ifindex;
319 + fl.fl4_gw = 0;
320 if (res.fi)
321 fib_info_put(res.fi);
322 res.fi = NULL;
323 @@ -2524,13 +2564,12 @@ static int ip_route_output_slow(struct r
324 goto make_route;
325 }
326
327 + if (res.type == RTN_UNICAST)
328 + fib_select_default(&fl, &res);
329 #ifdef CONFIG_IP_ROUTE_MULTIPATH
330 - if (res.fi->fib_nhs > 1 && fl.oif == 0)
331 + if (res.fi->fib_nhs > 1)
332 fib_select_multipath(&fl, &res);
333 - else
334 #endif
335 - if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
336 - fib_select_default(&fl, &res);
337
338 if (!fl.fl4_src)
339 fl.fl4_src = FIB_RES_PREFSRC(res);
340 @@ -2567,6 +2606,7 @@ int __ip_route_output_key(struct rtable
341 rth->fl.fl4_src == flp->fl4_src &&
342 rth->fl.iif == 0 &&
343 rth->fl.oif == flp->oif &&
344 + rth->fl.fl4_gw == flp->fl4_gw &&
345 rth->fl.mark == flp->mark &&
346 !((rth->fl.fl4_tos ^ flp->fl4_tos) &
347 (IPTOS_RT_MASK | RTO_ONLINK))) {
348 @@ -3199,3 +3239,4 @@ int __init ip_rt_init(void)
349 EXPORT_SYMBOL(__ip_select_ident);
350 EXPORT_SYMBOL(ip_route_input);
351 EXPORT_SYMBOL(ip_route_output_key);
352 +EXPORT_SYMBOL(ip_route_input_lookup);
This page took 0.057132 seconds and 5 git commands to generate.