From Jean-Luc.Richier@imag.fr  Wed Nov 15 03:19:45 2000
Return-Path: <Jean-Luc.Richier@imag.fr>
Received: from horus.imag.fr (horus.imag.fr [129.88.38.2])
	by hub.freebsd.org (Postfix) with ESMTP id 44DEF37B479
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 15 Nov 2000 03:19:43 -0800 (PST)
Received: (from richier@localhost)
	by horus.imag.fr (8.9.3/8.8.6) id MAA02336
	for FreeBSD-gnats-submit@freebsd.org; Wed, 15 Nov 2000 12:20:14 +0100 (MET)
Message-Id: <200011151120.MAA02336@horus.imag.fr>
Date: Wed, 15 Nov 2000 12:20:14 +0100 (MET)
From: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
To: FreeBSD-gnats-submit@freebsd.org
Subject: INET6 sockets which are INET compatible lose packets

>Number:         22866
>Category:       kern
>Synopsis:       Packets send on INET6 sockets compatible may be lost
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 15 03:20:01 PST 2000
>Closed-Date:    Wed Jul 17 16:04:43 PDT 2002
>Last-Modified:  Wed Jul 17 16:04:43 PDT 2002
>Originator:     Jean-Luc Richier
>Release:        FreeBSD 4.1.1-RELEASE i386
>Organization:
LSR-IMAG, France
>Environment:

	Any FreeBSD with INET6 support (FreeBSD or kame)

Description: 

There is problems with INET6 sockets when using IPv4-mapped addresses:
after sending both IPv6 and IPv4 packets, new packet sent are lost.

The problem has been detected in FreeBSD4.1.1 GENERIC, but source inspection
makes me believe that the problem is still in FreeBSD-current and in 
kame-20001106-freebsd41-snap.

How-To-Repeat: 

Suppose that tuna is a machine with a FreeBSD 4.1.1 GENERIC kernel.
Validate the daytime service in /etc/inetd.conf on transport udp46:

daytime dgram	udp46	wait	root	internal

On a other machine send udp queries to tuna to port daytime (13) in IPv4,
then in IPv6, then in IPv4 (I used a simple ad-hoc program):
The trace is:
lagavulin# ./client -s 13 tuna
129.88.23.4: RECEIVED <Tue Nov 14 18:58:20 2000^M^J>
lagavulin# ./client -s 13 tuna-v6.ipv6
3ffe:302:12:2::4: RECEIVED <Tue Nov 14 18:58:20 2000^M^J>
lagavulin# ./client -s 13 tuna
^C   -- Nothing received

The tuna kernel performs the following actions:
- inetd receives a packet. It sends back using sendto an answer addressed
  to the source sockaddr_in6 sockaddr, which contains an IPv4-mapped
  address if the first packet transport is IPv4.
- sendto calls the kernel routine udp6_send.
- If the destination is not an IPv4-mapped address, udp6_send calls
  udp6_output which calls in6_selectsrc to set the source address. This
  is done by setting a cached route to the destination in the
  inp_dependroute.inp4_route field of the inp struct of the socket.
  Then ip6_output is called, and then the interface output routine.
- If the destination is an IPv4-mapped address, udp6_send calls upd_send,
  which calls udp_output which calls in_pcbconnect to set the source address.
  This is done by setting a cached route to the destination in the
  inp_dependroute.inp4_route field of the inp struct of the socket.
  Then ip_output is called, and then the interface output routine.

In both cases the packet may be lost in the interface output routine.

The problem is in both in_pcbconnect and in6_selectsrc: These functions set
  cached routes and clear old cached routes if needed. But the space for
  the sockaddr of the cached route is shared between IPv4 and IPv6, and
  the code to replace a cached route is not careful enough:
+ in in_pcb.c (in_pcbconnect)
	      if (ro->ro_rt &&
		    (satosin(&ro->ro_dst)->sin_addr.s_addr !=
			sin->sin_addr.s_addr ||
		    inp->inp_socket->so_options & SO_DONTROUTE)) {   
			RTFREE(ro->ro_rt);
			ro->ro_rt = (struct rtentry *)0;
             if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/                    (ro->ro_rt == (struct rtentry *)0 ||
                    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {   
                        /* No route yet, so try to acquire one */
                        ro->ro_dst.sa_family = AF_INET;
                        ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
                        ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
                                sin->sin_addr;
                        rtalloc(ro);
 
+ in in6_src.c (in6_selectsrc)
	 if (ro->ro_rt &&
		!IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
			RTFREE(ro->ro_rt);
			ro->ro_rt = (struct rtentry *)0;
                }
                if (ro->ro_rt == (struct rtentry *)0 ||
                    ro->ro_rt->rt_ifp == (struct ifnet *)0) {   
                        /* No route yet, so try to acquire one */
                        bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
                        ro->ro_dst.sin6_family = AF_INET6;
                        ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
                        ro->ro_dst.sin6_addr = *dst;
                        ro->ro_dst.sin6_scope_id = dstsock->sin6_scope_id;
 
In fact there is two problems:

1/ The first problem is that most of the fields of the sockaddr_in are not
cleared. This is normal if the family is not changed, but if the old ro_dst
was AF_INET6, the sin_zero field is not zero, and the arp resolution fails.

This is shown by arp:
tuna# arp -a
ganesha.imag.fr (129.88.23.3) at (incomplete) [ethernet]
lagavulin.imag.fr (129.88.23.10) at 0:a0:c9:aa:21:a1 [ethernet]
lagavulin.imag.fr (129.88.23.10) at (incomplete) [ethernet]
basta1.imag.fr (129.88.23.254) at 0:0:c:3f:5b:97 [ethernet]
? (129.88.25.90) at (incomplete) [ethernet]

One sees a duplicated arp for lagavulin. Using a modified netstat which
prints non zero fields of the sockaddr, we see a routing table of:
tuna# ./netstat -rnf inet
Routing tables
 
Internet:
Destination        Gateway            Flags      Netif Expire
default            129.88.23.254      UGSc        4      175      de1
127.0.0.1          127.0.0.1          UH          0       13      lo0
129.88.22/24       129.88.23.10       UGc         0        0      de1
129.88.23/24       link#2             UC          0        0      de1 =>
129.88.23.3        link#2             UHLW        1        0      de1 =>
129.88.23.10       0:a0:c9:aa:21:a1   UHLW        1       11      de1   1156
[sin_zero:3ffe030200120002]129.88.23.10       link#2             UHLW        1
1      de1 =>
129.88.23.254      0:0:c:3f:5b:97     UHLW        3        4      de1   1159
129.88.24/24       129.88.23.3        UGc         0        0      de1
129.88.25/24       link#1             UC          0        0      de0 =>
129.88.25.90       link#1             UHLW        1        1      de0 =>

One sees that the sin_zero contains the beginning of an IPv6 address.

2/ second problem:
There is another problem: if the test is done on the lo0 interface, the
packets are also lost. This comes from the fact that the sa_family of the
ro_dst may be incorrect. As the route replacement test tests only the
address, and as sin_address and sin6_address fields do not overlap, the
test may say that old and new addresses are equal, so no replacement is done.
If the family is incorrect, in the IPv6/not IPv4-mapped case an IPv6
packet is passed to if_simloop with an af argument of AF_INET. This means
that the IPv6 packet is put in the IPv4 input queue, and ip_input will
reject it (one can test this by adding messages in ip_input and ip6_input).
The same problem occurs with a IPv4-mapped address: an IPv4 packet is
passed to if_simloop with an af argument of AF_INET6. The packet will be
put in IPv6 input queue, and ip6_input will drop it.

Fix: 

== Suggested corrections ==

I do not have a simple general solution. 

There is a problem with cached routed whenever the route structure is used for both IPv4 and IPv6. This can happen in many places, potentially
everywhere a rtalloc* function is called.

- One solution is to check the sa_family in the `same route cached' test
before every rtalloc* call, and to fully bzero the sockaddr each time the
cache is different. Ths solution seems costly.

- An other solution is to make the test only when a real conflict is
possible. Checking the code for all the calls to rtallocs, I found
4 places when the problem occurs: udp6 output, udp6 connect, tcp_respond,
gif_output.

The others calls seem to be sane: in raw, multicast and icmp outputs, the
code is not shared: one cannot send IPv4 on INET6 sockets except for udp
and tcp. In other places where rtalloc is used (ip*forward, ipsec, ...),
it seems that the route entry is a local one, used only for IPv4 or IPv6,
not both.

Therefore I propose in the following 3 patches, one for udp6, one for gif
and one for tcp, with appropriate comments (I am not really sure for tcp).


A/ ========= PATCH FOR UDP =========
The problem is to clear the cached route and all the ro_dst fields before
allocating a new route if the family change. This can only occurs for
INET6 sockets. rtalloc is called from two places, udp6_connect (which can
call udp_connect) and udp6_send with addr not NULL (which call udp6_output
or udp_send).
So in both places if the new destination is V4-mapped and the route cached
is not AF_INET, or if the new destination is not V4-mapped and the route
cached is not AF_INET6, we clear the rtentry and the sockaddr ro_dst.
This gives the following patch:
Comments:
- I replaced a call to in6_sin6_2_sin_in_sock by a call to in6_sin6_2_sin,
  as I have done a port of nfs to IPv6, and I do not want to modify the
  addr argument.
- For a new socket, the test 
		inp->inp_route.ro_dst.sa_family != nam->sa_family
  will clear a newly allocated inp, which is already zero. One can avoid
  this by adding a second test
		if (inp->inp_route.ro_dst.sa_family != 0 &&
  but this may not be worthwhile, as this will happen only the first time
  a new socket is used.

*** netinet6/udp6_usrreq.c.DIST	Thu Aug  3 02:09:37 2000
--- netinet6/udp6_usrreq.c	Wed Nov 15 09:16:06 2000
***************
*** 606,635 ****
  {
  	struct inpcb *inp;
  	int s, error;
  
  	inp = sotoinpcb(so);
  	if (inp == 0)
  		return EINVAL;
! 	if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0) {
! 		struct sockaddr_in6 *sin6_p;
! 
! 		sin6_p = (struct sockaddr_in6 *)nam;
! 		if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
! 			struct sockaddr_in sin;
! 
! 			if (inp->inp_faddr.s_addr != INADDR_ANY)
! 				return EISCONN;
! 			in6_sin6_2_sin(&sin, sin6_p);
! 			s = splnet();
! 			error = in_pcbconnect(inp, (struct sockaddr *)&sin, p);
! 			splx(s);
! 			if (error == 0) {
! 				inp->inp_vflag |= INP_IPV4;
! 				inp->inp_vflag &= ~INP_IPV6;
  				soisconnected(so);
- 			}
- 			return error;
  		}
  	}
  
  	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
--- 606,639 ----
  {
  	struct inpcb *inp;
  	int s, error;
+ 	struct sockaddr_in sin;
  
  	inp = sotoinpcb(so);
  	if (inp == 0)
  		return EINVAL;
! 	if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0 &&
! 	    IN6_IS_ADDR_V4MAPPED(&satosin6(nam)->sin6_addr)) {
! 		if (inp->inp_faddr.s_addr != INADDR_ANY)
! 			return EISCONN;
! 		in6_sin6_2_sin(&sin, satosin6(nam));
! 		nam = (struct sockaddr *)&sin;
! 	}
! 	/* route cache management does not support family changes */
! 	if (inp->inp_route.ro_dst.sa_family != nam->sa_family) {
! 		if (inp->inp_route.ro_rt)
! 			RTFREE(inp->inp_route.ro_rt);
! 		bzero(&inp->inp_dependroute, sizeof(inp->inp_dependroute));
! 	}
! 	if (nam->sa_family == AF_INET) {
! 		s = splnet();
! 		error = in_pcbconnect(inp, nam, p);
! 		splx(s);
! 		if (error == 0) {
! 			inp->inp_vflag |= INP_IPV4;
! 			inp->inp_vflag &= ~INP_IPV6;
  				soisconnected(so);
  		}
+ 		return error;
  	}
  
  	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
***************
*** 719,743 ****
  
  	if (ip6_mapped_addr_on) {
  		int hasv4addr;
! 		struct sockaddr_in6 *sin6 = 0;
  
  		if (addr == 0)
  			hasv4addr = (inp->inp_vflag & INP_IPV4);
  		else {
! 			sin6 = (struct sockaddr_in6 *)addr;
! 			hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)
! 				? 1 : 0;
  		}
  		if (hasv4addr) {
  			struct pr_usrreqs *pru;
  
- 			if (sin6)
- 				in6_sin6_2_sin_in_sock(addr);
  			pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
! 			error = ((*pru->pru_send)(so, flags, m, addr, control,
! 						  p));
! 			/* addr will just be freed in sendit(). */
! 			return error;
  		}
  	}
  
--- 723,753 ----
  
  	if (ip6_mapped_addr_on) {
  		int hasv4addr;
! 		struct sockaddr_in sin;
  
  		if (addr == 0)
  			hasv4addr = (inp->inp_vflag & INP_IPV4);
  		else {
! 			 if (IN6_IS_ADDR_V4MAPPED(&satosin6(addr)->sin6_addr)) {
! 				hasv4addr = 1;
! 		/* Do not change addr arg, nfs will not agree ! */
! 				in6_sin6_2_sin(&sin, satosin6(addr));
! 				addr = (struct sockaddr *)&sin;
! 			} else
! 				hasv4addr = 0;
! 		/* route cache management does not support family changes */
! 			if (inp->inp_route.ro_dst.sa_family != addr->sa_family) {
! 				if (inp->inp_route.ro_rt)
! 					RTFREE(inp->inp_route.ro_rt);
! 				bzero(&inp->inp_dependroute,
! 					sizeof(inp->inp_dependroute));
! 			}
  		}
  		if (hasv4addr) {
  			struct pr_usrreqs *pru;
  
  			pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
! 			return (*pru->pru_send)(so, flags, m, addr, control, p);
  		}
  	}
  


B/ ========= PATCH FOR gif =========
There is a problem in in_gif.c: the cached route for the destination is not 
correctly reset if one changes a gif tunnel from an IPv6 destination to an
IPv6 destination.
I suggest the following patch:

*** netinet/in_gif.c.DIST	Wed Aug 30 04:37:06 2000
--- netinet/in_gif.c	Wed Nov  8 18:16:53 2000
***************
*** 194,199 ****
--- 194,200 ----
  	if (dst->sin_family != sin_dst->sin_family ||
  	    dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) {
  		/* cache route doesn't match */
+ 		bzero(dst, sizeof(*dst));
  		dst->sin_family = sin_dst->sin_family;
  		dst->sin_len = sizeof(struct sockaddr_in);
  		dst->sin_addr = sin_dst->sin_addr;


C/ ========= PATCH FOR tcp =========
The cached route problem can occurs in tcp. The only case is when the
pcb/inp/socket is both IPv4 and IPv6, that is, a INET6 socket in initial
SO_ACCEPTCONN mode, bound to IN6ADDR_ANY_INIT address and without
IPV6_BINDV6ONLY option (if the socket is connected, we have either
INP_IPV4 or INP_IPV6, not both, and this cannot change as one cannot
reconnect a tcp socket).
In this mode the only possible emission is the calls to tcp_respond done
by a goto maybedropwithreset or dropwithreset, if tp is not NULL and
points to the tcpcb of the listening socket. 
I have checked this case by using a program which sends incorrect initial
tcp packets (packets with both SYN and ACK), and the problem occured: the
RST packet was badly sent, and lost.

The problem seems almost the same as the one listed in the tcp_input source
about ipsec and which caused the displacement of the test
		if ((thflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
(ref : * Subject: (KAME-snap 748)
       * From: Wayne Knowles <w.knowles@niwa.cri.nz>
       * ftp://ftp.kame.net/pub/mail-list/snap-users/748

But this displacement of the test is not enough, as tp is still pointing on
the old tcpcb of the listening socket. Therefore I do not fully understand
how this displacement corrects the problem described in KAME-snap 748.
But I am not proficient enough in analysis of IPSEC code.

To correct the problem, I suggest three possible corrections. I cannot
choose between them as I cannot analyze fully the effects on IPSEC.

---- Solution 1 ----
The first solution is to clear tp before the call to tcp_respond, for example
just after the test
		if (so->so_options & SO_ACCEPTCONN)
The IPSEC side effect is that the RST packet is sent without IPSEC assocation.
Is that a problem ? Also if tp is cleared, it seems that the problem
described in KAME-snap 748 will not occur anymore and displacing the test
may be not needed ? (tcp_respond will not have a tcpcb anymore so it
should (?) not modify the socket IPsec cache).

The patch is:

*** netinet/tcp_input.c.DIST	Wed Aug 16 08:14:23 2000
--- netinet/tcp_input.c	Wed Nov 15 10:39:55 2000
***************
*** 691,696 ****
--- 691,697 ----
  			struct inpcb *oinp = sotoinpcb(so);
  #endif /* INET6 */
  
+ 			tp = 0;
  #ifndef IPSEC
  			/*
  			 * Current IPsec implementation makes incorrect IPsec


---- Solution 2 ----
The second solution is to always defer the test
		if (so->so_options & SO_ACCEPTCONN) {
in both IPSEC and not IPSEC cases, and to set tp pointing to the tcpcb
of the new (accepted) socket before the call to tcp_respond.
The IPSEC side effect is that the RST is sent with a socket in which the
copy of the old IPsec policy into new socket is not yet done. 
Also I am still dubious about the place of the code displaced due to
KAME-snap 748. When the goto maybedropwithreset is done tp points to the
old tcpcb, which should mean that the old socket is used for IPsec
computation/caching.

I suggest this patch which works in the non IPSEC case and do not modify
the KAME-snap 748 correction, but I am dubious on the IPSEC effects.
I prefer the two other solutions.


*** netinet/tcp_input.c.DIST	Wed Aug 16 08:14:23 2000
--- netinet/tcp_input.c	Wed Nov 15 10:46:29 2000
***************
*** 691,714 ****
  			struct inpcb *oinp = sotoinpcb(so);
  #endif /* INET6 */
  
- #ifndef IPSEC
- 			/*
- 			 * Current IPsec implementation makes incorrect IPsec
- 			 * cache if this check is done here.
- 			 * So delay this until duplicated socket is created.
- 			 */
- 			if ((thflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
- 				/*
- 				 * Note: dropwithreset makes sure we don't
- 				 * send a RST in response to a RST.
- 				 */
- 				if (thflags & TH_ACK) {
- 					tcpstat.tcps_badsyn++;
- 					goto maybedropwithreset;
- 				}
- 				goto drop;
- 			}
- #endif
  			so2 = sonewconn(so, 0);
  			if (so2 == 0) {
  				tcpstat.tcps_listendrop++;
--- 691,696 ----
***************
*** 740,745 ****
--- 722,728 ----
  			 */
  			dropsocket++;
  			inp = (struct inpcb *)so->so_pcb;
+ 			tp = intotcpcb(inp);
  #ifdef INET6
  			if (isipv6)
  				inp->in6p_laddr = ip6->ip6_dst;
***************
*** 768,774 ****
  				inp->inp_lport = 0;
  				goto drop;
  			}
! #ifdef IPSEC
  			/*
  			 * To avoid creating incorrectly cached IPsec
  			 * association, this is need to be done here.
--- 751,757 ----
  				inp->inp_lport = 0;
  				goto drop;
  			}
! 
  			/*
  			 * To avoid creating incorrectly cached IPsec
  			 * association, this is need to be done here.
***************
*** 788,794 ****
  				}
  				goto drop;
  			}
- #endif
  #ifdef INET6
  			if (isipv6) {
  				/*
--- 771,776 ----
***************
*** 815,821 ****
  			                      inp->inp_sp))
  				printf("tcp_input: could not copy policy\n");
  #endif
- 			tp = intotcpcb(inp);
  			tp->t_state = TCPS_LISTEN;
  			tp->t_flags |= tp0->t_flags & (TF_NOPUSH|TF_NOOPT);
  
--- 797,802 ----


---- Solution 3 ----
The third solution is to always defer the test
		if (so->so_options & SO_ACCEPTCONN) {
in both IPSEC and not IPSEC cases after tp is fully set towards the new
socket, with ipsec policy copied. The IPSEC side effect is that the RST is
 called with the full new tcpcb/socket. An other side effect is that code
displaced in KAME-snap 748 will use the new tcpcb/socket which seems correct
for solving the KAME-snap 748 IPsec cache problem.
But the cost of rejecting a bad initial packet is more costly, as a lot of
code is done before dropping the connection.

The patch is:

*** netinet/tcp_input.c.DIST	Wed Aug 16 08:14:23 2000
--- netinet/tcp_input.c	Wed Nov 15 10:45:56 2000
***************
*** 691,714 ****
  			struct inpcb *oinp = sotoinpcb(so);
  #endif /* INET6 */
  
- #ifndef IPSEC
- 			/*
- 			 * Current IPsec implementation makes incorrect IPsec
- 			 * cache if this check is done here.
- 			 * So delay this until duplicated socket is created.
- 			 */
- 			if ((thflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
- 				/*
- 				 * Note: dropwithreset makes sure we don't
- 				 * send a RST in response to a RST.
- 				 */
- 				if (thflags & TH_ACK) {
- 					tcpstat.tcps_badsyn++;
- 					goto maybedropwithreset;
- 				}
- 				goto drop;
- 			}
- #endif
  			so2 = sonewconn(so, 0);
  			if (so2 == 0) {
  				tcpstat.tcps_listendrop++;
--- 691,696 ----
***************
*** 768,794 ****
  				inp->inp_lport = 0;
  				goto drop;
  			}
- #ifdef IPSEC
- 			/*
- 			 * To avoid creating incorrectly cached IPsec
- 			 * association, this is need to be done here.
- 			 *
- 			 * Subject: (KAME-snap 748)
- 			 * From: Wayne Knowles <w.knowles@niwa.cri.nz>
- 			 * ftp://ftp.kame.net/pub/mail-list/snap-users/748
- 			 */
- 			if ((thflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
- 				/*
- 				 * Note: dropwithreset makes sure we don't
- 				 * send a RST in response to a RST.
- 				 */
- 				if (thflags & TH_ACK) {
- 					tcpstat.tcps_badsyn++;
- 					goto maybedropwithreset;
- 				}
- 				goto drop;
- 			}
- #endif
  #ifdef INET6
  			if (isipv6) {
  				/*
--- 750,755 ----
***************
*** 816,821 ****
--- 777,803 ----
  				printf("tcp_input: could not copy policy\n");
  #endif
  			tp = intotcpcb(inp);
+ 			/*
+ 			 * To avoid creating incorrectly cached IPsec
+ 			 * association, this is need to be done here.
+ 			 *
+ 			 * Subject: (KAME-snap 748)
+ 			 * From: Wayne Knowles <w.knowles@niwa.cri.nz>
+ 			 * ftp://ftp.kame.net/pub/mail-list/snap-users/748
+ 			 *
+ 			 * Also need a correct IPv4 or IPv6 inp to send back RST
+ 			 */
+ 			if ((thflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
+ 				/*
+ 				 * Note: dropwithreset makes sure we don't
+ 				 * send a RST in response to a RST.
+ 				 */
+ 				if (thflags & TH_ACK) {
+ 					tcpstat.tcps_badsyn++;
+ 					goto maybedropwithreset;
+ 				}
+ 				goto drop;
+ 			}
  			tp->t_state = TCPS_LISTEN;
  			tp->t_flags |= tp0->t_flags & (TF_NOPUSH|TF_NOOPT);
  


-- 
Jean-Luc RICHIER (Jean-Luc.Richier@Imag.Fr  richier@imag.fr)
Laboratoire Logiciels, Systemes et Reseaux (LSR-IMAG)
IMAG-CAMPUS, BP 72, F-38402 St Martin d'Heres Cedex
Tel : +33 4 76 82 72 32 Fax : +33 4 76 82 72 87

>Description:
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:

From: Mark Valentine <mark@thuvia.demon.co.uk>
To: Jean-Luc.Richier@imag.fr, FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/22866: INET6 sockets which are INET compatible lose packets
Date: Mon, 29 Apr 2002 22:05:43 +0100 (BST)

 FreeBSD-CURRENT now seems to have some similar code to that in the
 submitted patch applied.  Is there still a problem?
 
                 Cheers,
 
                 Mark.
 
 -- 
 Mark Valentine, Thuvia Labs <mark@thuvia.co.uk>       <http://www.thuvia.co.uk>
 "Tigers will do ANYTHING for a tuna fish sandwich."       Mark Valentine uses
 "We're kind of stupid that way."   *munch* *munch*        and endorses FreeBSD
   -- <http://www.calvinandhobbes.com>                  <http://www.freebsd.org>

From: Mark Valentine <mark@thuvia.demon.co.uk>
To: Jean-Luc.Richier@imag.fr, FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/22866: INET6 sockets which are INET compatible lose packets
Date: Tue, 30 Apr 2002 18:03:47 +0100 (BST)

 I wrote:
 > FreeBSD-CURRENT now seems to have some similar code to that in the
 > submitted patch applied.  Is there still a problem?
 
 My apologies, I misread the code.  I don't think this issue has been
 addressed.
 
 It may be more effective to take it up directly with the KAME folks.
 
 		Cheers,
 
 		Mark.
 
 -- 
 Mark Valentine, Thuvia Labs <mark@thuvia.co.uk>       <http://www.thuvia.co.uk>
 "Tigers will do ANYTHING for a tuna fish sandwich."       Mark Valentine uses
 "We're kind of stupid that way."   *munch* *munch*        and endorses FreeBSD
   -- <http://www.calvinandhobbes.com>                  <http://www.freebsd.org>

From: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
To: Mark Valentine <mark@thuvia.demon.co.uk>,
	FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/22866: INET6 sockets which are INET compatible lose packets
Date: Thu, 30 May 2002 15:44:40 +0200 (MEST)

 In your mail dated Mon, 29 Apr 2002:
 
 FreeBSD-CURRENT now seems to have some similar code to that in the
 submitted patch applied.  Is there still a problem?
 
                 Cheers,
                 Mark.
 
 In your mail dated Mon, 20 Apr 2002:
 >I wrote:
 >> FreeBSD-CURRENT now seems to have some similar code to that in the
 >> submitted patch applied.  Is there still a problem?
 >
 >My apologies, I misread the code.  I don't think this issue has been
 >addressed.
 >
 >It may be more effective to take it up directly with the KAME folks.
 >
 >		Cheers,
 >		Mark.
 >
 In fact, you are right. Mods done in netinet/ip_output.c and
 netinet6/ip6_output.c betwwen 4.5 and 4.6 on replacing cached routes
 solve most of the problem. 
 
 There are still problems in the managment of socket wrt IPv4mapped addresses
 but the most annoying one (dirty route structures which cannot be corrected)
 is solved.
 As most of this suggested patch is mow irrelevant, I suggest that one should
 close this patch, and I shall submit new bugs reports with proposed patches
 for the problems I found on the new version.
 
 Sincerly
 
 
 -- 
 Jean-Luc RICHIER (Jean-Luc.Richier@Imag.Fr  richier@imag.fr)
 Laboratoire Logiciels, Systemes et Reseaux (LSR-IMAG)
 IMAG-CAMPUS, BP 72, F-38402 St Martin d'Heres Cedex
 Tel : +33 4 76 82 72 32 Fax : +33 4 76 82 72 87

From: Jean-Luc Richier <Jean-Luc.Richier@imag.fr>
To: freebsd-gnats-submit@FreeBSD.org, Jean-Luc.Richier@imag.fr
Cc:  
Subject: Re: kern/22866: Packets send on INET6 sockets compatible may be lost
Date: Sun, 14 Jul 2002 20:10:43 +0200

 As I said in my previous follow-up, I have submitted 3 bugs reports (to
 FreeBSD and KAME)
 about the current (FreeBSD4.6) state of this half corrected bug
 So one should consider this report as closed, and look to reports:
 kern/40558,  kern/40561,  and kern/40563
 
 --
 Jean-Luc RICHIER (Jean-Luc.Richier@Imag.Fr  richier@imag.fr)
 Laboratoire Logiciels, Systemes et Reseaux (LSR-IMAG)
 IMAG-CAMPUS, BP 72, F-38402 St Martin d'Heres Cedex
 Tel : +33 4 76 82 72 32 Fax : +33 4 76 82 72 87
 
 
 
State-Changed-From-To: open->closed 
State-Changed-By: dwmalone 
State-Changed-When: Wed Jul 17 16:02:49 PDT 2002 
State-Changed-Why:  
Closed at sumbitters request as the PR has been overtaken by 
the new PRs kern/40558,  kern/40561,  and kern/40563. 

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