A small unix program to redirect TCP connection to another server and/or port.
/*
* tcpredir.c: redirect TCP connection to another server and/or port
*
* Original author: abbelf@usa.net
*
* $Id: tcpredir.c,v 1.3 2000/12/01 00:15:28 hanhua Exp $
*/
/*
* Compilation:
* cc -o tcpredir tcpredir.c [-lsocket -lnsl]
*
* Usage:
* tcpredir 4000 202.112.26.39 2323
* To redirect connection accepted on port 4000 to 202.112.26.39:2323
* tcpredir 4000 202.112.26.39 2323 1800
* To redirect connection and cut off the connection in half an hour
* tcpredir 4000 202.112.26.39 2323 0 2
* To redirect connection, monitor mode 2, without cutting off connection
*
* Comments:
* Monitor mode including 1(hex mode) 2(c string mode).
* This program goes into background automatically by folking a sub-process.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void reaper( int i )
{
int status;
while ( wait3( &status, WNOHANG, 0 ) > 0 )
;
}
int dflag = 0;
#define BUF_SIZE 4096
int main( int argc, char *argv[] )
{
int sock, cfd, sinsize, sfd, pid, idle;
struct sockaddr_in sin;
fd_set readfds;
unsigned char buf[BUF_SIZE];
struct timeval tv;
int n;
if ( 4 != argc && 5 != argc && 6 != argc )
{
char *p = strrchr( argv[0], '/' );
fprintf( stderr, "Usage: %s <port> <remote_ip> <remote_port>"
" [<idle_seconds> [<d_flag>]]\n",
p ? p+1 : argv[0] );
return 0;
}
if ( 6 == argc )
dflag = atoi( argv[5] );
if ( 5 == argc || 6 == argc )
idle = atoi( argv[4] );
else
idle = 0;
if ( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
perror( "socket" );
return -1;
}
sin.sin_family = AF_INET;
sin.sin_port = htons( atoi( argv[1] ) );
sin.sin_addr.s_addr = INADDR_ANY;
if ( bind( sock, (struct sockaddr *) &sin, sizeof(sin) ) < 0 )
{
perror( "bind" );
return -1;
}
sinsize = sizeof(sin);
if ( getsockname( sock, (struct sockaddr *) & sin, &sinsize ) == -1 )
{
perror( "getsockname" );
return -1;
}
if ( listen( sock, 5 ) == -1 )
{
perror( "listen" );
return -1;
}
if ( ( pid = fork() ) )
{
printf( "%d\n", pid );
return 0;
}
setpgid( 0, 0 );
signal( SIGHUP, SIG_IGN );
signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
signal( SIGALRM, SIG_IGN );
signal( SIGURG, SIG_IGN );
signal( SIGTSTP, SIG_IGN );
signal( SIGTTIN, SIG_IGN );
signal( SIGTTOU, SIG_IGN );
for(;;)
{
signal( SIGCHLD, reaper );
sinsize = sizeof(sin);
sfd = accept( sock, (struct sockaddr *)&sin, &sinsize );
if ( sfd == -1 )
continue;
pid = fork();
if ( 0 == pid )
break;
close( sfd );
}
close( sock );
sin.sin_family = PF_INET;
sin.sin_addr.s_addr = inet_addr( argv[2] );
sin.sin_port = htons( atoi( argv[3] ) );
cfd = socket( sin.sin_family, SOCK_STREAM, 0 );
if ( cfd < 0 )
{
char *errmsg = "Socket error\n";
send( sfd, errmsg, strlen( errmsg ), 0 );
return -1;
}
if ( connect( cfd, (struct sockaddr *) &sin, sizeof sin) )
{
char *errmsg = "Connecting failed\n";
send( sfd, errmsg, strlen( errmsg ), 0 );
return -1;
}
for (;;)
{
tv.tv_sec = idle;
tv.tv_usec = 0;
FD_ZERO( &readfds );
FD_SET( sfd, &readfds );
FD_SET( cfd, &readfds );
if ( select( sfd>cfd ? sfd+1 : cfd+1, &readfds, NULL, NULL,
idle > 0 ? &tv : NULL ) <= 0 )
break;
if ( FD_ISSET( cfd, &readfds ) )
{
n = recv( cfd, buf, BUF_SIZE, 0 );
if (n <= 0)
break;
send( sfd, buf, n, 0 );
}
if ( FD_ISSET( sfd, &readfds ) )
{
n = recv( sfd, buf, BUF_SIZE, 0 );
if (n <= 0)
break;
send( cfd, buf, n, 0 );
}
}
close( cfd );
close( sfd );
/* printf( "\n" ); */
exit( 0 );
return 0;
}
fork version
/*
* tcpredir.c: redirect TCP connection to another server and/or port
*
* Original author: abbelf@usa.net
*
* $Id: tcpredir.c,v 1.3 2000/12/01 00:15:28 hanhua Exp $
*/
/*
* Compilation:
* cc -o tcpredir tcpredir.c [-lsocket -lnsl]
*
* Usage:
* tcpredir 4000 202.112.26.39 2323
* To redirect connection accepted on port 4000 to 202.112.26.39:2323
* tcpredir 4000 202.112.26.39 2323 1800
* To redirect connection and cut off the connection in half an hour
* tcpredir 4000 202.112.26.39 2323 0 2
* To redirect connection, monitor mode 2, without cutting off connection
*
* Comments:
* Monitor mode including 1(hex mode) 2(c string mode).
* This program goes into background automatically by folking a sub-process.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void reaper( int i )
{
int status;
while ( wait3( &status, WNOHANG, 0 ) > 0 )
;
}
int dflag = 0;
#define BUF_SIZE 4096
int main( int argc, char *argv[] )
{
int sock, cfd, sinsize, sfd, pid, idle;
struct sockaddr_in sin;
fd_set readfds;
unsigned char buf[BUF_SIZE];
struct timeval tv;
int n;
if ( 4 != argc && 5 != argc && 6 != argc )
{
char *p = strrchr( argv[0], '/' );
fprintf( stderr, "Usage: %s <port> <remote_ip> <remote_port>"
" [<idle_seconds> [<d_flag>]]\n",
p ? p+1 : argv[0] );
return 0;
}
if ( 6 == argc )
dflag = atoi( argv[5] );
if ( 5 == argc || 6 == argc )
idle = atoi( argv[4] );
else
idle = 0;
if ( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
perror( "socket" );
return -1;
}
sin.sin_family = AF_INET;
sin.sin_port = htons( atoi( argv[1] ) );
sin.sin_addr.s_addr = INADDR_ANY;
if ( bind( sock, (struct sockaddr *) &sin, sizeof(sin) ) < 0 )
{
perror( "bind" );
return -1;
}
sinsize = sizeof(sin);
if ( getsockname( sock, (struct sockaddr *) & sin, &sinsize ) == -1 )
{
perror( "getsockname" );
return -1;
}
if ( listen( sock, 5 ) == -1 )
{
perror( "listen" );
return -1;
}
if ( ( pid = fork() ) )
{
printf( "%d\n", pid );
return 0;
}
setpgid( 0, 0 );
signal( SIGHUP, SIG_IGN );
signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
signal( SIGALRM, SIG_IGN );
signal( SIGURG, SIG_IGN );
signal( SIGTSTP, SIG_IGN );
signal( SIGTTIN, SIG_IGN );
signal( SIGTTOU, SIG_IGN );
for(;;)
{
signal( SIGCHLD, reaper );
sinsize = sizeof(sin);
sfd = accept( sock, (struct sockaddr *)&sin, &sinsize );
if ( sfd == -1 )
continue;
pid = fork();
if ( 0 == pid )
break;
close( sfd );
}
close( sock );
sin.sin_family = PF_INET;
sin.sin_addr.s_addr = inet_addr( argv[2] );
sin.sin_port = htons( atoi( argv[3] ) );
cfd = socket( sin.sin_family, SOCK_STREAM, 0 );
if ( cfd < 0 )
{
char *errmsg = "Socket error\n";
send( sfd, errmsg, strlen( errmsg ), 0 );
return -1;
}
if ( connect( cfd, (struct sockaddr *) &sin, sizeof sin) )
{
char *errmsg = "Connecting failed\n";
send( sfd, errmsg, strlen( errmsg ), 0 );
return -1;
}
if(fork() == 0) { // child
for (;;)
{
n = recv( cfd, buf, BUF_SIZE, 0 );
if (n <= 0) break;
send( sfd, buf, n, 0 );
}
} else {
for (;;)
{
n = recv( sfd, buf, BUF_SIZE, 0 );
if (n <= 0) break;
send( cfd, buf, n, 0 );
}
}
close( cfd );
close( sfd );
/* printf( "\n" ); */
exit( 0 );
return 0;
}
원본: http://abbelfy.tripod.com/tcpredir.c
/* * tcpredir.c: redirect TCP connection to another server and/or port * * Author: abbelf@usa.net * * $Id: tcpredir.c,v 1.3 2000/12/01 00:15:28 hanhua Exp $ */ /* * Compilation: * cc -o tcpredir tcpredir.c [-lsocket -lnsl] * * Usage: * tcpredir 4000 202.112.26.39 2323 * To redirect connection accepted on port 4000 to 202.112.26.39:2323 * tcpredir 4000 202.112.26.39 2323 1800 * To redirect connection and cut off the connection in half an hour * tcpredir 4000 202.112.26.39 2323 0 2 * To redirect connection, monitor mode 2, without cutting off connection * * Comments: * Monitor mode including 1(hex mode) 2(c string mode). * This program goes into background automatically by folking a sub-process. */ #include <stdio.h> #include <ctype.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/resource.h> #include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> void reaper( int i ) { int status; while ( wait3( &status, WNOHANG, 0 ) > 0 ) ; } int dflag = 0; void debug( unsigned char ch, int n ) { static char buf[2][82]; static int p[2] = { 0, 0 }; if ( dflag == 0 ) return; if ( dflag == 1 ) { printf("%c%02X", n ? '>' : '<', ch ); return; } if ( dflag == 2 ) { switch( ch ) { case '\r': buf[n][p[n]++] = '\\'; buf[n][p[n]++] = 'r'; break; case '\n': buf[n][p[n]++] = '\\'; buf[n][p[n]++] = 'n'; buf[n][p[n]] = '\0'; p[n] = 78; break; case '\t': buf[n][p[n]++] = '\\'; buf[n][p[n]++] = 't'; break; case '\\': buf[n][p[n]++] = '\\'; buf[n][p[n]++] = '\\'; break; default: if ( ch >= 0x20 && ch < 0x7f ) { buf[n][p[n]++] = ch; } else { buf[n][p[n]++] = '\\'; buf[n][p[n]++] = 'x'; buf[n][p[n]++] = ch/16 >= 10 ? ch/16 + 'A' - 10 : ch/16 + '0'; buf[n][p[n]++] = ch%16 >= 10 ? ch%16 + 'A' - 10 : ch%16 + '0'; } } if ( p[n] >= 76 ) { buf[n][p[n]] = '\0'; printf( "%c%s\n", n ? '>' : '<', buf[n] ); p[n] = 0; } } } int main( int argc, char *argv[] ) { int sock, cfd, sinsize, sfd, pid, idle; struct sockaddr_in sin; fd_set readfds; unsigned char ch; struct timeval tv; if ( 4 != argc && 5 != argc && 6 != argc ) { char *p = strrchr( argv[0], '/' ); fprintf( stderr, "Usage: %s <port> <remote_ip> <remote_port>" " [<idle_seconds> [<d_flag>]]\n", p ? p+1 : argv[0] ); return 0; } if ( 6 == argc ) dflag = atoi( argv[5] ); if ( 5 == argc || 6 == argc ) idle = atoi( argv[4] ); else idle = 0; if ( ( sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror( "socket" ); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons( atoi( argv[1] ) ); sin.sin_addr.s_addr = INADDR_ANY; if ( bind( sock, (struct sockaddr *) &sin, sizeof(sin) ) < 0 ) { perror( "bind" ); return -1; } sinsize = sizeof(sin); if ( getsockname( sock, (struct sockaddr *) & sin, &sinsize ) == -1 ) { perror( "getsockname" ); return -1; } if ( listen( sock, 5 ) == -1 ) { perror( "listen" ); return -1; } if ( ( pid = fork() ) ) { printf( "%d\n", pid ); return 0; } setpgid( 0, 0 ); signal( SIGHUP, SIG_IGN ); signal( SIGINT, SIG_IGN ); signal( SIGQUIT, SIG_IGN ); signal( SIGALRM, SIG_IGN ); signal( SIGURG, SIG_IGN ); signal( SIGTSTP, SIG_IGN ); signal( SIGTTIN, SIG_IGN ); signal( SIGTTOU, SIG_IGN ); for(;;) { signal( SIGCHLD, reaper ); sinsize = sizeof(sin); sfd = accept( sock, (struct sockaddr *)&sin, &sinsize ); if ( sfd == -1 ) continue; pid = fork(); if ( 0 == pid ) break; close( sfd ); } close( sock ); sin.sin_family = PF_INET; sin.sin_addr.s_addr = inet_addr( argv[2] ); sin.sin_port = htons( atoi( argv[3] ) ); cfd = socket( sin.sin_family, SOCK_STREAM, 0 ); if ( cfd < 0 ) { char *errmsg = "Socket error\n"; send( sfd, errmsg, strlen( errmsg ), 0 ); return -1; } if ( connect( cfd, (struct sockaddr *) &sin, sizeof sin) ) { char *errmsg = "Connecting failed\n"; send( sfd, errmsg, strlen( errmsg ), 0 ); return -1; } for (;;) { tv.tv_sec = idle; tv.tv_usec = 0; FD_ZERO( &readfds ); FD_SET( sfd, &readfds ); FD_SET( cfd, &readfds ); if ( select( sfd>cfd ? sfd+1 : cfd+1, &readfds, NULL, NULL, idle > 0 ? &tv : NULL ) <= 0 ) break; if ( FD_ISSET( cfd, &readfds ) ) { if ( 1 != recv( cfd, &ch, 1, 0 ) ) break; send( sfd, &ch, 1, 0 ); debug( ch, 1 ); } if ( FD_ISSET( sfd, &readfds ) ) { if ( 1 != recv( sfd, &ch, 1, 0 ) ) break; send( cfd, &ch, 1, 0 ); debug( ch, 0 ); } } close( cfd ); close( sfd ); /* printf( "\n" ); */ exit( 0 ); return 0; }
'Programming' 카테고리의 다른 글
(C, Unix) Joinc: select를 이용한 입출력 다중화 (0) | 2013.04.26 |
---|---|
(C) Unix Daemon Server Programming (0) | 2013.04.24 |
C++ 0x : 람다(Lambda) (0) | 2013.04.14 |
(Visual C++ 2010) Examples of Lambda Expressions (0) | 2013.04.14 |
(JavaScript) How to make a cool $() selector (0) | 2013.04.09 |