l2tp: add support for IPv4-mapped IPv6 addresses
Subsystems (2)
PATCH v2 1/1 l2tp: add support for IPv4-mapped IPv6 addresses
IPv4 mapped addresses cause kernel panic.
The patch juste check whether the IPv6 address is an IPv4 mapped address. If so, use the IPv4 API instead of IPv6 one.
Signed-off-by François CACHEREUL <[email protected]>
---
v2: apply requested changes
net/l2tp/l2tp_core.c | 29 +++++++++++++++++++++++++---- net/l2tp/l2tp_core.h | 3 +++ 2 files changed, 28 insertions(+), 4 deletions(-)
net/l2tp/l2tp_core.c +25 -4
@@ -496,6 +496,7 @@ out:static inline int l2tp_verify_udp_checksum (struct sock *sk,struct sk_buff *skb) { +struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data;struct udphdr *uh =udp_hdr (skb);u16 ulen =ntohs (uh->len);__wsum psum;
@@ -504,7 +505,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk,return 0 ;#if IS_ENABLED (CONFIG_IPV6 ) -if (sk->sk_family ==PF_INET6 ) { +if (sk->sk_family ==PF_INET6 && !tunnel->v4mapped) {if (!uh->check) {LIMIT_NETDEBUG (KERN_INFO "L2TP: IPv6: checksum is 0\n" );return 1 ;
@@ -1128,7 +1129,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,/* Queue the packet to IP for output */ skb->local_df =1 ;#if IS_ENABLED (CONFIG_IPV6 ) -if (skb->sk->sk_family ==PF_INET6 ) +if (skb->sk->sk_family ==PF_INET6 && !tunnel->v4mapped) error =inet6_csk_xmit (skb,NULL ); else#endif
@@ -1255,7 +1256,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len/* Calculate UDP checksum if configured to do so */ #if IS_ENABLED (CONFIG_IPV6 ) -if (sk->sk_family ==PF_INET6 ) +if (sk->sk_family ==PF_INET6 && !tunnel->v4mapped)l2tp_xmit_ipv6_csum (sk, skb, udp_len); else#endif
@@ -1620,6 +1621,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32int err;struct socket *sock =NULL ;struct sock *sk =NULL ; +#if IS_ENABLED (CONFIG_IPV6 ) +#endif struct l2tp_net *pn;enum l2tp_encap_type encap =L2TP_ENCAPTYPE_UDP ;
@@ -1704,6 +1707,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32if (cfg !=NULL ) tunnel->debug = cfg->debug; +#if IS_ENABLED (CONFIG_IPV6 ) +if (sk->sk_family ==PF_INET6 ) { +struct ipv6_pinfo *np =inet6_sk (sk); + +if (ipv6_addr_v4mapped (&np->saddr) && +ipv6_addr_v4mapped (&np->daddr)) { +struct inet_sock *inet =inet_sk (sk); + + tunnel->v4mapped = true; + inet->inet_saddr = np->saddr.s6_addr32[3 ]; + inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3 ]; + inet->inet_daddr = np->daddr.s6_addr32[3 ]; + }else { + tunnel->v4mapped = false; + } + } +#endif +/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ tunnel->encap = encap;if (encap ==L2TP_ENCAPTYPE_UDP ) {
@@ -1712,7 +1733,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32udp_sk (sk)->encap_rcv = l2tp_udp_encap_recv;udp_sk (sk)->encap_destroy = l2tp_udp_encap_destroy;#if IS_ENABLED (CONFIG_IPV6 ) -if (sk->sk_family ==PF_INET6 ) +if (sk->sk_family ==PF_INET6 && !tunnel->v4mapped)udpv6_encap_enable (); else#endif
net/l2tp/l2tp_core.h +3 -0
@@ -194,6 +194,9 @@ struct l2tp_tunnel {struct sock *sock;/* Parent socket */ int fd;/* Parent fd, if tunnel socket * was created by userspace */ +#if IS_ENABLED (CONFIG_IPV6 ) +bool v4mapped; +#endif struct work_struct del_work;
Signature · 1 line
1.7.10.4
David Miller
maintainerFrom: François Cachereul <[email protected]>
Date: Tue, 01 Oct 2013 09:54:31 +0200
net/l2tp/l2tp_core.c int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 · line 1628
Quoted 9 lines
net/l2tp/l2tp_core.c +2
-0@@ -1620,6 +1621,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32int err;struct socket *sock =NULL ;struct sock *sk =NULL ; +#if IS_ENABLED (CONFIG_IPV6 ) +#endif struct l2tp_net *pn;enum l2tp_encap_type encap =L2TP_ENCAPTYPE_UDP ;
Please get rid of this.