int TunMainLoop(int tunfd, SOCKET Socket, tBoolean keepalive, int keepalive_interval, char *local_address_ipv6, char *keepalive_address) { fd_set rfds; int count, maxfd; unsigned char bufin[2048]; unsigned char bufout[2048]; struct timeval timeout; int ret; if (keepalive_interval != 0) { timeout.tv_sec = 0; timeout.tv_usec = 100000; // 100 ms NetKeepaliveInit(local_address_ipv6, keepalive_address, keepalive_interval, AF_INET6); } else { keepalive = FALSE; timeout.tv_sec = 7 * 24 * 60 * 60 ; /* one week */ timeout.tv_usec = 0; } while( tspCheckForStopOrWait( 0 ) == 0 ) { FD_ZERO(&rfds); FD_SET(tunfd,&rfds); FD_SET(Socket,&rfds); maxfd = tunfd>Socket?tunfd:Socket; bufin[0]=0; bufin[1]=0; bufin[2]=0x86; bufin[3]=0xdd; if( keepalive ) { // Reinit timeout variable; in linux select modifies it. timeout.tv_sec = 0; timeout.tv_usec = 100000; // 100 ms if (NetKeepaliveDo() == 2) return KEEPALIVE_TIMEOUT; } ret = select(maxfd+1,&rfds,0,0,&timeout); if( ret > 0 ) { if( FD_ISSET(tunfd,&rfds) ) { /* data sent through udp tunnel */ if ( (count = read(tunfd,bufout,sizeof(bufout) )) == -1 ) { Display( LOG_LEVEL_3, ELError, "TunMainLoop",HEX_STR_ERR_READING_TUN_DEV ); return TUNNEL_ERROR; } NetKeepaliveGotWrite(); if (send(Socket,bufout+4,count-4,0) != count-4) { Display( LOG_LEVEL_3, ELError, "TunMainLoop",HEX_STR_ERR_WRITE_SOCKET ); return TUNNEL_ERROR; } } if( FD_ISSET(Socket,&rfds) ) { /* data received through udp tunnel */ count = recvfrom(Socket,bufin+4,2048-4,0,NULL,NULL); NetKeepaliveGotRead(); if( write(tunfd,bufin,count+4) != count+4 ) { Display( LOG_LEVEL_3, ELError, "TunMainLoop", HEX_STR_ERR_WRITE_TUN_DEV ); return TUNNEL_ERROR; } } } } // while() return NO_ERROR; }
int TunMainLoop(int tunfd, SOCKET Socket, tBoolean keepalive, int keepalive_interval, char *local_address_ipv6, char *keepalive_address_ipv6) { fd_set rfds; int count, maxfd; char bufin[2048]; char bufout[2048]; struct timeval timeout; int ret = 0; if (keepalive_interval != 0) { timeout.tv_sec = 0; timeout.tv_usec = 100000; // 100 ms NetKeepaliveInit(local_address_ipv6, keepalive_address_ipv6, keepalive_interval); } else { keepalive = FALSE; timeout.tv_sec = 7 * 24 * 60 * 60 ; /* one week */ timeout.tv_usec = 0; } bufin[0] = 0; bufin[1] = 0; bufin[2] = 0; bufin[3] = 0x1c; while(1) { FD_ZERO(&rfds); FD_SET(tunfd,&rfds); FD_SET(Socket,&rfds); maxfd = tunfd>Socket?tunfd:Socket; if(keepalive) if (NetKeepaliveDo() == 2) return KEEPALIVE_TIMEOUT; ret = select(maxfd+1,&rfds,0,0,&timeout); if (ret > 0) { if( FD_ISSET(tunfd, &rfds) ) { /* data sent through udp tunnel */ ioctl(tunfd, FIONREAD, &count); if (count > sizeof(bufout)) { Display(1, ELError, "TunMainLoop", "Error reading from tun device, buffer too small"); return(TUNNEL_ERROR); } if (read(tunfd, bufout, count) != count) { Display(1, ELError, "TunMainLoop", "Error reading from tun device"); return(TUNNEL_ERROR); } NetKeepaliveGotWrite(); if (send(Socket, bufout+4, count-4, 0) != count-4) { Display(1, ELError, "TunMainLoop", "Error writing to socket"); return(TUNNEL_ERROR); } } if(FD_ISSET(Socket,&rfds)) { /* data received through udp tunnel */ count=recvfrom(Socket,bufin+4,2048 - 4,0,NULL,NULL); NetKeepaliveGotRead(); if (write(tunfd, bufin, count + 4) != count + 4) { Display(1, ELError, "TunMainLoop", "Error writing to tun device"); return(TUNNEL_ERROR); } } }//if (ret>0) }//while(1) }