Skip to contentSkip to conversation

ipv6: raw: use IPv4 raw_sendmsg on v4-mapped IPv6 destinations

PATCH In review Ivan Delalande 2 participants 2 messages Jan 25, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ipv6: raw: use IPv4 raw_sendmsg on v4-mapped IPv6 destinations

Make IPv6 SOCK_RAW sockets operate like IPv6 UDP and TCP sockets with respect to IPv4 mapped addresses by calling IPv4 raw_sendmsg from rawv6_sendmsg to send those messages out.

---
 include/net/raw.h |  1 +
 net/ipv4/raw.c    |  5 +++--
 net/ipv6/raw.c    | 14 ++++++++++++++
 3 files changed, 18 insertions(+), 2 deletions(-)
include/net/raw.h +1 -0
index 99d26d0c4a19..b4dbf730da54 100644
@@ -33,6 +33,7 @@ void raw_icmp_error(struct sk_buff *, int, u32);
 int raw_local_deliver(struct sk_buff *, int);
 
 int raw_rcv(struct sock *, struct sk_buff *);
+int rawv4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
 
 #define RAW_HTABLE_SIZE	MAX_INET_PROTOS
 
net/ipv4/raw.c +3 -2
index 136544b36a46..09f719af8642 100644
@@ -499,7 +499,7 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
 	return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
 }
 
-static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+int rawv4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct net *net = sock_net(sk);
@@ -692,6 +692,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 	err = 0;
 	goto done;
 }
+EXPORT_SYMBOL_GPL(rawv4_sendmsg);
 
 static void raw_close(struct sock *sk, long timeout)
 {
@@ -969,7 +970,7 @@ struct proto raw_prot = {
 	.init		   = raw_init,
 	.setsockopt	   = raw_setsockopt,
 	.getsockopt	   = raw_getsockopt,
-	.sendmsg	   = raw_sendmsg,
+	.sendmsg	   = rawv4_sendmsg,
 	.recvmsg	   = raw_recvmsg,
 	.bind		   = raw_bind,
 	.backlog_rcv	   = raw_rcv_skb,
net/ipv6/raw.c +14 -0
index ddda7eb3c623..f8513e2f1481 100644
@@ -844,6 +844,20 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 		fl6.flowlabel = np->flow_label;
 	}
 
+	if (daddr && ipv6_addr_v4mapped(daddr)) {
+		struct sockaddr_in sin;
+
+		sin.sin_family = AF_INET;
+		sin.sin_port = sin6 ? sin6->sin6_port : inet->inet_dport;
+		sin.sin_addr.s_addr = daddr->s6_addr32[3];
+		msg->msg_name = &sin;
+		msg->msg_namelen = sizeof(sin);
+
+		if (__ipv6_only_sock(sk))
+			return -ENETUNREACH;
+		return rawv4_sendmsg(sk, msg, len);
+	}
+
 	if (fl6.flowi6_oif == 0)
 		fl6.flowi6_oif = sk->sk_bound_dev_if;
 
Signature · 1 line
2.16.1
maintainer
#1 lore raw

From: Ivan Delalande <[email protected]>
Date: Wed, 24 Jan 2018 17:43:43 -0800

Quoted 6 lines

Make IPv6 SOCK_RAW sockets operate like IPv6 UDP and TCP sockets with respect to IPv4 mapped addresses by calling IPv4 raw_sendmsg from rawv6_sendmsg to send those messages out.

For RAW sockets this doesn't make any sense.

Especially when header-include is enabled, one expects the application to provide an address-family appropriate protocol header in it's buffer.

Which means ipv4 for ipv4 sockets and ipv6 for ipv6 sockets.

So we should interpret the request as an ipv6 one regardless of whether the ipv6 destination is ipv4 mapped or not.

Thank you.