* [PATCH] IPv6: fix IPV6_RECVERR handling of locally-generated errors
@ 2010-05-04 1:44 Brian Haley
0 siblings, 0 replies; only message in thread
From: Brian Haley @ 2010-05-04 1:44 UTC (permalink / raw)
To: David Miller, YOSHIFUJI Hideaki; +Cc: netdev@vger.kernel.org
I noticed when I added support for IPV6_DONTFRAG that if you set
IPV6_RECVERR and tried to send a UDP packet larger than 64K to an
IPv6 destination, you'd correctly get an EMSGSIZE, but reading from
MSG_ERRQUEUE returned the incorrect address in the cmsg:
struct msghdr:
msg_name 0x7fff8f3c96d0
msg_namelen 28
struct sockaddr_in6:
sin6_family 10
sin6_port 7639
sin6_flowinfo 0
sin6_addr ::ffff:38.32.0.0
sin6_scope_id 0 ((null))
It should have returned this in my case:
struct msghdr:
msg_name 0x7fffd866b510
msg_namelen 28
struct sockaddr_in6:
sin6_family 10
sin6_port 7639
sin6_flowinfo 0
sin6_addr 2620:0:a09:e000:21f:29ff:fe57:f88b
sin6_scope_id 0 ((null))
The problem is that ipv6_recv_error() assumes that if the error
wasn't generated by ICMPv6, it's an IPv4 address sitting there,
and proceeds to create a v4-mapped address from it.
--
Change ipv6_icmp_error() and ipv6_local_error() to set skb->protocol
to htons(ETH_P_IPV6) so that ipv6_recv_error() knows the address
sitting right after the extended error is IPv6, else it will
incorrectly map the first octet into an IPv4-mapped IPv6 address
in the cmsg structure returned in a recvmsg() call to obtain
the error.
Signed-off-by: Brian Haley <brian.haley@hp.com>
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 5959230..7126846 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -222,6 +222,8 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
if (!skb)
return;
+ skb->protocol = htons(ETH_P_IPV6);
+
serr = SKB_EXT_ERR(skb);
serr->ee.ee_errno = err;
serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6;
@@ -255,6 +257,8 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
if (!skb)
return;
+ skb->protocol = htons(ETH_P_IPV6);
+
skb_put(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
iph = ipv6_hdr(skb);
@@ -358,7 +362,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
sin->sin6_flowinfo = 0;
sin->sin6_port = serr->port;
sin->sin6_scope_id = 0;
- if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
+ if (skb->protocol == htons(ETH_P_IPV6)) {
ipv6_addr_copy(&sin->sin6_addr,
(struct in6_addr *)(nh + serr->addr_offset));
if (np->sndflow)
@@ -380,7 +384,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
sin->sin6_family = AF_INET6;
sin->sin6_flowinfo = 0;
sin->sin6_scope_id = 0;
- if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
+ if (skb->protocol == htons(ETH_P_IPV6)) {
ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr);
if (np->rxopt.all)
datagram_recv_ctl(sk, msg, skb);
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2010-05-04 1:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-04 1:44 [PATCH] IPv6: fix IPV6_RECVERR handling of locally-generated errors Brian Haley
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.