Commit a210d01a authored by Julian Anastasov's avatar Julian Anastasov Committed by David S. Miller

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: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarKOVACS Krisztian <hidden@sch.bme.hu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4edd87ad
...@@ -47,6 +47,8 @@ struct flowi { ...@@ -47,6 +47,8 @@ struct flowi {
#define fl4_scope nl_u.ip4_u.scope #define fl4_scope nl_u.ip4_u.scope
__u8 proto; __u8 proto;
__u8 flags;
#define FLOWI_FLAG_ANYSRC 0x01
union { union {
struct { struct {
__be16 sport; __be16 sport;
......
...@@ -2361,11 +2361,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, ...@@ -2361,11 +2361,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
ipv4_is_zeronet(oldflp->fl4_src)) ipv4_is_zeronet(oldflp->fl4_src))
goto out; goto out;
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out = ip_dev_find(net, oldflp->fl4_src);
if (dev_out == NULL)
goto out;
/* I removed check for oif == dev_out->oif here. /* I removed check for oif == dev_out->oif here.
It was wrong for two reasons: It was wrong for two reasons:
1. ip_dev_find(net, saddr) can return wrong iface, if saddr 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,6 +2372,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
if (oldflp->oif == 0 if (oldflp->oif == 0
&& (ipv4_is_multicast(oldflp->fl4_dst) || && (ipv4_is_multicast(oldflp->fl4_dst) ||
oldflp->fl4_dst == htonl(0xFFFFFFFF))) { oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out = ip_dev_find(net, oldflp->fl4_src);
if (dev_out == NULL)
goto out;
/* Special hack: user can direct multicasts /* Special hack: user can direct multicasts
and limited broadcast via necessary interface and limited broadcast via necessary interface
without fiddling with IP_MULTICAST_IF or IP_PKTINFO. 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,9 +2395,15 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
fl.oif = dev_out->ifindex; fl.oif = dev_out->ifindex;
goto make_route; goto make_route;
} }
if (dev_out)
if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) {
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out = ip_dev_find(net, oldflp->fl4_src);
if (dev_out == NULL)
goto out;
dev_put(dev_out); dev_put(dev_out);
dev_out = NULL; dev_out = NULL;
}
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment