summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2016-12-08 18:12:23 +0300
committerDmitry Kozlov <xeb@mail.ru>2016-12-08 18:19:01 +0300
commitfc33b4c6ec83533d35db3626887fb5156478bca3 (patch)
tree86c67ea62ed87c000149ef6fe703ba53283966a3 /drivers
parentbe063e68bbbba46048215a8fdfccf511af45c490 (diff)
downloadaccel-ppp-fc33b4c6ec83533d35db3626887fb5156478bca3.tar.gz
accel-ppp-fc33b4c6ec83533d35db3626887fb5156478bca3.zip
ipoe: fixed nat support
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ipoe/ipoe.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/ipoe/ipoe.c b/drivers/ipoe/ipoe.c
index f1addcc8..ceab7c9b 100644
--- a/drivers/ipoe/ipoe.c
+++ b/drivers/ipoe/ipoe.c
@@ -138,6 +138,8 @@ static int ipoe_do_nat(struct sk_buff *skb, __be32 new_addr, int to_peer);
static int ipoe_queue_u(struct sk_buff *skb, __be32 addr);
static int ipoe_lookup1_u(__be32 addr, unsigned long *ts);
+static struct net *pick_net(struct sk_buff *skb);
+
static const struct net_device_ops ipoe_netdev_ops;
static struct genl_family ipoe_nl_family;
@@ -223,6 +225,33 @@ static int ipoe_check_exclude(__be32 addr)
return r;
}
+static int check_nat_required(struct sk_buff *skb, struct net_device *link)
+{
+ struct net *net = pick_net(skb);
+ struct rtable *rt;
+ struct flowi4 fl4;
+ struct iphdr *iph = ip_hdr(skb);
+ int r = 0;
+
+ if (!list_empty(&ipoe_networks))
+ return ipoe_check_network(iph->daddr) == 0;
+
+ memset(&fl4, 0, sizeof(fl4));
+ fl4.daddr = iph->daddr;
+ fl4.flowi4_tos = RT_TOS(0);
+ fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+ rt = ip_route_output_key(net, &fl4);
+ if (IS_ERR(rt))
+ return 0;
+
+ if (rt->rt_gateway || (rt->dst.dev != link && rt->dst.dev != skb->dev))
+ r = 1;
+
+ ip_rt_put(rt);
+
+ return r;
+}
+
static int ipoe_do_nat(struct sk_buff *skb, __be32 new_addr, int to_peer)
{
struct iphdr *iph;
@@ -789,7 +818,7 @@ static rx_handler_result_t ipoe_recv(struct sk_buff **pskb)
else if (memcmp(eth->h_source, ses->hwaddr, ETH_ALEN))
goto drop;
- if (ses->addr > 1 && ipoe_do_nat(skb, ses->addr, 0))
+ if (ses->addr > 1 && check_nat_required(skb, ses->link_dev) && ipoe_do_nat(skb, ses->addr, 0))
goto drop;
skb->dev = ses->dev;