История изменений
Исправление IvanRia, (текущая версия) :
для понимания, несколько сниппетов
открытие /dev/net/tun
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
free(*fds);
perror("open /dev/net/tun");
return ERROR;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strcpy(ifr.ifr_name, args->tun_name);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
free(*fds), close(fd);
perror("ioctl TUNSETIFF");
return ERROR;
}
(*fds)->tun_fd = fd;
return SUCCESS;
открытие сетевого сокета на клиентской стороне
int cli_tun(CMD_t *args, NetFD_t *fds)
{
struct sockaddr_in remote;
int sock_fd;
if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket client");
return ERROR;
}
remote.sin_family = AF_INET;
remote.sin_addr = args->ip_addr.remote_ip;
remote.sin_port = htons(args->port);
if (connect(sock_fd, (struct sockaddr *)&remote, sizeof(struct sockaddr_in)) == -1) {
perror("connect client");
return ERROR;
}
fds->net_fd = sock_fd;
return SUCCESS;
}
открытие сокета на серверной стороне
int serv_tun(CMD_t *args, NetFD_t *fds)
{
struct sockaddr_in local, guest;
int sock_fd;
socklen_t socklen;
if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket server");
return ERROR;
}
memset(&local, 0, sizeof(struct sockaddr_in));
local.sin_family = AF_INET;
local.sin_addr = args->ip_addr.local_ip;
local.sin_port = htons(args->port);
if (bind(sock_fd, (struct sockaddr *)&local, sizeof(struct sockaddr_in)) == -1) {
perror("bind server");
return ERROR;
}
if (listen(sock_fd, 0) == -1) {
perror("listen server");
return ERROR;
}
socklen = sizeof(struct sockaddr_in);
if ( (fds->net_fd = accept(sock_fd, (struct sockaddr *)&guest, &socklen)) == -1) {
perror("accept server");
return ERROR;
}
return SUCCESS;
}
вот цикл, который выполняется и на клиенте и на сервере
for (;;) {
FD_ZERO(&rfds);
FD_SET(net_fd, &rfds);
FD_SET(tun_fd, &rfds);
ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
if (ret == -1 && errno == EINTR) {
continue;
}
if (FD_ISSET(tun_fd, &rfds) == true) { //data in tun
//must read from tun
//and write to net
if ((nr = read(tun_fd, buffer, BUF_SIZE)) == -1) {
perror("read from tun");
}
if ((nw = write(net_fd, buffer, nr))==-1) {
perror("write to net\n");
}
}
if (FD_ISSET(net_fd, &rfds) == true) { //data in net
//must read from net
//and write to tun
if ((nr = read(net_fd, buffer, BUF_SIZE)) == -1) {
perror("read from net");
}
if ((nw = write(tun_fd, buffer, nr))==-1) {
perror("write to tun");
}
}
} /*for (;;)*/
вот этот цикл и делает всю работу, то есть ты просто читаешь из tun и отправляешь в сеть и наоборот, читаешь из сети и отправляешь в tun и цикл этот работает и на сервере и на клиенте без изменений. Это в самом простом варианте, проще наверно не придумаешь
Исходная версия IvanRia, :
для понимания, несколько сниппетов
открытие /dev/net/tun
if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) {
free(*fds);
perror("open /dev/net/tun");
return ERROR;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strcpy(ifr.ifr_name, args->tun_name);
if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
free(*fds), close(fd);
perror("ioctl TUNSETIFF");
return ERROR;
}
(*fds)->tun_fd = fd;
return SUCCESS;
открытие сетевого сокета на клиентской стороне
int cli_tun(CMD_t *args, NetFD_t *fds)
{
struct sockaddr_in remote;
int sock_fd;
if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket client");
return ERROR;
}
remote.sin_family = AF_INET;
remote.sin_addr = args->ip_addr.remote_ip;
remote.sin_port = htons(args->port);
if (connect(sock_fd, (struct sockaddr *)&remote, sizeof(struct sockaddr_in)) == -1) {
perror("connect client");
return ERROR;
}
fds->net_fd = sock_fd;
return SUCCESS;
}
открытие сокета на серверной стороне
int serv_tun(CMD_t *args, NetFD_t *fds)
{
struct sockaddr_in local, guest;
int sock_fd;
socklen_t socklen;
if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket server");
return ERROR;
}
memset(&local, 0, sizeof(struct sockaddr_in));
local.sin_family = AF_INET;
local.sin_addr = args->ip_addr.local_ip;
local.sin_port = htons(args->port);
if (bind(sock_fd, (struct sockaddr *)&local, sizeof(struct sockaddr_in)) == -1) {
perror("bind server");
return ERROR;
}
if (listen(sock_fd, 0) == -1) {
perror("listen server");
return ERROR;
}
socklen = sizeof(struct sockaddr_in);
if ( (fds->net_fd = accept(sock_fd, (struct sockaddr *)&guest, &socklen)) == -1) {
perror("accept server");
return ERROR;
}
return SUCCESS;
}
вот цикл, который выполняется и на клиенте и на сервере
for (;;) {
FD_ZERO(&rfds);
FD_SET(net_fd, &rfds);
FD_SET(tun_fd, &rfds);
ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
if (ret == -1 && errno == EINTR) {
continue;
}
if (FD_ISSET(tun_fd, &rfds) == true) { //data in tun
//must read from tun
//and write to net
if ((nr = read(tun_fd, buffer, BUF_SIZE)) == -1) {
perror("read from tun");
}
if ((nw = write(net_fd, buffer, nr))==-1) {
perror("write to net\n");
}
}
if (FD_ISSET(net_fd, &rfds) == true) { //data in net
//must read from net
//and write to tun
if ((nr = read(net_fd, buffer, BUF_SIZE)) == -1) {
perror("read from net");
}
if ((nw = write(tun_fd, buffer, nr))==-1) {
perror("write to tun");
}
}
} /*for (;;)*/}
вот этот цикл и делает всю работу, то есть ты просто читаешь из tun и отправляешь в сеть и наоборот, читаешь из сети и отправляешь в tun и цикл этот работает и на сервере и на клиенте без изменений. Это в самом простом варианте, проще наверно не придумаешь