Created
December 30, 2011 05:12
-
-
Save xream/1538016 to your computer and use it in GitHub Desktop.
Multiple SSH Tunnels
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <signal.h> | |
#include <fcntl.h> | |
#include <netdb.h> | |
#define PORT 7070 | |
#define ADDRESS "127.0.0.1" | |
#define RPORT 7071 | |
#define THREAD 4 | |
#define RADDR "127.0.0.1" | |
#define MAXDATA 1024 | |
#define MAXCLIENT 255 | |
#define LOG 0 | |
#define ERRLOG 1 | |
#define SELLOG 0 | |
int INDEX = -1; | |
#define MSG_NOSIGNAL 0 | |
void xsocket(int *_listen_fd){ | |
int on = 1; | |
errno = 0; | |
if((*_listen_fd=socket(AF_INET, SOCK_STREAM, 0)) >= 0){ | |
if(LOG) {perror("#10000.socket\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#10001.socket\t");} | |
//exit(1); | |
} | |
errno = 0; | |
if(setsockopt(*_listen_fd, SOL_SOCKET, SO_REUSEADDR, (int *) &on, sizeof(on)) >= 0){ | |
if(LOG) {perror("#10020.setopt\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#10021.setopt\t");} | |
} | |
return; | |
} | |
void xbzero(struct sockaddr_in *_saddr){ | |
bzero(((char *) _saddr), sizeof(*_saddr)); | |
return; | |
} | |
void xbind(int *_listen_fd, struct sockaddr_in *_saddr, int *len){ | |
_saddr->sin_family = PF_INET; | |
_saddr->sin_addr.s_addr = inet_addr(ADDRESS); | |
_saddr->sin_port = htons(PORT); | |
errno = 0; | |
if(bind(*_listen_fd, (struct sockaddr *)_saddr, *len) >= 0){ | |
if(LOG) {perror("#10100.bind\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#10101.bind\t");} | |
//exit(1); | |
} | |
return; | |
} | |
void xlisten(int *_listen_fd){ | |
errno = 0; | |
if(listen(*_listen_fd, MAXCLIENT) >= 0){ | |
if(LOG) {perror("#10200.listen\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#10201.listen\t");} | |
exit(1); | |
} | |
printf("start listening port %d\n", PORT); | |
return; | |
} | |
int xaccept(int *_listen_fd, struct sockaddr_in *_caddr, int *_len){ | |
int conn_fd; | |
if((conn_fd = accept(*_listen_fd, (struct sockaddr *) _caddr, (socklen_t *__restrict) _len)) >= 0){ | |
if(LOG) {perror("#10300.accept\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#10301.accept\t");} | |
} | |
return conn_fd; | |
} | |
void xgetaddrinfo(char *_name, int _port, struct addrinfo **_addr){ | |
char port[10]; | |
sprintf(port, "%d", _port); | |
errno = 0; | |
if(getaddrinfo(_name, port, NULL, _addr) >= 0){ | |
if(LOG) {perror("#11000.getaddr\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#11001.getaddr\t");} | |
exit(1); | |
} | |
return; | |
} | |
int xconnect(int *_conn_fd, struct addrinfo *_addr){ | |
int ret = 0; | |
errno = 0; | |
if(connect(*_conn_fd, _addr->ai_addr, _addr->ai_addrlen) >= 0){ | |
if(LOG) {perror("#11100.connect\t");} | |
} | |
else{ | |
if(ERRLOG) {perror("#11101.connect\t");} | |
ret = -1; | |
} | |
return ret; | |
} | |
int max(int x, int y){ | |
if(x >= y){ | |
return x; | |
} | |
else{ | |
return y; | |
} | |
} | |
void dclose(int *fd, int *rfd, int i){ | |
close(fd[i]); | |
close(rfd[i]); | |
fd[i] = -1; | |
rfd[i] = -1; | |
return; | |
} | |
int main(int argc, char **argv){ | |
struct sockaddr_in saddr; | |
struct sockaddr_in caddr; | |
int listen_fd; | |
int len = sizeof(struct sockaddr_in); | |
int rsize; | |
char buf[MAXDATA]; | |
int i; | |
int ret; | |
int fd[MAXCLIENT]; | |
int rfd[MAXCLIENT]; | |
int nfds = 0; | |
struct addrinfo *addr[THREAD]; | |
fd_set rd; | |
FD_ZERO(&rd); | |
for(i = 0;i < MAXCLIENT;i++){ | |
fd[i] = -1; | |
rfd[i] = -1; | |
} | |
for(i = 0;i < THREAD;i++){ | |
xgetaddrinfo(RADDR, RPORT+i, &addr[i]); | |
} | |
signal(SIGPIPE, SIG_IGN); | |
xsocket(&listen_fd); | |
xbzero(&saddr); | |
xbzero(&caddr); | |
xbind(&listen_fd, &saddr, &len); | |
xlisten(&listen_fd); | |
while(1){ | |
if(SELLOG){printf("loop start\n");} | |
FD_ZERO(&rd); | |
FD_SET(listen_fd, &rd); | |
for(i = 0; i < MAXCLIENT; i++){ | |
if(fd[i] >= 0){ | |
FD_SET(fd[i], &rd); | |
} | |
if(rfd[i] >= 0){ | |
FD_SET(rfd[i], &rd); | |
} | |
} | |
nfds = max(nfds, listen_fd); | |
ret = select(nfds+1, &rd, NULL, NULL, NULL); | |
if(SELLOG){printf("select return\n");} | |
if(ret < 0){ | |
if (errno == EINTR){ //EINTR = 4 | |
continue; | |
} | |
else{ | |
if(ERRLOG){printf("begin select failure\n");} | |
} | |
} | |
if(FD_ISSET(listen_fd ,&rd)){ | |
if(SELLOG){printf("start accept\n");} | |
for(i = 0; i < MAXCLIENT; i++){ | |
if(fd[i] < 0){ | |
fd[i] = xaccept(&listen_fd, &caddr, &len); | |
if(fd[i] < 0){ | |
if(ERRLOG){printf("accept a new connection failure\n");} | |
} | |
else{ | |
if(++INDEX >= THREAD){ | |
INDEX = 0; | |
} | |
if(SELLOG){printf("%d\n",RPORT+INDEX);} | |
xsocket(&(rfd[i])); | |
if(xconnect(&(rfd[i]), addr[INDEX]) < 0){ | |
if(ERRLOG){printf("connect remote server error\n");} | |
dclose(fd, rfd, i); | |
} | |
else{ | |
if(SELLOG){printf("connect remote server finish\n");} | |
} | |
} | |
if (fd[i] > nfds){ | |
nfds = fd[i]; | |
} | |
if (rfd[i] > nfds){ | |
nfds = rfd[i]; | |
} | |
break; | |
} | |
} | |
continue; | |
} | |
for(i = 0; i < MAXCLIENT; i++){ | |
if(fd[i] < 0){ | |
continue; | |
} | |
if(FD_ISSET(fd[i], &rd)){ | |
bzero(&buf, sizeof(buf)); | |
errno = 0; | |
if(SELLOG){printf("recv data form local\n");} | |
rsize = recv(fd[i], buf, MAXDATA, MSG_NOSIGNAL); | |
if(rsize < 0){ | |
if(SELLOG){perror("#50001.recv error");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
else if(rsize ==0){ | |
if(SELLOG){printf("local connection closed\n");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
else{ | |
if(SELLOG){printf("send data to remote server\n");} | |
if(send(rfd[i], buf, rsize, MSG_NOSIGNAL) < 0){ | |
if(SELLOG){printf("send data to remote server error\n");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
} | |
} | |
if(FD_ISSET(rfd[i], &rd)){ | |
bzero(&buf, sizeof(buf)); | |
errno = 0; | |
if(SELLOG){printf("recv data form remote server\n");} | |
rsize = recv(rfd[i], buf, MAXDATA, MSG_NOSIGNAL); | |
if(rsize < 0){ | |
if(SELLOG){perror("#50001.recv error");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
else if(rsize ==0){ | |
if(SELLOG){printf("remote connection closed\n");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
else{ | |
if(SELLOG){printf("send data to local\n");} | |
if(send(fd[i], buf, rsize, MSG_NOSIGNAL) < 0){ | |
if(SELLOG){printf("send data to local error\n");} | |
dclose(fd, rfd, i); | |
continue; | |
} | |
} | |
} | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment