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