From saper@saper.info  Wed Sep  3 02:24:11 2008
Return-Path: <saper@saper.info>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id D64CE106564A
	for <freebsd-gnats-submit@freebsd.org>; Wed,  3 Sep 2008 02:24:11 +0000 (UTC)
	(envelope-from saper@saper.info)
Received: from system.pl (ns356865.ovh.net [91.121.143.223])
	by mx1.freebsd.org (Postfix) with ESMTP id 355F98FC12
	for <freebsd-gnats-submit@freebsd.org>; Wed,  3 Sep 2008 02:24:09 +0000 (UTC)
	(envelope-from saper@saper.info)
Received: (qmail 29906 invoked by uid 10); 3 Sep 2008 04:24:08 +0200
Received: from radziecki.saper.info (localhost [127.0.0.1])
	by radziecki.saper.info (8.14.2/8.14.2) with ESMTP id m832N8Vl029160
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 3 Sep 2008 04:23:08 +0200 (CEST)
	(envelope-from saper@saper.info)
Received: (from saper@localhost)
	by radziecki.saper.info (8.14.2/8.14.2/Submit) id m832Fqsr024291;
	Wed, 3 Sep 2008 04:15:52 +0200 (CEST)
	(envelope-from saper)
Message-Id: <200809030215.m832Fqsr024291@radziecki.saper.info>
Date: Wed, 3 Sep 2008 04:15:52 +0200 (CEST)
From: Marcin Cieslak <saper@SYSTEM.PL>
Reply-To: Marcin Cieslak <saper@SYSTEM.PL>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: Unable to send UDP packet via IPv6 socket to IPv4 mapped address
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         127057
>Category:       kern
>Synopsis:       [udp] Unable to send UDP packet via IPv6 socket to IPv4 mapped address
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bz
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 03 02:30:01 UTC 2008
>Closed-Date:    Sat Feb 11 16:56:33 UTC 2012
>Last-Modified:  Sat Feb 11 16:56:33 UTC 2012
>Originator:     Marcin Cieslak
>Release:        FreeBSD 7.0-STABLE amd64
>Organization:
http://saper.info
>Environment:
System: FreeBSD radziecki.saper.info 7.0-STABLE FreeBSD 7.0-STABLE #0: Wed Jul 23 05:06:20 CEST 2008 saper@radziecki.saper.info:/usr/obj/usr/bsd/build/sys/VAIO amd64


     $FreeBSD: src/sys/netinet6/dest6.c,v 1.11 2007/07/05 16:23:46 delphij Exp $
     $FreeBSD: src/sys/netinet6/frag6.c,v 1.33 2007/07/05 16:29:39 delphij Exp $
     $FreeBSD: src/sys/netinet6/icmp6.c,v 1.80 2007/07/05 16:29:39 delphij Exp $
     $FreeBSD: src/sys/netinet6/icmp6.h,v 1.6 2000/07/04 16:35:09 itojun Exp $
     $FreeBSD: src/sys/netinet6/in6.c,v 1.73.2.1 2008/03/09 19:01:50 bz Exp $
     $FreeBSD: src/sys/netinet6/in6.h,v 1.51 2007/07/19 09:16:40 bz Exp $
     $FreeBSD: src/sys/netinet6/in6_cksum.c,v 1.16 2007/07/05 16:23:47 delphij Exp $
     $FreeBSD: src/sys/netinet6/in6_gif.c,v 1.29 2007/07/05 16:29:39 delphij Exp $
     $FreeBSD: src/sys/netinet6/in6_gif.h,v 1.7 2005/01/07 02:30:34 imp Exp $
     $FreeBSD: src/sys/netinet6/in6_ifattach.c,v 1.39 2007/07/05 16:23:47 delphij Exp $
     $FreeBSD: src/sys/netinet6/in6_ifattach.h,v 1.7 2005/10/21 16:23:00 suz Exp $
     $FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.84.2.2 2008/04/27 14:39:32 rwatson Exp $
     $FreeBSD: src/sys/netinet6/in6_pcb.h,v 1.19 2007/05/11 10:20:50 rwatson Exp $
     $FreeBSD: src/sys/netinet6/in6_proto.c,v 1.46 2007/07/05 16:29:39 delphij Exp $
     $FreeBSD: src/sys/netinet6/in6_rmx.c,v 1.18 2007/07/05 16:29:39 delphij Exp $
     $FreeBSD: src/sys/netinet6/in6_src.c,v 1.46.2.1 2008/03/08 23:45:39 bz Exp $
     $FreeBSD: src/sys/netinet6/in6_var.h,v 1.31 2007/06/02 08:02:36 jinmei Exp $
     $FreeBSD: src/sys/netinet6/ip6.h,v 1.5 2000/07/04 16:35:09 itojun Exp $
     $FreeBSD: src/sys/netinet6/ip6_ecn.h,v 1.6 2005/01/07 02:30:34 imp Exp $
     $FreeBSD: src/sys/netinet6/ip6_forward.c,v 1.40 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/ip6_id.c,v 1.8 2007/07/05 16:23:47 delphij Exp $
     $FreeBSD: src/sys/netinet6/ip6_input.c,v 1.95 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/ip6_ipsec.c,v 1.6.2.2 2008/03/21 23:08:36 bz Exp $
     $FreeBSD: src/sys/netinet6/ip6_ipsec.h,v 1.2.2.1 2008/03/21 23:03:32 bz Exp $
     $FreeBSD: src/sys/netinet6/ip6_mroute.c,v 1.46 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/ip6_mroute.h,v 1.12 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/ip6_output.c,v 1.109.2.6 2008/03/21 23:22:06 bz Exp $
     $FreeBSD: src/sys/netinet6/ip6_var.h,v 1.39.2.1 2008/03/09 19:01:50 bz Exp $
     $FreeBSD: src/sys/netinet6/ip6protosw.h,v 1.13 2005/01/07 02:30:34 imp Exp $
     $FreeBSD: src/sys/netinet6/mld6.c,v 1.31 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/mld6_var.h,v 1.7 2005/10/21 16:23:00 suz Exp $
     $FreeBSD: src/sys/netinet6/nd6.c,v 1.83.2.1 2007/10/30 18:03:50 jhb Exp $
     $FreeBSD: src/sys/netinet6/nd6.h,v 1.21 2005/10/21 16:23:00 suz Exp $
     $FreeBSD: src/sys/netinet6/nd6_nbr.c,v 1.47 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/nd6_rtr.c,v 1.36 2007/07/05 16:29:40 delphij Exp $
     $FreeBSD: src/sys/netinet6/pim6.h,v 1.3 2005/01/07 02:30:35 imp Exp $
     $FreeBSD: src/sys/netinet6/pim6_var.h,v 1.5 2005/08/10 07:10:02 obrien Exp $
     $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.73.2.1 2008/03/09 19:01:50 bz Exp $
     $FreeBSD: src/sys/netinet6/raw_ip6.h,v 1.2 2005/01/07 02:30:35 imp Exp $
     $FreeBSD: src/sys/netinet6/route6.c,v 1.14 2007/07/05 16:23:48 delphij Exp $
     $FreeBSD: src/sys/netinet6/scope6.c,v 1.17 2007/07/05 16:23:48 delphij Exp $
     $FreeBSD: src/sys/netinet6/scope6_var.h,v 1.5 2005/07/25 12:31:42 ume Exp $
     $FreeBSD: src/sys/netinet6/sctp6_usrreq.c,v 1.41.2.1 2008/04/29 09:26:32 rrs Exp $
     $FreeBSD: src/sys/netinet6/sctp6_var.h,v 1.8 2007/09/13 10:36:43 rrs Exp $
     $FreeBSD: src/sys/netinet6/tcp6_var.h,v 1.7 2005/01/07 02:30:35 imp Exp $
     $FreeBSD: src/sys/netinet6/tcp6_var.h,v 1.7 2005/01/07 02:30:35 imp Exp $
     $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.81.2.1 2008/03/09 19:01:50 bz Exp $
     $FreeBSD: src/sys/netinet6/udp6_var.h,v 1.9 2007/07/23 07:58:58 rwatson Exp $


net.inet6.ip6.forwarding: 0
net.inet6.ip6.redirect: 1
net.inet6.ip6.hlim: 64
net.inet6.ip6.maxfragpackets: 6400
net.inet6.ip6.accept_rtadv: 0
net.inet6.ip6.keepfaith: 0
net.inet6.ip6.log_interval: 5
net.inet6.ip6.hdrnestlimit: 15
net.inet6.ip6.dad_count: 1
net.inet6.ip6.auto_flowlabel: 1
net.inet6.ip6.defmcasthlim: 1
net.inet6.ip6.gifhlim: 30
net.inet6.ip6.kame_version: FreeBSD
net.inet6.ip6.use_deprecated: 1
net.inet6.ip6.rr_prune: 5
net.inet6.ip6.v6only: 0
net.inet6.ip6.rtexpire: 3600
net.inet6.ip6.rtminexpire: 10
net.inet6.ip6.rtmaxcache: 128
net.inet6.ip6.use_tempaddr: 0
net.inet6.ip6.temppltime: 86400
net.inet6.ip6.tempvltime: 604800
net.inet6.ip6.auto_linklocal: 1
net.inet6.ip6.prefer_tempaddr: 0
net.inet6.ip6.use_defaultzone: 0
net.inet6.ip6.maxfrags: 6400
net.inet6.ip6.mcast_pmtu: 0
net.inet6.ip6.fw.enable: 1
net.inet6.ip6.fw.deny_unknown_exthdrs: 1
net.inet6.ipsec6.def_policy: 1
net.inet6.ipsec6.esp_trans_deflev: 1
net.inet6.ipsec6.esp_net_deflev: 1
net.inet6.ipsec6.ah_trans_deflev: 1
net.inet6.ipsec6.ah_net_deflev: 1
net.inet6.ipsec6.ecn: 0
net.inet6.ipsec6.debug: 0
net.inet6.ipsec6.esp_randpad: -1
net.inet6.icmp6.rediraccept: 1
net.inet6.icmp6.redirtimeout: 600
net.inet6.icmp6.nd6_prune: 1
net.inet6.icmp6.nd6_delay: 5
net.inet6.icmp6.nd6_umaxtries: 3
net.inet6.icmp6.nd6_mmaxtries: 3
net.inet6.icmp6.nd6_useloopback: 1
net.inet6.icmp6.nodeinfo: 3
net.inet6.icmp6.errppslimit: 100
net.inet6.icmp6.nd6_maxnudhint: 0
net.inet6.icmp6.nd6_debug: 0
net.inet6.icmp6.nd6_maxqueuelen: 1

>Description:

Calling bind() with an unspecified IPv6 address followed by connect() to an IPv4
mapped address causes EINVAL in sendto()

Same also on an i386 machine.

I think this problem is also concerning TCP.

This affects mostly Java programs, since Java sends IPv4 packets (by default)
via the IPv6 socket.

>How-To-Repeat:

A simple C program:


/**
 * Sending UDP datagram from :: -> 2001:db8::1 (OK)
 * Sending UDP datagram from :: -> ::ffff:192.168.101.23 (fails, EINVAL)
 */

#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <netinet/in.h>
/*
 * $40 = {him4 = {sin_len = 0 '\0', sin_family = 28 '\034', sin_port = 0, sin_addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, him6 = {
 *     sin6_len = 0 '\0', sin6_family = 28 '\034', sin6_port = 0, sin6_flowinfo = 0, sin6_addr = {__u6_addr = {__u6_addr8 = '\0' <repeats 15 times>,
 *         __u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, __u6_addr32 = {0, 0, 0, 0}}}, sin6_scope_id = 0}}
 */

static u_char bindaddr[] = { 
 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00 };

/*
 * $42 = {him4 = {sin_len = 0 '\0', sin_family = 28 '\034', sin_port = 13568, sin_addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, him6 = {
 *     sin6_len = 0 '\0', sin6_family = 28 '\034', sin6_port = 13568, sin6_flowinfo = 0, sin6_addr = {__u6_addr = {
 *         __u6_addr8 = "\000\000\000\000\000\000\000\000\000\000���e\027", __u6_addr16 = {0, 0, 0, 0, 0, 65535, 43200, 5989}, __u6_addr32 = {0, 0,
 *           4294901760, 392538304}}}, sin6_scope_id = 0}}
 */

static u_char connectaddr4[] =  {
 0x1c, 0x1c, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x65, 0x17,
 0x00, 0x00, 0x00, 0x00 };

/* [2001:db8::1] */

static u_char connectaddr6[] =  {
 0x1c, 0x1c, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00,
 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
 0x00, 0x00, 0x00, 0x00 };

/* IN SRV query _xmpp-server._tcp.google.com */

static u_char dns_packet[] = {
 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
 0x70, 0x70, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65,
 0x72, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x67,
 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
 0x6d, 0x00, 0x00, 0x21, 0x00, 0x01 };

void process_socket(struct sockaddr *bind_to, 
	struct sockaddr *connect_to)
{
	int fd = socket(PF_INET6, SOCK_DGRAM, 17);
	int optval, optlen, rc;

	optlen = sizeof(optval);

	bind(fd, bind_to, 28); 
	if (connect(fd, connect_to, 28) < 0)
		perror("connect");

	if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, 
		&optlen) == -1)
             err(1, "getsockopt");
	printf("IPV6_V6ONLY = %d\n", optval);

	if ((rc = sendto(fd, dns_packet, 46, 0, NULL, 0)) < 0)
		perror("sendto");
	else
		printf("Success, wrote %d bytes\n", rc);
	close(fd);
}

int main() {

	printf("Trying to send to 2001:db8::1\n");
	process_socket( (struct sockaddr *) &bindaddr, 
			(struct sockaddr *) &connectaddr6);
	printf("Trying to send to 192.168.101.23\n");
	process_socket( (struct sockaddr *) &bindaddr, 
			(struct sockaddr *) &connectaddr4);
}

Output:

Trying to send to 2001:db8::1
IPV6_V6ONLY = 0
Success, wrote 46 bytes
Trying to send to 192.168.101.23
IPV6_V6ONLY = 0
sendto: Invalid argument

>Fix:

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Sep 3 03:18:48 UTC 2008 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=127057 

From: "Alexander V. Chernikov" <melifaro@ipfw.ru>
To: bug-followup@FreeBSD.org, saper@SYSTEM.PL
Cc:  
Subject: Re: kern/127057: [udp] Unable to send UDP packet via IPv6 socket
 to IPv4 mapped address
Date: Thu, 24 Jun 2010 19:44:25 +0400

 1) Problem can be more easily reproduced with nc:
 echo | ktrace nc -nu6 ::ffff:127.0.0.1 53 ; kdump | grep socket -A 15
 
   1682 nc       CALL  socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP)
   1682 nc       RET   socket 3
   1682 nc       CALL  connect(0x3,0x800a050e0,0x1c)
   1682 nc       STRU  struct sockaddr { AF_INET6, [::ffff:127.0.0.1]:53 }
   1682 nc       RET   connect 0
   1682 nc       CALL  poll(0x7fffffffa6b0,0x2,0xffffffff)
   1682 nc       RET   poll 1
   1682 nc       CALL  read(0,0x7fffffffa6c0,0x400)
   1682 nc       GIO   fd 0 read 1 byte
        "
        "
   1682 nc       RET   read 1
   1682 nc       CALL  write(0x3,0x7fffffffa6c0,0x1)
   1682 nc       RET   write -1 errno 22 Invalid argument
 
 Problem is related with [implicit] IPv4 bind done by in_pcbconnect  (or 
 in_pcbbind_setup in case of explicit bind())
 Selected IPv4 IP address is written into inpcb -> 
 inp_inc.inc_ie.ie_dependladdr.ie46_local
 According to struct in_addr_4in6 interpreting written value as IPv6 
 address results in ::127.0.0.1, which is not correct v4-mapped address 
 (it is actually deprecated ipv4-compatible address),
 so IN6_IS_ADDR_V4MAPPED() address check in udp6_send failes with EINVAL.
 
 
 
 Proposed solution is to add required ffff immediately after v4 protocol 
 layer connection succeeded, e.g.
 
 --- sys/netinet6/udp6_usrreq.c.orig     2010-06-24 12:32:10.813316692 +0000
 +++ sys/netinet6/udp6_usrreq.c  2010-06-24 12:33:02.977455989 +0000
 @@ -923,6 +923,8 @@
                 if (error == 0) {
                         inp->inp_vflag |= INP_IPV4;
                         inp->inp_vflag &= ~INP_IPV6;
 +                       /* Make v6 addr v4-mapped */
 +                       
 inp->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_pad32[2] = 
 IPV6_ADDR_INT32_SMP;
                         soisconnected(so);
                 }
                 goto out;
 
 This tiny patch fixes an issue with java DNS resolution (at least for me)
 

From: "Alexander V. Chernikov" <melifaro@ipfw.ru>
To: bug-followup@FreeBSD.org, saper@SYSTEM.PL
Cc:  
Subject: Re: kern/127057: [udp] Unable to send UDP packet via IPv6 socket
 to IPv4 mapped address
Date: Thu, 24 Jun 2010 19:54:02 +0400

 Problem can be more easily reproduced with nc:
 echo | ktrace nc -nu6 ::ffff:127.0.0.1 53 ; kdump | grep socket -A 15
 
   1682 nc       CALL  socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP)
   1682 nc       RET   socket 3
   1682 nc       CALL  connect(0x3,0x800a050e0,0x1c)
   1682 nc       STRU  struct sockaddr { AF_INET6, [::ffff:127.0.0.1]:53 }
   1682 nc       RET   connect 0
   1682 nc       CALL  poll(0x7fffffffa6b0,0x2,0xffffffff)
   1682 nc       RET   poll 1
   1682 nc       CALL  read(0,0x7fffffffa6c0,0x400)
   1682 nc       GIO   fd 0 read 1 byte
        "
        "
   1682 nc       RET   read 1
   1682 nc       CALL  write(0x3,0x7fffffffa6c0,0x1)
   1682 nc       RET   write -1 errno 22 Invalid argument
   1682 nc       CALL  close(0x3)
   1682 nc       RET   close 0
   1682 nc       CALL  sigprocmask(SIG_BLOCK,0x80063e140,0x7fffffffc640)
 
 
 Problem is related with an [implicit] IPv4 bind() done in in_pcbconnect 
 (or in_pcbbind_setup for explicit bind ).
 bind results in selected IPv4 address written in 
 inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4
 According to struct in_addr_4in6, interpreting witten value as IPv6 
 address results in ::127.0.0.1 v6 address for 127.0.0.1 which is not 
 IPv4-mapped address (it is deprecated IPv4-compatible adddress, actually).
 This address causes udp6_send() returning  EINVAL (immediately after 
 IN6_IS_ADDR_V4MAPPED(&inp->in6p_laddr) check)
 
 Proposed solution is to add missing :ffff: immediately after successful 
 v4 layer connect, e.g.
 
 --- sys/netinet6/udp6_usrreq.c.orig     2010-06-24 12:32:10.813316692 +0000
 +++ sys/netinet6/udp6_usrreq.c  2010-06-24 12:33:02.977455989 +0000
 @@ -923,6 +923,8 @@
                 if (error == 0) {
                         inp->inp_vflag |= INP_IPV4;
                         inp->inp_vflag &= ~INP_IPV6;
 +                       /* Make v6 addr v4-mapped */
 +                       
 inp->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_pad32[2] = 
 IPV6_ADDR_INT32_SMP;
                         soisconnected(so);
                 }
                 goto out;
 
 
 
 This tiny patch fixes java DNS resolution for me

From: "Alexander V. Chernikov" <melifaro@ipfw.ru>
To: bug-followup@FreeBSD.org, saper@SYSTEM.PL
Cc:  
Subject: Re: kern/127057: [udp] Unable to send UDP packet via IPv6 socket
 to IPv4 mapped address
Date: Sun, 26 Jun 2011 15:16:46 +0400

 Problem seems to be fixed in -current in r220463
State-Changed-From-To: open->patched 
State-Changed-By: bz 
State-Changed-When: Mon Jul 4 19:11:06 UTC 2011 
State-Changed-Why:  
Seems I fixed it lately in r220463. 


Responsible-Changed-From-To: freebsd-net->bz 
Responsible-Changed-By: bz 
Responsible-Changed-When: Mon Jul 4 19:11:06 UTC 2011 
Responsible-Changed-Why:  
Take given it seems I fixed it so I can track MFCs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=127057 
State-Changed-From-To: patched->closed 
State-Changed-By: bz 
State-Changed-When: Sat Feb 11 16:55:58 UTC 2012 
State-Changed-Why:  
It seems this has long been MFCed but the PR was never closed 
as the original commit had happened unrelated to the PR. 

Thanks a lot for reporting! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=127057 
>Unformatted:
