[4041] in linux-net channel archive
Re: port remapping
daemon@ATHENA.MIT.EDU (Jan Vicherek)
Fri Aug 16 06:15:00 1996
Date: Thu, 15 Aug 1996 21:47:12 -0400 (EDT)
From: Jan Vicherek <honza@ied.com>
To: System Development <devel@vrml.k12.la.us>
cc: linux-net@vger.rutgers.edu
In-Reply-To: <199608141621.LAA03287@vpsd5.vrml.k12.la.us>
On Wed, 14 Aug 1996, System Development wrote:
> i am interested in remapping service ports on a linux gateway to
> different ports on another machine. For instance,
>
> 198.180.155.8:81 -> 198.180.155.7:80
> 198.180.155.8:82 -> 198.180.155.6:80
>
> any suggestions?
sure.
--- Gospel is the power of God for all who believe - (Rom. 1:16) ---
Jan Vicherek .............. Check out: http://www.ied.com/~honza/fslu/
Interactive Electronic Design Inc. . "To some, nothing is impossible."
http://www.ied.com/~honza ................... finger honza@www.ied.com
_________ bounce.c __________________________
/* Distribution: Public */
/* Copyright: Held by the respective contributors */
/* Posted to USENET September '93 by Mark mark@cairo.anu.edu.au */
/* This file was telserv.c, part of the Telnet Server package v. 1.0,
written by "Hal-9000". Much of that package was developed by Richard
Stephens and his thanks go to "Xanadude" for providing him with that
section. Performance fix by Darren Reed. */
/* Reworked to add concurrency, password checking and destination selection
on the fly. - Mark 31st Aug 93
Now its a IRC bouncer
Compiled and tested on:
HPUX 9.01 9000/700 series NeXTStep 3.1 NeXT 68040
OSx Pyramid 90x BSD universe SunOS 5.2 sun4c
Ultrix 4.3 DEC RISC
To compile, type "cc -O -s ircb.c -o ircb".
Michael Morgan used "gcc -O -s bounce -o bounce"
*/
/*+ IRC Bouncer hacks +*/
#define ircserv "irc.escape.com"
#define ircport 6667
#define ircbnc 10000
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#define QLEN 5
char sbuf[4096], cbuf[4096];
extern int errno;
void reaper();
extern char *sys_errlist[];
int main();
void telcli();
int IRCBNC=0,IRCPORT=0;
char IRCSERV[100];
int main(argc, argv)
int argc;
char *argv[];
{
char string_user[20];
int srv_fd, rem_fd, rem_len, opt = 1;
struct sockaddr_in rem_addr, srv_addr;
#if !defined(SVR4) && !defined(POSIX) && !defined(linux) && !defined(__386BSD__) && !defined(hpux)
union wait status;
#else
int status;
#endif /* !defined(SVR4) */
printf ("\n\rIRC IP/Port Bouncer * Modified by Bourbon");
printf ("\n\rOriginal code by Mark mark@cairo.anu.edu.au\n\r");
printf ("Weak command line code added by Michael Morgan ");
printf ("mlmorgan@rice.edu\n\r");
if (argc>1 && !strcmp(argv[1],"-s"))
{
printf ("\n\rEnter IRC Server Port [%i]: ",ircport);
gets(string_user);
if (string_user[0]==0)
IRCPORT=ircport;
else
IRCPORT=atoi(string_user);
printf ("\n\rEnter Bouncer Port [%i]: ",ircbnc);
gets(string_user);
if (string_user[0]==0)
IRCBNC=ircbnc;
else
IRCBNC=atoi(string_user);
printf ("\n\rEnter IRC Server IP or address [%s]: ",ircserv);
gets(IRCSERV);
if (IRCSERV[0]==0) strcpy (IRCSERV,ircserv);
}
/* Michael Morgan's attempt at a simple command line interface */
else if (argc==5 && !strcmp(argv[1],"-c"))
{
IRCBNC=atoi(argv[2]);
strcpy (IRCSERV,argv[3]);
IRCPORT=atoi(argv[4]);
}
/* End of my try */
else
{
IRCPORT=ircport;
IRCBNC=ircbnc;
strcpy(IRCSERV,ircserv);
}
if (argc>1 && !strcmp(argv[1],"-h"))
{
printf ("\n\rUsage: %s [-h] [-s] [-c ",argv[0]);
printf ("<bounce port> <remote machine> <remote port>]");
printf ("\n\r-s Set ports&IP interactively");
printf ("\n\r-c Set ports&IP on command line");
printf ("\n\r-h Display this help\n\r");
printf ("\n\rCurrent Defaults: 127.0.0.1:%i -> %s:%i\n\n\r",ircbnc,ircserv,ircport);
exit(0);
}
printf ("\n\rRedirecting port %i of this machine to port %i of %s\n\n\r"
,IRCBNC,IRCPORT,IRCSERV);
bzero((char *) &rem_addr, sizeof(rem_addr));
bzero((char *) &srv_addr, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
srv_addr.sin_port = htons(IRCBNC); /*+ IRC Bouncer hack +*/
srv_fd = socket(PF_INET, SOCK_STREAM, 0);
if (bind(srv_fd, (struct sockaddr *) &srv_addr, sizeof(srv_addr)) == -1) {
perror("bind");
exit(-1);
}
listen(srv_fd, QLEN);
close(0); close(1); close(2);
#ifdef TIOCNOTTY
if ((rem_fd = open("/dev/tty", O_RDWR)) >= 0) {
ioctl(rem_fd, TIOCNOTTY, (char *)0);
close(rem_fd);
}
#endif
if (fork()) exit(0);
while (1) {
rem_len = sizeof(rem_addr);
rem_fd=accept(srv_fd, (struct sockaddr *) &rem_addr, &rem_len);
if (rem_fd < 0) {
if (errno == EINTR) continue;
exit(-1);
}
switch(fork()) {
case 0: /* child process */
close(srv_fd); /* close original socket */
telcli(rem_fd); /* process the request */
close(rem_fd);
exit(0);
break;
default:
close(rem_fd); /* parent process */
if (fork()) exit(0); /* let init worry about children */
break;
case -1:
fprintf(stderr, "\n\rfork: %s\n\r", sys_errlist[errno]);
break;
}
}
}
void telcli(source)
int source;
{
int dest;
int found;
struct sockaddr_in sa;
struct hostent *hp;
struct servent *sp;
char gethost[100];
char getport[100];
char string[100];
hp = gethostbyname(IRCSERV);
if (hp) {
found++;
#if !defined(h_addr) /* In 4.3, this is a #define */
#if defined(hpux) || defined(NeXT) || defined(ultrix) || defined(POSIX)
memcpy((caddr_t)&sa.sin_addr, hp->h_addr_list[0], hp->h_length);
#else
bcopy(hp->h_addr_list[0], &sa.sin_addr, hp->h_length);
#endif
#else /* defined(h_addr) */
#if defined(hpux) || defined(NeXT) || defined(ultrix) || defined(POSIX)
memcpy((caddr_t)&sa.sin_addr, hp->h_addr, hp->h_length);
#else
bcopy(hp->h_addr, &sa.sin_addr, hp->h_length);
#endif
#endif /* defined(h_addr) */
} else {
if (inet_addr(gethost) == -1) {
found = 0;
sprintf(string, "Didnt find address for %s\r\n", gethost);
write(source, string, strlen(string));
} else {
found++;
sa.sin_addr.s_addr = inet_addr(gethost);
}
}
sa.sin_family = AF_INET;
sa.sin_port = htons((unsigned) IRCPORT);
if (sa.sin_port == 0) {
sp = getservbyname(getport, "tcp");
if (sp)
sa.sin_port = sp->s_port;
else {
sprintf(string, "%s: bad port number\r\n", getport);
write(source, string, strlen(string));
return;
}
}
if ((dest = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("telcli: socket");
exit(1);
}
connect(dest, (struct sockaddr *) &sa, sizeof(sa));
#ifdef FNDELAY
fcntl(source,F_SETFL,fcntl(source,F_GETFL,0)|FNDELAY);
fcntl(dest,F_SETFL,fcntl(dest,F_GETFL,0)|FNDELAY);
#else
fcntl(source,F_SETFL,O_NDELAY);
fcntl(dest,F_SETFL,O_NDELAY);
#endif
communicate(dest,source);
close(dest);
exit(0);
}
communicate(sfd,cfd) {
char *chead, *ctail, *shead, *stail;
int num, nfd, spos, cpos;
extern int errno;
fd_set rd, wr;
chead = ctail = cbuf;
cpos = 0;
shead = stail = sbuf;
spos = 0;
while (1) {
FD_ZERO(&rd);
FD_ZERO(&wr);
if (spos < sizeof(sbuf)-1) FD_SET(sfd, &rd);
if (ctail > chead) FD_SET(sfd, &wr);
if (cpos < sizeof(cbuf)-1) FD_SET(cfd, &rd);
if (stail > shead) FD_SET(cfd, &wr);
nfd = select(256, &rd, &wr, 0, 0);
if (nfd <= 0) continue;
if (FD_ISSET(sfd, &rd)) {
num=read(sfd,stail,sizeof(sbuf)-spos);
if ((num==-1) && (errno != EWOULDBLOCK)) return;
if (num==0) return;
if (num>0) {
spos += num;
stail += num;
if (!--nfd) continue;
}
}
if (FD_ISSET(cfd, &rd)) {
num=read(cfd,ctail,sizeof(cbuf)-cpos);
if ((num==-1) && (errno != EWOULDBLOCK)) return;
if (num==0) return;
if (num>0) {
cpos += num;
ctail += num;
if (!--nfd) continue;
}
}
if (FD_ISSET(sfd, &wr)) {
num=write(sfd,chead,ctail-chead);
if ((num==-1) && (errno != EWOULDBLOCK)) return;
if (num>0) {
chead += num;
if (chead == ctail) {
chead = ctail = cbuf;
cpos = 0;
}
if (!--nfd) continue;
}
}
if (FD_ISSET(cfd, &wr)) {
num=write(cfd,shead,stail-shead);
if ((num==-1) && (errno != EWOULDBLOCK)) return;
if (num>0) {
shead += num;
if (shead == stail) {
shead = stail = sbuf;
spos = 0;
}
if (!--nfd) continue;
}
}
}
}