2 * Simple TCP redirector
4 * Luiz Fernando N. Capitulino <lcapitulino@gmail.com>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <sys/select.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
18 static void die(const char *s
)
24 static void help(void)
26 printf("redir <source IP>:<source port> <destination IP>:<destination port>\n");
30 static void cleanup_child(int signr
)
35 static int read_user_addr(struct sockaddr_in
*addr
, const char *addr_str
)
40 addr_str2
= strdup(addr_str
);
41 p
= strchr(addr_str2
, ':');
47 if (!inet_aton(addr_str2
, &addr
->sin_addr
)) {
56 addr
->sin_port
= htons(strtol(p
, NULL
, 10));
57 addr
->sin_family
= AF_INET
;
65 static int redir(int sfd
, int dfd
)
67 unsigned char buf
[4096];
68 size_t count
, total
, idx
;
70 memset(buf
, 0, sizeof(buf
));
72 count
= read(sfd
, buf
, sizeof(buf
));
80 count
= write(dfd
, buf
+ idx
, total
);
93 static void handle_new_client(int cfd
, struct sockaddr_in
*client_add
,
94 struct sockaddr_in
*dest_addr
)
98 dfd
= socket(AF_INET
, SOCK_STREAM
, 0);
103 ret
= connect(dfd
, (struct sockaddr
*) dest_addr
,
104 sizeof(struct sockaddr_in
));
109 nfds
= cfd
>= dfd
? cfd
: dfd
;
117 ret
= select(nfds
+ 1, &rfds
, NULL
, NULL
, 0);
120 } else if (FD_ISSET(cfd
, &rfds
)) {
121 if (redir(cfd
, dfd
)) {
124 } else if (FD_ISSET(dfd
, &rfds
)) {
125 if (redir(dfd
, cfd
)) {
136 int main(int argc
, const char *argv
[])
138 struct sockaddr_in src_addr
, dest_addr
, client_addr
;
139 socklen_t dest_addr_sz
;
146 err
= read_user_addr(&src_addr
, argv
[1]);
151 err
= read_user_addr(&dest_addr
, argv
[2]);
156 signal(SIGCHLD
, cleanup_child
);
158 sfd
= socket(AF_INET
, SOCK_STREAM
, 0);
163 err
= bind(sfd
, (struct sockaddr
*) &src_addr
, sizeof(struct sockaddr_in
));
168 err
= listen(sfd
, 2);
176 dest_addr_sz
= sizeof(struct sockaddr_in
);
177 cfd
= accept(sfd
, (struct sockaddr
*) &client_addr
, &dest_addr_sz
);
182 fprintf(stderr
, "-> New connection from: %s:%d\n",
183 inet_ntoa(client_addr
.sin_addr
), ntohs(client_addr
.sin_port
));
188 } else if (pid
== 0) {
190 handle_new_client(cfd
, &client_addr
, &dest_addr
);