Subject: Re: IPNAT trouble - system crashes (fwd)
To: Roger Fischer <roger@badger1.net>
From: Scott Reynolds <scottr@og.org>
List: port-mac68k
Date: 05/23/1998 09:08:48
hi folks.

there's a pretty serious problem in the NAT code when translating to a
single IP address, as in the case of NATing through a PPP link.  this
problem has been fixed for almost 2 months in NetBSD-current, but hasn't
been pulled down to the release branch due to an oversight on my part.

here's the change, which should apply directly to a 1.3 or 1.3.1 source
tree.

--scott

Index: sys/netinet/ip_nat.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_nat.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -c -r1.16 -r1.17
*** ip_nat.c	1997/11/25 03:14:11	1.16
--- ip_nat.c	1998/03/29 22:56:00	1.17
***************
*** 11,17 ****
   */
  #if !defined(lint)
  static const char sccsid[] = "@(#)ip_nat.c	1.11 6/5/96 (C) 1995 Darren Reed";
! static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.0.2.44.2.6 1997/11/24 11:35:13 darrenr Exp ";
  #endif
  
  #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
--- 11,17 ----
   */
  #if !defined(lint)
  static const char sccsid[] = "@(#)ip_nat.c	1.11 6/5/96 (C) 1995 Darren Reed";
! static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.0.2.44.2.7 1997/12/02 13:54:27 darrenr Exp ";
  #endif
  
  #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
***************
*** 523,529 ****
  u_short flags;
  int direction;
  {
! 	register u_long sum1, sum2, sumd;
  	u_short port = 0, sport = 0, dport = 0, nport = 0;
  	struct in_addr in;
  	tcphdr_t *tcp = NULL;
--- 523,529 ----
  u_short flags;
  int direction;
  {
! 	register u_long sum1, sum2, sumd, l;
  	u_short port = 0, sport = 0, dport = 0, nport = 0;
  	struct in_addr in;
  	tcphdr_t *tcp = NULL;
***************
*** 553,565 ****
  		 * If it's an outbound packet which doesn't match any existing
  		 * record, then create a new port
  		 */
  		do {
  			port = 0;
  			in.s_addr = np->in_nip;
  			if (!in.s_addr && (np->in_outmsk == 0xffffffff)) {
! 				if (nat_ifpaddr(nat, fin->fin_ifp, &in) == -1)
  					return NULL;
  			} else if (!in.s_addr && !np->in_outmsk) {
  				in.s_addr = ntohl(ip->ip_src.s_addr);
  				if (nflags & IPN_TCPUDP)
  					port = sport;
--- 553,574 ----
  		 * If it's an outbound packet which doesn't match any existing
  		 * record, then create a new port
  		 */
+ 		l = 0;
  		do {
+ 			l++;
  			port = 0;
  			in.s_addr = np->in_nip;
  			if (!in.s_addr && (np->in_outmsk == 0xffffffff)) {
! 				if ((l > 1) ||
! 				    nat_ifpaddr(nat, fin->fin_ifp, &in) == -1) {
! 					KFREE(nat);
  					return NULL;
+ 				}
  			} else if (!in.s_addr && !np->in_outmsk) {
+ 				if (l > 1) {
+ 					KFREE(nat);
+ 					return NULL;
+ 				}
  				in.s_addr = ntohl(ip->ip_src.s_addr);
  				if (nflags & IPN_TCPUDP)
  					port = sport;