Subject: Re: bin/30437: recent NATT changes breaks racoon
To: None <manu@netbsd.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: S.P.Zeidler <spz@serpens.de>
List: netbsd-bugs
Date: 10/01/2005 13:27:01
The following reply was made to PR bin/30437; it has been noted by GNATS.

From: "S.P.Zeidler" <spz@serpens.de>
To: Emmanuel Dreyfus <manu@netbsd.org>
Cc: gnats-bugs@netbsd.org
Subject: Re: bin/30437: recent NATT changes breaks racoon
Date: Sat, 1 Oct 2005 15:26:18 +0200

 Hi,
 
 -current as of 27th September, the patch seems to make stuff work
 (at least my laptop does have a connection :)
 
 regards,
 	spz
 
 Thus wrote Emmanuel Dreyfus (manu@netbsd.org):
 
 > Here is an updated kernel patch that fixes the problem at mine.
 > I have to check that NAT-T still works with that patch, and even
 > with multiple endpoints behind the NAT. Help is welcome as I currently
 > lack the hardware.
 > 
 > -- 
 > Emmanuel Dreyfus
 > manu@netbsd.org
 
 > Index: key.c
 > ===================================================================
 > RCS file: /cvsroot/src/sys/netkey/key.c,v
 > retrieving revision 1.135
 > diff -U2 -r1.135 key.c
 > --- key.c	3 Jul 2005 22:57:09 -0000	1.135
 > +++ key.c	26 Sep 2005 17:24:35 -0000
 > @@ -387,8 +387,10 @@
 >  static struct mbuf *key_setsadbxport __P((u_int16_t, u_int16_t));
 >  static struct mbuf *key_setsadbxtype __P((u_int16_t));
 > +#endif
 >  static void key_porttosaddr __P((struct sockaddr *, u_int16_t));
 >  #define KEY_PORTTOSADDR(saddr, port) \
 > -     key_porttosaddr((struct sockaddr *)(saddr), (port))
 > -#endif
 > +	key_porttosaddr((struct sockaddr *)(saddr), (port))
 > +static int key_checksalen __P((const struct sockaddr *));
 > +#define KEY_CHECKSALEN(saddr) key_checksalen((const struct sockaddr *)(saddr))
 >  static struct mbuf *key_setsadblifetime __P((u_int16_t, u_int32_t,
 >  	u_int64_t, u_int64_t, u_int64_t));
 > @@ -804,5 +806,7 @@
 >  			bcopy(src, &sin.sin_addr,
 >  			    sizeof(sin.sin_addr));
 > +#ifdef IPSEC_NAT_T
 >  			sin.sin_port = sport;
 > +#endif
 >  			if (key_sockaddrcmp((struct sockaddr*)&sin,
 >  			    (struct sockaddr *)&sav->sah->saidx.src, 
 > @@ -817,5 +821,7 @@
 >  			bcopy(src, &sin6.sin6_addr,
 >  			    sizeof(sin6.sin6_addr));
 > +#ifdef IPSEC_NAT_T
 >  			sin6.sin6_port = sport;
 > +#endif
 >  			if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
 >  				/* kame fake scopeid */
 > @@ -845,5 +851,7 @@
 >  			bcopy(dst, &sin.sin_addr,
 >  			    sizeof(sin.sin_addr));
 > +#ifdef IPSEC_NAT_T
 >  			sin.sin_port = dport;
 > +#endif
 >  			if (key_sockaddrcmp((struct sockaddr*)&sin,
 >  			    (struct sockaddr *)&sav->sah->saidx.dst,
 > @@ -858,5 +866,7 @@
 >  			bcopy(dst, &sin6.sin6_addr,
 >  			    sizeof(sin6.sin6_addr));
 > +#ifdef IPSEC_NAT_T
 >  			sin6.sin6_port = dport;
 > +#endif
 >  			if (IN6_IS_SCOPE_LINKLOCAL(&sin6.sin6_addr)) {
 >  				/* kame fake scopeid */
 > @@ -4039,5 +4049,5 @@
 >  	return port;
 >  }
 > -
 > +#endif /* IPSEC_NAT_T */
 >  
 >  /*
 > @@ -4065,5 +4075,6 @@
 >  #endif
 >  	default:
 > -		printf("key_porttosaddr: unexpected address family\n");
 > +		printf("key_porttosaddr: unexpected address family %d\n", 
 > +		    saddr->sa_family);
 >  		break;
 >  	}
 > @@ -4071,5 +4082,32 @@
 >  	return;
 >  }
 > -#endif /* IPSEC_NAT_T */
 > +
 > +/*
 > + * Safety check sa_len 
 > + */
 > +static int 
 > +key_checksalen(saddr)
 > +	const struct sockaddr *saddr;
 > +{
 > +	switch (saddr->sa_family) {
 > +	case AF_INET:
 > +		if (saddr->sa_len != sizeof(struct sockaddr_in))
 > +			return -1;
 > +		break;
 > +#ifdef INET6
 > +	case AF_INET6:
 > +		if (saddr->sa_len != sizeof(struct sockaddr_in6))
 > +			return -1;
 > +		break;
 > +#endif
 > +	default:
 > +		printf("key_checksalen: unexpected sa_family %d\n", 
 > +		    saddr->sa_family);
 > +		return -1;
 > +		break;
 > +	}
 > +
 > +	return 0;
 > +}
 >  
 >  /*
 > @@ -5029,52 +5067,18 @@
 >  	}
 >  
 > -	/* 
 > -	 * make sure if port number is zero. 
 > -	 * If using NAT-T, skip that check.
 > -	 */
 > -	switch (((struct sockaddr *)(src0 + 1))->sa_family) {
 > -	case AF_INET:
 > -		if (((struct sockaddr *)(src0 + 1))->sa_len !=
 > -		    sizeof(struct sockaddr_in))
 > -			return key_senderror(so, m, EINVAL);
 > -#ifndef IPSEC_NAT_T
 > -		((struct sockaddr_in *)(src0 + 1))->sin_port = 0;
 > -#endif
 > -		break;
 > -	case AF_INET6:
 > -		if (((struct sockaddr *)(src0 + 1))->sa_len !=
 > -		    sizeof(struct sockaddr_in6))
 > -			return key_senderror(so, m, EINVAL);
 > -#ifndef IPSEC_NAT_T
 > -		((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0;
 > -#endif
 > -		break;
 > -	default:
 > -		; /*???*/
 > -	}
 > -	switch (((struct sockaddr *)(dst0 + 1))->sa_family) {
 > -	case AF_INET:
 > -		if (((struct sockaddr *)(dst0 + 1))->sa_len !=
 > -		    sizeof(struct sockaddr_in))
 > -			return key_senderror(so, m, EINVAL);
 > -#ifndef IPSEC_NAT_T
 > -		((struct sockaddr_in *)(dst0 + 1))->sin_port = 0;
 > -#endif
 > -		break;
 > -	case AF_INET6:
 > -		if (((struct sockaddr *)(dst0 + 1))->sa_len !=
 > -		    sizeof(struct sockaddr_in6))
 > -			return key_senderror(so, m, EINVAL);
 > -#ifndef IPSEC_NAT_T
 > -		((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0;
 > -#endif
 > -		break;
 > -	default:
 > -		; /*???*/
 > -	}
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 >  
 > -	/* XXX boundary check against sa_len */
 >  	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure port numbers are set to zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* SPI allocation */
 >  	spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
 > @@ -5327,7 +5331,18 @@
 >  	dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	
 >  	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* get a SA header */
 >  	if ((sah = key_getsah(&saidx)) == NULL) {
 > @@ -5577,7 +5592,18 @@
 >  	dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	
 >  	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* get a SA header */
 >  	if ((newsah = key_getsah(&saidx)) == NULL) {
 > @@ -5866,7 +5892,18 @@
 >  	dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +
 >  	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* get a SA header */
 >  	LIST_FOREACH(sah, &sahtree, chain) {
 > @@ -5933,7 +5970,18 @@
 >  	dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +
 >  	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	LIST_FOREACH(sah, &sahtree, chain) {
 >  		if (sah->state == SADB_SASTATE_DEAD)
 > @@ -6042,7 +6090,18 @@
 >  	dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +
 >  	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* get a SA header */
 >  	LIST_FOREACH(sah, &sahtree, chain) {
 > @@ -6733,7 +6792,18 @@
 >  	dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
 >  
 > -	/* XXX boundary check against sa_len */
 > +	/* sa_len safety check */
 > +	if (KEY_CHECKSALEN(src0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +	if (KEY_CHECKSALEN(dst0 + 1) != 0)
 > +		return key_senderror(so, m, EINVAL);
 > +
 >  	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 >  
 > +	/* If not using NAT-T, make sure if port number is zero. */
 > +#ifndef IPSEC_NAT_T
 > +	KEY_PORTTOSADDR(&saidx.src, 0);
 > +	KEY_PORTTOSADDR(&saidx.dst, 0);
 > +#endif
 > +
 >  	/* get a SA index */
 >  	LIST_FOREACH(sah, &sahtree, chain) {
 
 
 -- 
 spz@serpens.de (S.P.Zeidler)