aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/l2tp/l2tp_core.c27
-rw-r--r--net/l2tp/l2tp_core.h3
2 files changed, 26 insertions, 4 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index feae495a0a30..aedaa2cd4237 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -496,6 +496,7 @@ out:
496static inline int l2tp_verify_udp_checksum(struct sock *sk, 496static inline int l2tp_verify_udp_checksum(struct sock *sk,
497 struct sk_buff *skb) 497 struct sk_buff *skb)
498{ 498{
499 struct l2tp_tunnel *tunnel = (struct l2tp_tunnel *)sk->sk_user_data;
499 struct udphdr *uh = udp_hdr(skb); 500 struct udphdr *uh = udp_hdr(skb);
500 u16 ulen = ntohs(uh->len); 501 u16 ulen = ntohs(uh->len);
501 __wsum psum; 502 __wsum psum;
@@ -504,7 +505,7 @@ static inline int l2tp_verify_udp_checksum(struct sock *sk,
504 return 0; 505 return 0;
505 506
506#if IS_ENABLED(CONFIG_IPV6) 507#if IS_ENABLED(CONFIG_IPV6)
507 if (sk->sk_family == PF_INET6) { 508 if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) {
508 if (!uh->check) { 509 if (!uh->check) {
509 LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n"); 510 LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
510 return 1; 511 return 1;
@@ -1128,7 +1129,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
1128 /* Queue the packet to IP for output */ 1129 /* Queue the packet to IP for output */
1129 skb->local_df = 1; 1130 skb->local_df = 1;
1130#if IS_ENABLED(CONFIG_IPV6) 1131#if IS_ENABLED(CONFIG_IPV6)
1131 if (skb->sk->sk_family == PF_INET6) 1132 if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped)
1132 error = inet6_csk_xmit(skb, NULL); 1133 error = inet6_csk_xmit(skb, NULL);
1133 else 1134 else
1134#endif 1135#endif
@@ -1255,7 +1256,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
1255 1256
1256 /* Calculate UDP checksum if configured to do so */ 1257 /* Calculate UDP checksum if configured to do so */
1257#if IS_ENABLED(CONFIG_IPV6) 1258#if IS_ENABLED(CONFIG_IPV6)
1258 if (sk->sk_family == PF_INET6) 1259 if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
1259 l2tp_xmit_ipv6_csum(sk, skb, udp_len); 1260 l2tp_xmit_ipv6_csum(sk, skb, udp_len);
1260 else 1261 else
1261#endif 1262#endif
@@ -1704,6 +1705,24 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1704 if (cfg != NULL) 1705 if (cfg != NULL)
1705 tunnel->debug = cfg->debug; 1706 tunnel->debug = cfg->debug;
1706 1707
1708#if IS_ENABLED(CONFIG_IPV6)
1709 if (sk->sk_family == PF_INET6) {
1710 struct ipv6_pinfo *np = inet6_sk(sk);
1711
1712 if (ipv6_addr_v4mapped(&np->saddr) &&
1713 ipv6_addr_v4mapped(&np->daddr)) {
1714 struct inet_sock *inet = inet_sk(sk);
1715
1716 tunnel->v4mapped = true;
1717 inet->inet_saddr = np->saddr.s6_addr32[3];
1718 inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3];
1719 inet->inet_daddr = np->daddr.s6_addr32[3];
1720 } else {
1721 tunnel->v4mapped = false;
1722 }
1723 }
1724#endif
1725
1707 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ 1726 /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
1708 tunnel->encap = encap; 1727 tunnel->encap = encap;
1709 if (encap == L2TP_ENCAPTYPE_UDP) { 1728 if (encap == L2TP_ENCAPTYPE_UDP) {
@@ -1712,7 +1731,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
1712 udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; 1731 udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
1713 udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; 1732 udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;
1714#if IS_ENABLED(CONFIG_IPV6) 1733#if IS_ENABLED(CONFIG_IPV6)
1715 if (sk->sk_family == PF_INET6) 1734 if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
1716 udpv6_encap_enable(); 1735 udpv6_encap_enable();
1717 else 1736 else
1718#endif 1737#endif
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 66a559b104b6..6f251cbc2ed7 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -194,6 +194,9 @@ struct l2tp_tunnel {
194 struct sock *sock; /* Parent socket */ 194 struct sock *sock; /* Parent socket */
195 int fd; /* Parent fd, if tunnel socket 195 int fd; /* Parent fd, if tunnel socket
196 * was created by userspace */ 196 * was created by userspace */
197#if IS_ENABLED(CONFIG_IPV6)
198 bool v4mapped;
199#endif
197 200
198 struct work_struct del_work; 201 struct work_struct del_work;
199 202