LINUX.ORG.RU

История изменений

Исправление 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 и цикл этот работает и на сервере и на клиенте без изменений. Это в самом простом варианте, проще наверно не придумаешь