aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Anastasov <ja@ssi.bg>2008-10-01 10:28:28 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-01 10:28:28 -0400
commita210d01ae3ee006b59e54e772a7f212486e0f021 (patch)
treeceea5f8de75e70b13641f340e3b13a125a52567a
parent4edd87ad5cad8e159e0db3ce3131b3d97219c9cd (diff)
ipv4: Loosen source address check on IPv4 output
ip_route_output() contains a check to make sure that no flows with non-local source IP addresses are routed. This obviously makes using such addresses impossible. This patch introduces a flowi flag which makes omitting this check possible. The new flag provides a way of handling transparent and non-transparent connections differently. Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/flow.h2
-rw-r--r--net/ipv4/route.c20
2 files changed, 15 insertions, 7 deletions
diff --git a/include/net/flow.h b/include/net/flow.h
index 228b2477ceec..b45a5e4fcadd 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -47,6 +47,8 @@ struct flowi {
47#define fl4_scope nl_u.ip4_u.scope 47#define fl4_scope nl_u.ip4_u.scope
48 48
49 __u8 proto; 49 __u8 proto;
50 __u8 flags;
51#define FLOWI_FLAG_ANYSRC 0x01
50 union { 52 union {
51 struct { 53 struct {
52 __be16 sport; 54 __be16 sport;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f62187bb6d08..a6d7c584f53b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2361,11 +2361,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
2361 ipv4_is_zeronet(oldflp->fl4_src)) 2361 ipv4_is_zeronet(oldflp->fl4_src))
2362 goto out; 2362 goto out;
2363 2363
2364 /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
2365 dev_out = ip_dev_find(net, oldflp->fl4_src);
2366 if (dev_out == NULL)
2367 goto out;
2368
2369 /* I removed check for oif == dev_out->oif here. 2364 /* I removed check for oif == dev_out->oif here.
2370 It was wrong for two reasons: 2365 It was wrong for two reasons:
2371 1. ip_dev_find(net, saddr) can return wrong iface, if saddr 2366 1. ip_dev_find(net, saddr) can return wrong iface, if saddr
@@ -2377,6 +2372,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
2377 if (oldflp->oif == 0 2372 if (oldflp->oif == 0
2378 && (ipv4_is_multicast(oldflp->fl4_dst) || 2373 && (ipv4_is_multicast(oldflp->fl4_dst) ||
2379 oldflp->fl4_dst == htonl(0xFFFFFFFF))) { 2374 oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
2375 /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
2376 dev_out = ip_dev_find(net, oldflp->fl4_src);
2377 if (dev_out == NULL)
2378 goto out;
2379
2380 /* Special hack: user can direct multicasts 2380 /* Special hack: user can direct multicasts
2381 and limited broadcast via necessary interface 2381 and limited broadcast via necessary interface
2382 without fiddling with IP_MULTICAST_IF or IP_PKTINFO. 2382 without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -2395,9 +2395,15 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
2395 fl.oif = dev_out->ifindex; 2395 fl.oif = dev_out->ifindex;
2396 goto make_route; 2396 goto make_route;
2397 } 2397 }
2398 if (dev_out) 2398
2399 if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) {
2400 /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
2401 dev_out = ip_dev_find(net, oldflp->fl4_src);
2402 if (dev_out == NULL)
2403 goto out;
2399 dev_put(dev_out); 2404 dev_put(dev_out);
2400 dev_out = NULL; 2405 dev_out = NULL;
2406 }
2401 } 2407 }
2402 2408
2403 2409