NetBSD-5.0.2/dist/ipf/FWTK/ftp-gw.diff

*** ftp-gw.c.orig	Sun Jun 22 16:27:42 1997
--- ftp-gw.c	Sun Jun 22 17:02:16 1997
***************
*** 11,31 ****
--- 11,41 ----
   */
  static	char	RcsId[] = "$Header: /cvsroot/src/dist/ipf/FWTK/ftp-gw.diff,v 1.1 1999/12/11 22:24:01 veego Exp $";
  
+ /*
+  * Patches for IP Filter NAT extensions written by Darren Reed, 7/7/96
+  * darrenr@cyber.com.au
+  */
+ static	char	vIpFilter[] = "v3.1.11";
  
  #include	<stdio.h>
  #include	<ctype.h>
  #include	<syslog.h>
+ #include	<unistd.h>
+ #include	<fcntl.h>
  #include	<sys/signal.h>
  #include	<sys/ioctl.h>
  #include	<sys/errno.h>
  extern	int	errno;
+ #ifdef	sun
  extern	char	*sys_errlist[];
+ #endif
  #include	<arpa/ftp.h>
  #include	<arpa/telnet.h>
  #include	<sys/time.h>
  #include	<sys/types.h>
  #include	<sys/socket.h>
  #include	<netinet/in.h>
+ #include	<net/if.h>
  
  extern	char	*rindex();
  extern	char	*index();
***************
*** 36,41 ****
--- 46,54 ----
  
  #include	"firewall.h"
  
+ #include	"ip_compat.h"
+ #include	"ip_fil.h"
+ #include	"ip_nat.h"
  
  #ifndef	BSIZ
  #define	BSIZ	2048
***************
*** 83,88 ****
--- 96,103 ----
  static	int	cmd_noop();
  static	int	cmd_abor();
  static	int	cmd_passthru();
+ static	int	nat_destination();
+ static	int	connectdest();
  static	void	saveline();
  static	void	flushsaved();
  static	void	trap_sigurg();
***************
*** 317,323 ****
  			if(authallflg)
  				if(say(0,"220-Proxy first requires authentication"))
  					exit(1);
! 			sprintf(xuf,"220 %s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
  			if(say(0,xuf))
  				exit(1);
  		}
--- 332,341 ----
  			if(authallflg)
  				if(say(0,"220-Proxy first requires authentication"))
  					exit(1);
! 			sprintf(xuf,"220-%s FTP proxy (Version %s) ready.",huf,FWTK_VERSION_MINOR);
! 			if(say(0,xuf))
! 				exit(1);
! 			sprintf(xuf,"220-%s TIS ftp-gw with IP Filter %s NAT extensions",huf,vIpFilter);
  			if(say(0,xuf))
  				exit(1);
  		}
***************
*** 338,343 ****
--- 356,363 ----
  				exit(1);
  	}
  
+ 	nat_destination(0);
+ 
  	/* main loop */
  	while(1) {
  		FD_ZERO(&rdy);
***************
*** 608,619 ****
  	static char	narg[] = "501 Missing or extra username";
  	static char	noad[] = "501 Use user@site to connect via proxy";
  	char		buf[1024];
- 	char 		mbuf[512];
  	char		*p;
  	char		*dest;
  	char		*user;
  	int		x;
- 	int		msg_int;
  	short		port = FTPPORT;
  
  	/* kludgy but effective. if authorizing everything call auth instead */
--- 628,637 ----
***************
*** 643,648 ****
--- 661,687 ----
  			return(sayn(0,noad,sizeof(noad)));
  	}
  
+ 	if((rfd == -1) && (x = connectdest(dest,port)))
+ 		return x;
+ 	sprintf(buf,"USER %s",user);
+ 	if(say(rfd,buf))
+ 		return(1);
+ 	x = getresp(rfd,buf,sizeof(buf),1);
+ 	if(sendsaved(0,x))
+ 		return(1);
+ 	return(say(0,buf));
+ }
+ 
+ static int
+ connectdest(dest,port)
+ char *dest;
+ short port;
+ {
+ 	char		buf[1024];
+ 	char 		mbuf[512];
+ 	int		msg_int;
+ 	int		x;
+ 
  	if(*dest == '\0')
  		dest = "localhost";
  
***************
*** 685,693 ****
  		char	ebuf[512];
  
  		strcpy(ebuf,buf);
! 		sprintf(buf,"521 %s: %s",dest,ebuf);
  		return(say(0,buf));
  	}
  	sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
  	saveline(buf);
  
--- 724,733 ----
  		char	ebuf[512];
  
  		strcpy(ebuf,buf);
! 		sprintf(buf,"521 %s,%d: %s",dest,ntohs(port),ebuf);
  		return(say(0,buf));
  	}
+ 
  	sprintf(buf,"----GATEWAY CONNECTED TO %s----",dest);
  	saveline(buf);
  
***************
*** 698,711 ****
  		return(say(0,buf));
  	}
  	saveline(buf);
! 
! 	sprintf(buf,"USER %s",user);
! 	if(say(rfd,buf))
! 		return(1);
! 	x = getresp(rfd,buf,sizeof(buf),1);
! 	if(sendsaved(0,x))
! 		return(1);
! 	return(say(0,buf));
  }
  
  
--- 738,745 ----
  		return(say(0,buf));
  	}
  	saveline(buf);
! 	sendsaved(0,-1);
! 	return 0;
  }
  
  
***************
*** 1591,1593 ****
--- 1625,1671 ----
  	dup(nread);
  }
  #endif
+ 
+ 
+ static int
+ nat_destination(fd)
+ int fd;
+ {
+ 	struct	sockaddr_in	laddr, faddr;
+ 	struct	natlookup	natlookup;
+ 	char	*dest;
+ 	int	slen, natfd;
+ 
+ 	bzero((char *)&laddr, sizeof(laddr));
+ 	bzero((char *)&faddr, sizeof(faddr));
+ 	slen = sizeof(laddr);
+ 	if(getsockname(fd,(struct sockaddr *)&laddr,&slen) < 0) {
+ 		perror("getsockname");
+ 		exit(1);
+ 	}
+ 	slen = sizeof(faddr);
+ 	if(getpeername(fd,(struct sockaddr *)&faddr,&slen) < 0) {
+ 		perror("getsockname");
+ 		exit(1);
+ 	}
+ 
+ 	natlookup.nl_inport = laddr.sin_port;
+ 	natlookup.nl_outport = faddr.sin_port;
+ 	natlookup.nl_inip = laddr.sin_addr;
+ 	natlookup.nl_outip = faddr.sin_addr;
+ 	natlookup.nl_flags = IPN_TCP;
+ 	if((natfd = open(IPL_NAT, O_RDONLY)) < 0) {
+ 		perror("open");
+ 		exit(1);
+ 	}
+ 	if(ioctl(natfd, SIOCGNATL, &natlookup) == -1) {
+ 		syslog(LOG_ERR, "SIOCGNATL failed: %m\n");
+ 		close(natfd);
+ 		if(say(0,"220 Ready"))
+ 			exit(1);
+ 		return 0;
+ 	}
+ 	close(natfd);
+ 	return connectdest(inet_ntoa(natlookup.nl_realip),
+ 			   ntohs(natlookup.nl_realport));
+ }