diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2016-12-08 18:12:23 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2016-12-08 18:19:01 +0300 |
commit | fc33b4c6ec83533d35db3626887fb5156478bca3 (patch) | |
tree | 86c67ea62ed87c000149ef6fe703ba53283966a3 /drivers | |
parent | be063e68bbbba46048215a8fdfccf511af45c490 (diff) | |
download | accel-ppp-fc33b4c6ec83533d35db3626887fb5156478bca3.tar.gz accel-ppp-fc33b4c6ec83533d35db3626887fb5156478bca3.zip |
ipoe: fixed nat support
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ipoe/ipoe.c | 31 |
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; |