int alloc_lzo(struct vtun_host *host) { int zlevel = host->zlevel ? host->zlevel : 1; int mem; switch( zlevel ){ case 9: lzo1x_compress = lzo1x_999_compress; mem = LZO1X_999_MEM_COMPRESS; break; default: lzo1x_compress = lzo1x_1_15_compress; mem = LZO1X_1_15_MEM_COMPRESS; break; } if( lzo_init() != LZO_E_OK ){ vtun_syslog(LOG_ERR,"Can't initialize compressor"); return 1; } if( !(zbuf = lfd_alloc(zbuf_size)) ){ vtun_syslog(LOG_ERR,"Can't allocate buffer for the compressor"); return 1; } if( !(wmem = lzo_malloc(mem)) ){ vtun_syslog(LOG_ERR,"Can't allocate buffer for the compressor"); return 1; } vtun_syslog(LOG_INFO, "LZO compression[level %d] initialized", zlevel); return 0; }
void server(int sock) { struct sigaction sa; sa.sa_handler=SIG_IGN; sa.sa_flags=SA_NOCLDWAIT;; sigaction(SIGINT,&sa,NULL); sigaction(SIGQUIT,&sa,NULL); sigaction(SIGCHLD,&sa,NULL); sigaction(SIGPIPE,&sa,NULL); sigaction(SIGUSR1,&sa,NULL); vtun_syslog(LOG_INFO,"VTUN server ver %s (%s)", VTUN_VER, vtun.svr_type == VTUN_INETD ? "inetd" : "stand" ); switch( vtun.svr_type ){ case VTUN_STAND_ALONE: #ifdef HAVE_WORKING_FORK listener(); #else vtun_syslog(LOG_ERR,"Standalone server is not supported: fork() not available"); #endif break; case VTUN_INETD: connection(sock); break; } }
int zlib_decomp(int len, char *in, char **out) { int oavail = 0, olen = 0; int err; zi.next_in = (void *) in; zi.avail_in = len; zi.next_out = (void *) zbuf; zi.avail_out = zbuf_size; while(1) { oavail = zi.avail_out; if( (err=inflate(&zi, Z_SYNC_FLUSH)) != Z_OK ) { vtun_syslog(LOG_ERR,"Inflate error %d len %d", err, len); return -1; } olen += oavail - zi.avail_out; if(!zi.avail_in) break; if( expand_zbuf(&zi,100) ) { vtun_syslog( LOG_ERR, "Can't expand compression buffer"); return -1; } } *out = (void *) zbuf; return olen; }
/* * Initialize compressor/decompressor. * Allocate the buffer. */ int zlib_alloc(struct vtun_host *host) { int zlevel = host->zlevel ? host->zlevel : 1; zd.zalloc = (alloc_func)0; zd.zfree = (free_func)0; zd.opaque = (voidpf)0; zi.zalloc = (alloc_func)0; zi.zfree = (free_func)0; zi.opaque = (voidpf)0; if( deflateInit(&zd, zlevel ) != Z_OK ){ vtun_syslog(LOG_ERR,"Can't initialize compressor"); return 1; } if( inflateInit(&zi) != Z_OK ){ vtun_syslog(LOG_ERR,"Can't initialize decompressor"); return 1; } if( !(zbuf = (void *) lfd_alloc(zbuf_size)) ){ vtun_syslog(LOG_ERR,"Can't allocate buffer for the compressor"); return 1; } vtun_syslog(LOG_INFO,"ZLIB compression[level %d] initialized.", zlevel); return 0; }
/* Set address by interface name, ip address or hostname */ int generic_addr(struct sockaddr_in *addr, struct vtun_addr *vaddr) { struct hostent *hent; memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; switch (vaddr->type) { case VTUN_ADDR_IFACE: if (!(addr->sin_addr.s_addr = getifaddr(vaddr->name))) { vtun_syslog(LOG_ERR, "Can't get address of interface %s", vaddr->name); return -1; } break; case VTUN_ADDR_NAME: if (!(hent = gethostbyname(vaddr->name))) { vtun_syslog(LOG_ERR, "Can't resolv local address %s", vaddr->name); return -1; } addr->sin_addr.s_addr = *(unsigned long *) hent->h_addr; break; default: addr->sin_addr.s_addr = INADDR_ANY; break; } if (vaddr->port) addr->sin_port = htons(vaddr->port); return 0; }
void connection(int sock) { struct sockaddr_in my_addr, cl_addr; struct vtun_host *host; struct sigaction sa; char *ip; int opt; opt = sizeof(struct sockaddr_in); if( getpeername(sock, (struct sockaddr *) &cl_addr, &opt) ){ vtun_syslog(LOG_ERR, "Can't get peer name"); exit(1); } opt = sizeof(struct sockaddr_in); if( getsockname(sock, (struct sockaddr *) &my_addr, &opt) < 0 ){ vtun_syslog(LOG_ERR, "Can't get local socket address"); exit(1); } ip = strdup(inet_ntoa(cl_addr.sin_addr)); io_init(); if( (host=auth_server(sock)) ){ sa.sa_handler=SIG_IGN; sa.sa_flags=SA_NOCLDWAIT;; sigaction(SIGHUP,&sa,NULL); vtun_syslog(LOG_INFO,"Session %s[%s:%d] opened", host->host, ip, ntohs(cl_addr.sin_port) ); host->rmt_fd = sock; host->sopt.laddr = strdup(inet_ntoa(my_addr.sin_addr)); host->sopt.lport = vtun.bind_addr.port; host->sopt.raddr = strdup(ip); host->sopt.rport = ntohs(cl_addr.sin_port); /* Start tunnel */ tunnel(host, 1); vtun_syslog(LOG_INFO,"Session %s closed", host->host); /* Unlock host. (locked in auth_server) */ unlock_host(host); } else { vtun_syslog(LOG_INFO,"Denied connection from %s:%d", ip, ntohs(cl_addr.sin_port) ); } close(sock); exit(0); }
int run_cmd(void *d, void *opt) { struct vtun_cmd *cmd = d; char *argv[50], *args; int pid, st; switch( (pid=fork()) ){ case 0: break; case -1: vtun_syslog(LOG_ERR,"Couldn't fork()"); return 0; default: if( cmd->flags & VTUN_CMD_WAIT ){ /* Wait for termination */ if( waitpid(pid,&st,0) > 0 && (WIFEXITED(st) && WEXITSTATUS(st)) ) vtun_syslog(LOG_INFO,"Command [%s %.20s] error %d", cmd->prog ? cmd->prog : "sh", cmd->args ? cmd->args : "", WEXITSTATUS(st) ); } if( cmd->flags & VTUN_CMD_DELAY ){ struct timespec tm = { VTUN_DELAY_SEC, 0 }; /* Small delay hack to sleep after pppd start. * Until I have no good solution for solving * PPP + route problem */ nanosleep(&tm, NULL); } return 0; } args = subst_opt(cmd->args, opt); if( !cmd->prog ){ /* Run using shell */ cmd->prog = "/bin/sh"; argv[0] = "sh"; argv[1] = "-c"; argv[2] = args; argv[3] = NULL; } else { argv[0] = cmd->prog; split_args(args, argv + 1); } execv(cmd->prog, argv); vtun_syslog(LOG_ERR,"Couldn't exec program %s", cmd->prog); exit(1); }
void server(int sock) { struct sigaction sa; sa.sa_handler=SIG_IGN; sa.sa_flags=SA_NOCLDWAIT;; sigaction(SIGINT,&sa,NULL); sigaction(SIGQUIT,&sa,NULL); sigaction(SIGCHLD,&sa,NULL); sigaction(SIGPIPE,&sa,NULL); sigaction(SIGUSR1,&sa,NULL); sigaction(SIGUSR2,&sa,NULL); vtun_syslog(LOG_INFO,"vtrunkd server ver %s %s (%s)", VTUN_VER, BUILD_DATE, vtun.svr_type == VTUN_INETD ? "inetd" : "stand" ); switch( vtun.svr_type ){ case VTUN_STAND_ALONE: listener(); break; case VTUN_INETD: connection(sock); break; } }
void reread_config(int sig) { if( !read_config(vtun.cfg_file) ){ vtun_syslog(LOG_ERR,"No hosts defined"); exit(1); } }
int send_new_port(struct vtun_host *host, int i, int j, int ctrl_msg_type) { struct sockaddr_in saddr; short port; int s, opt; int buflen = 10; char buf[10]; char ipstr[INET_ADDRSTRLEN]; ctrl_msg cm; bind_link bl; vtun_syslog(LOG_ERR, "send_new_port creating socket for %d using %d", i, j); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); saddr.sin_family = AF_INET; saddr.sin_port = htons(host->sport[i]); saddr.sin_addr.s_addr = inet_addr(host->saddr[i].ip); //vtun_syslog(LOG_ERR,"send_new_port bind to port"); errno = 0; /*Bind a port*/ if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); //vtun_syslog(LOG_ERR,"send_new_port getsocknamei %s",strerror(errno)); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } port = saddr.sin_port; opt = sizeof(host->fs[j].daddr); cm.type = ctrl_msg_type; bl.index = i; bl.port = port; cm.bl = bl; // vtun_syslog(LOG_ERR,"send_new_port sending"); errno = 0; sendfromto(host->ctrl, (char *) &cm, sizeof(cm), 0, (struct sockaddr *) &host->fs[j].saddr, opt, (struct sockaddr *) &host->fs[j].daddr, opt); inet_ntop(AF_INET, &(host->fs[j].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "From %s:%d", ipstr, ntohs(host->fs[j].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[j].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "To %s:%d", ipstr, ntohs(host->fs[j].daddr.sin_port)); vtun_syslog(LOG_ERR, "send_new_port returning %s", strerror(errno)); return 1; }
/* * Very simple PID file creation function. Used by server. * Overrides existing file. */ void write_pid(void) { FILE *f; if (!(f = fopen(VTUN_PID_FILE, "w"))) { vtun_syslog(LOG_ERR, "Can't write PID file"); return; } fprintf(f, "%d", (int) getpid()); fclose(f); }
int decomp_lzo(int len, char *in, char **out) { unsigned int zlen = 0; int err; if( (err=lzo1x_decompress((void *)in,len,zbuf,&zlen,wmem)) != LZO_E_OK ){ vtun_syslog(LOG_ERR,"Decompress error %d",err); return -1; } *out = (void *) zbuf; return zlen; }
int prep_key(char **key, int size, struct vtun_host *host) { int tmplen, halflen; char *hashkey; if ( !(hashkey = malloc(size)) ) { vtun_syslog(LOG_ERR,"Can't allocate buffer for key hash"); return -1; } memset(hashkey,0,size); if (size == 32) { tmplen = strlen(host->passwd); if (tmplen != 0) halflen = tmplen>>1; else halflen = 0;
void send_flag_info(struct vtun_host *host, int ctrl) { ctrl_msg cm; fd_info my_info; int i; cm.type = FD_INFO; for (i = 0; i < VTUN_MAX_INT; i++) { my_info.flag[i] = host->fs[i].fd_flag; } cm.fi = my_info; i = sizeof(host->fs[ctrl].daddr); sendfromto(host->ctrl, (char *) &cm, sizeof(cm), 0, (struct sockaddr *) &host->fs[ctrl].saddr, i, (struct sockaddr *) &host->fs[ctrl].daddr, i); vtun_syslog(-1, "FLAG INFO IS SENT "); }
/* Set local address */ int local_addr(struct sockaddr_in *addr, struct vtun_host *host, int con) { int opt; if (con) { /* Use address of the already connected socket. */ opt = sizeof(struct sockaddr_in); if (getsockname(host->rmt_fd, (struct sockaddr *) addr, &opt) < 0) { vtun_syslog(LOG_ERR, "Can't get local socket address"); return -1; } } else { if (generic_addr(addr, &host->src_addr) < 0) return -1; } host->sopt.laddr = strdup(inet_ntoa(addr->sin_addr)); return 0; }
void send_unbind_req(struct vtun_host *host, int index) { ctrl_msg cm; bind_link bl; int i; int j; int opt; cm.type = UNBIND_REQ; bl.index = index; bl.port = 0; cm.bl = bl; j = get_ctrl_index(host); opt = sizeof(host->fs[j].daddr); sendfromto(host->ctrl, (char *) &cm, sizeof(cm), 0, (struct sockaddr *) &host->fs[j].saddr, opt, (struct sockaddr *) &host->fs[j].daddr, opt); close(host->fs[index].fd); vtun_syslog(LOG_ERR, "UNBIND REQ IS SENT %d", index); return; }
int server_addr(struct sockaddr_in *addr, struct vtun_host *host) { struct hostent * hent; memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; addr->sin_port = htons(vtun.bind_addr.port); /* Lookup server's IP address. * We do it on every reconnect because server's IP * address can be dynamic. */ if (!(hent = gethostbyname(vtun.svr_name))) { vtun_syslog(LOG_ERR, "Can't resolv server address: %s", vtun.svr_name); return -1; } addr->sin_addr.s_addr = *(unsigned long *) hent->h_addr; host->sopt.raddr = strdup(inet_ntoa(addr->sin_addr)); host->sopt.rport = vtun.bind_addr.port; return 0; }
int udp_session_fs(struct vtun_host *host, int count) { struct sockaddr_in saddr; short port; int s, opt; saddr.sin_family = AF_INET; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket %d", count); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ saddr.sin_port = host->sport[count]; saddr.sin_addr.s_addr = inet_addr(host->saddr[count].ip); vtun_syslog(LOG_ERR, "address %s:%d", host->saddr[count].ip, host->sport[count]); vtun_syslog(LOG_ERR, "address %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket (%d:%s)", errno, strerror(errno)); return -1; } saddr.sin_port = host->dport[count]; saddr.sin_addr.s_addr = inet_addr(host->daddr[count].ip); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket %d ", count); return -1; } host->fs[count].saddr = saddr; host->fs[count].fd = s; host->fs[count].fd_flag = 1; vtun_syslog(LOG_INFO, "UDP %d connection initialized", count); return s; }
/* int cshit3(struct conn_info * sci, int fx) { int cnt = 0, cnt2=0; int nnl = sci->resend_buf.frames.rel_head; int nnf = sci->resend_buf.free_frames.rel_head; while(nnl > -1) { cnt++; nnl = sci->resend_buf.frames_buf[nnl].rel_next; } while(nnf > -1) { cnt++; nnf = sci->resend_buf.frames_buf[nnf].rel_next; } vtun_syslog(LOG_INFO, "%d count l: %d f: %d", fx, cnt, cnt2); return 0; } */ void client(struct vtun_host *host) { struct sockaddr_in my_addr,svr_addr; struct sigaction sa; int s, opt, reconnect, sss, len; int shm_new = 0; struct sockaddr_un remote; vtun_syslog(LOG_INFO,"vtrunkd client ver %s %s started",VTUN_VER, BUILD_DATE); memset(&sa,0,sizeof(sa)); sa.sa_handler=SIG_IGN; sa.sa_flags = SA_NOCLDWAIT; sigaction(SIGHUP,&sa,NULL); sigaction(SIGQUIT,&sa,NULL); sigaction(SIGPIPE,&sa,NULL); sigaction(SIGCHLD,&sa,NULL); sa.sa_handler=sig_term; sigaction(SIGTERM,&sa,NULL); sigaction(SIGINT,&sa,NULL); // now init everything... int shmid; key_t key; struct conn_info *shm_conn_info; struct timeval cur_time; /* * We'll name our shared memory segment * "5678". */ key = SHM_TUN_KEY; /* * First, try to open shm */ if ((shmid = shmget(key, sizeof(struct conn_info), 0666)) < 0) { /* * Create the segment. */ vtun_syslog(LOG_INFO,"client: init new shm..."); if ((shmid = shmget(key, sizeof(struct conn_info), IPC_CREAT | 0666)) < 0) { vtun_syslog(LOG_ERR,"shmget 2 size %d", sizeof(struct conn_info)); exit(1); } shm_new = 1; } else { vtun_syslog(LOG_INFO,"client: reusing shm..."); shm_new = 0; } /* * Now we attach the segment to our data space. */ if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) -1) { vtun_syslog(LOG_ERR,"shmat 2"); exit(1); } //cshit3(&shm_conn_info[0], 36); // now try to connect to socket if shm_new ==0 if(!shm_new) { if ((sss = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { vtun_syslog(LOG_ERR, "socket 44"); exit(1); } remote.sun_family = AF_UNIX; strcpy(remote.sun_path, shm_conn_info[0].devname); len = strlen(remote.sun_path) + sizeof(remote.sun_family); if ( (shm_conn_info->rdy) && (connect(sss, (struct sockaddr *)&remote, len) == -1)) { vtun_syslog(LOG_INFO, "SHM ready but socket not open! Assuming we're only process running;"); shm_new = 1; // could not connect; assume we're new! } else { vtun_syslog(LOG_INFO, "Socket connected OK seems all OK"); } close(sss); } if(shm_new) { vtun_syslog(LOG_INFO, "client doing memset"); memset(shm_conn_info, 0, sizeof(struct conn_info)); } //cshit3(&shm_conn_info[0], 37); client_term = 0; reconnect = 0; while( (!client_term) || (client_term == VTUN_SIG_HUP) ){ if( reconnect && (client_term != VTUN_SIG_HUP) ){ if( vtun.persist || host->persist ){ /* Persist mode. Sleep and reconnect. */ sleep(5); } else { /* Exit */ break; } } else { reconnect = 1; } set_title("%s init initializing", host->host); /* Set server address */ if( server_addr(&svr_addr, host) < 0 ) continue; /* Set local address */ if( local_addr(&my_addr, host, 0) < 0 ) continue; /* We have to create socket again every time * we want to connect, since STREAM sockets * can be successfully connected only once. */ if( (s = socket(AF_INET,SOCK_STREAM,0))==-1 ){ vtun_syslog(LOG_ERR,"Can't create socket. %s(%d)", strerror(errno), errno); continue; } //cshit3(&shm_conn_info[0], 38); /* Required when client is forced to bind to specific port */ opt=1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); #ifndef W_O_SO_MARK if(host->RT_MARK != -1) { if (setsockopt(s, SOL_SOCKET, SO_MARK, &host->RT_MARK, sizeof(host->RT_MARK))) { vtun_syslog(LOG_ERR,"client socket rt mark error %s(%d)", strerror(errno), errno); break; } } #endif if( bind(s,(struct sockaddr *)&my_addr,sizeof(my_addr)) ){ vtun_syslog(LOG_ERR,"Can't bind socket. %s(%d)", strerror(errno), errno); continue; } /* * Clear speed and flags which will be supplied by server. */ host->spd_in = host->spd_out = 0; host->flags &= VTUN_CLNT_MASK; io_init(); set_title("%s connecting to %s", host->host, vtun.svr_name); vtun_syslog(LOG_INFO,"Connecting to %s", vtun.svr_name); if( connect_t(s,(struct sockaddr *) &svr_addr, host->timeout) ){ vtun_syslog(LOG_INFO,"Connect to %s failed. %s(%d)", vtun.svr_name, strerror(errno), errno); } else { if( auth_client(s, host) ){ vtun_syslog(LOG_INFO,"Session %s[%s] opened",host->host,vtun.svr_name); host->rmt_fd = s; //cshit3(&shm_conn_info[0], 39); /* Start the tunnel */ client_term = tunnel(host, 0); gettimeofday(&cur_time, NULL); shm_conn_info->alive = cur_time.tv_sec; // show we are alive and trying to reconnect still.. (or fd_server will quit) vtun_syslog(LOG_INFO,"Session %s[%s] closed",host->host,vtun.svr_name); } else { vtun_syslog(LOG_INFO,"Connection denied by %s",vtun.svr_name); } } close(s); free_sopt(&host->sopt); } vtun_syslog(LOG_INFO, "Exit"); return; }
void listener(void) { struct sigaction sa; struct sockaddr_in my_addr, cl_addr; int s, s1, opt; memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; /* Set listen address */ if( generic_addr(&my_addr, &vtun.bind_addr) < 0) { vtun_syslog(LOG_ERR, "Can't fill in listen socket"); exit(1); } if( (s=socket(AF_INET,SOCK_STREAM,0))== -1 ){ vtun_syslog(LOG_ERR,"Can't create socket"); exit(1); } opt=1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if( bind(s,(struct sockaddr *)&my_addr,sizeof(my_addr)) ){ vtun_syslog(LOG_ERR,"Can't bind to the socket"); exit(1); } if( listen(s, 10) ){ vtun_syslog(LOG_ERR,"Can't listen on the socket"); exit(1); } memset(&sa,0,sizeof(sa)); sa.sa_flags = SA_NOCLDWAIT; sa.sa_handler=sig_term; sigaction(SIGTERM,&sa,NULL); sigaction(SIGINT,&sa,NULL); // WARNING: signals should be re-checked before using! server_term = 0; set_title("waiting for connections on port %d", vtun.bind_addr.port); // now init everything... int shmid; key_t key; struct conn_info* shm_conn_info; /* * We'll name our shared memory segment * "5678". */ key = SHM_TUN_KEY; /* * Create the segment. */ // TODO: do not allocate all memory at once!!!! if ((shmid = shmget(key, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM, IPC_CREAT | 0666)) < 0) { vtun_syslog(LOG_ERR,"Can not allocate SHM buffer of size %d. Please check your system shmmax or use 'ipcrm' to remove stale SHMs", sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM); exit(1); } /* * Now we attach the segment to our data space. */ if ((shm_conn_info = shmat(shmid, NULL, 0)) == (struct conn_info *) -1) { vtun_syslog(LOG_ERR,"shmat 1"); exit(1); } memset(shm_conn_info, 0, sizeof(struct conn_info) * vtun.MAX_TUNNELS_NUM); while( (!server_term) || (server_term == VTUN_SIG_HUP) ){ opt=sizeof(cl_addr); if( (s1=accept(s,(struct sockaddr *)&cl_addr,&opt)) < 0 ) continue; switch( fork() ){ case 0: close(s); #ifdef DEBUGG // now init the profiler; don;t forget to set GMON_OUT_PREFIX extern void _start (void), etext (void); monstartup ((u_long) &_start, (u_long) &etext); #endif connection(s1); break; case -1: vtun_syslog(LOG_ERR, "Couldn't fork()"); default: close(s1); // normal cont break; } } shmctl(key, IPC_RMID, NULL); vtun_syslog(LOG_INFO, "SERVER QUIT %d", server_term); }
int cf2bf(char *str, struct vtun_host *host) { char *ptr, *p; int s; if( (ptr = strchr(str,'<')) ){ vtun_syslog(LOG_DEBUG,"Remote Server sends %s.", ptr); ptr++; while(*ptr){ switch(*ptr++){ case 't': host->flags |= VTUN_TTY; break; case 'p': host->flags |= VTUN_PIPE; break; case 'e': host->flags |= VTUN_ETHER; break; case 'u': host->flags |= VTUN_TUN; break; case 'U': host->flags &= ~VTUN_PROT_MASK; host->flags |= VTUN_UDP; break; case 'X': host->flags &= ~VTUN_PROT_MASK; host->flags |= VTUN_SCTP; break; case 'T': host->flags &= ~VTUN_PROT_MASK; host->flags |= VTUN_TCP; break; case 'K': host->flags |= VTUN_KEEP_ALIVE; break; case 'C': if((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) return 0; host->flags |= VTUN_ZLIB; host->zlevel = s; ptr = p; break; case 'L': if((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) return 0; host->flags |= VTUN_LZO; host->zlevel = s; ptr = p; break; case 'E': /* new form is 'E10', old form is 'E', so remove the ptr==p check */ if((s = strtol(ptr,&p,10)) == ERANGE) { vtun_syslog(LOG_ERR,"Garbled encryption method. Bailing out."); return 0; } host->flags |= VTUN_ENCRYPT; if (0 == s) { host->cipher = VTUN_LEGACY_ENCRYPT; vtun_syslog(LOG_INFO,"Remote server using older encryption."); } else { host->cipher = s; } ptr = p; break; case 'S': if((s = strtol(ptr,&p,10)) == ERANGE || ptr == p) return 0; if( s ){ host->flags |= VTUN_SHAPE; host->spd_out = s; } ptr = p; break; case 'F': /* reserved for Feature transmit */ break; case '>': return 1; default: return 0; } } } return 0; }
//add by adonis for multiple interfaces int udp_session_fs1(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; vtun_syslog(LOG_ERR, "in udp_session_fs1"); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ vtun_syslog(LOG_ERR, "in local_addr"); local_addr(&saddr, host, 1); vtun_syslog(LOG_ERR, "after local_addr"); vtun_syslog(LOG_ERR, "debug %d", host->sport[1]); vtun_syslog(LOG_ERR, "debug %d, %s", host->sport[1], host->saddr[1].ip); saddr.sin_port = host->sport[1]; saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); vtun_syslog(LOG_ERR, "before bind"); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } vtun_syslog(LOG_ERR, "after bind"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd2, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); vtun_syslog(LOG_ERR, "after port ex send"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd2, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } vtun_syslog(LOG_ERR, "after port ex recv"); opt = sizeof(saddr); if (getpeername(host->rmt_fd2, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } host->sopt.rport = htons(port); host->rmt_sock2 = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd2); host->rmt_fd2 = s; //add by Kai for multiple interfaces host->fs[1].saddr = saddr; host->fs[1].fd = s; host->fs[1].fd_flag = 1; //end add vtun_syslog(LOG_INFO, "UDP 1 connection initialized"); return s; }
int no_zlib(struct vtun_host *host) { vtun_syslog(LOG_INFO, "ZLIB compression is not supported"); return -1; }
/* * Establish UDP session with host connected to fd(socket). * Returns connected UDP socket or -1 on error. */ int udp_session(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; int buflen = 10; char buf[10]; char ipstr[INET_ADDRSTRLEN]; vtun_syslog(LOG_INFO, "UDP connection initialized %d,%d", host->rmt_fd, host->rmt_fd2); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = htons(host->sport[0]); saddr.sin_addr.s_addr = inet_addr(host->saddr[0].ip); errno = 0; if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s (%s:%d)", strerror(errno), host->saddr[0].ip, host->sport[0]); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } host->fs[0].saddr = saddr; /* if we are not just binding port number then we are server*/ if (host->role == 1) { vtun_syslog(LOG_INFO, "udp_session for server 1"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } vtun_syslog(LOG_INFO, "Waiting for UDP ACK 1, wrote port %d", port); opt = sizeof(saddr); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "UDP ACK 1 from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); host->fs[0].daddr.sin_family = saddr.sin_family; host->fs[0].daddr.sin_port = saddr.sin_port; host->fs[0].daddr.sin_addr.s_addr = saddr.sin_addr.s_addr; inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[0].daddr.sin_port)); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } write_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "FINAL ACK SENT 1"); } else { //vtun_syslog(LOG_INFO,"udp_session for client 1"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, (char *) &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } vtun_syslog(LOG_INFO, "Recieved port %d info from server 1", port); opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; sendto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, opt); vtun_syslog(LOG_INFO, "Sent ACK on UDP 1"); host->fs[0].daddr = saddr; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } read_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "Connected & Recived final ACK 1"); } /* Why we need this ??*/ host->sopt.rport = htons(port); host->rmt_sock = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; //add by Kai for multiple interfaces // host->fs[0].daddr = saddr; host->fs[0].fd = s; host->fs[0].fd_flag = 1; s = 0; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = htons(host->sport[1]); saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } host->fs[1].saddr = saddr; /* if we are not just binding port number then we are server*/ //if(saddr.sin_addr.s_addr == inet_addr("0.0.0.0")){ if (host->role == 1) { vtun_syslog(LOG_INFO, "udp_session for server 2"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd2, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } vtun_syslog(LOG_INFO, "Waiting for UDP ACK 2 wrote port %d", port); opt = sizeof(saddr); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "UDP ACK 2 from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); host->fs[1].daddr.sin_family = saddr.sin_family; host->fs[1].daddr.sin_port = saddr.sin_port; host->fs[1].daddr.sin_addr.s_addr = saddr.sin_addr.s_addr; inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[1].daddr.sin_port)); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } write_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "FINAL ACK SENT 2"); } else { vtun_syslog(LOG_INFO, "udp_session for client 2"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd2, (char *) &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd2, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; vtun_syslog(LOG_INFO, "Recieved port %d info from server 2", port); sendto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, opt); host->fs[1].daddr = saddr; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } read_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "Connected & Recived final ACK 2"); } host->rmt_sock2 = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd2); host->rmt_fd2 = s; //add by Kai for multiple interfaces host->fs[1].fd = s; host->fs[1].fd_flag = 1; inet_ntop(AF_INET, &(host->fs[0].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[0].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[0].daddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[1].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[1].daddr.sin_port)); host->fs[0].saddr.sin_port = htons(4444); host->fs[0].daddr.sin_port = htons(4444); host->fs[1].saddr.sin_port = htons(4444); host->fs[1].daddr.sin_port = htons(4444); /* host->fs[0].saddr.sin_port = htons(host->dport[1]+10); host->fs[0].daddr.sin_port = htons(host->dport[1]+10); host->fs[1].saddr.sin_port = htons(host->dport[1]+10); host->fs[1].daddr.sin_port = htons(host->dport[1]+10); */ inet_ntop(AF_INET, &(host->fs[0].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[0].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[0].daddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[1].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[1].daddr.sin_port)); vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }
int main(int argc, char *argv[], char *env[]) { int svr, daemon, sock, dofork, fd, opt; struct vtun_host *host = NULL; struct sigaction sa; char *hst; /* Configure default settings */ svr = 0; daemon = 1; sock = 0; dofork = 1; vtun.cfg_file = VTUN_CONFIG_FILE; vtun.persist = -1; vtun.timeout = -1; /* Dup strings because parser will try to free them */ vtun.ppp = strdup("/usr/sbin/pppd"); vtun.ifcfg = strdup("/sbin/ifconfig"); vtun.route = strdup("/sbin/route"); vtun.fwall = strdup("/sbin/ipchains"); vtun.iproute = strdup("/sbin/ip"); vtun.svr_name = NULL; vtun.svr_addr = NULL; vtun.bind_addr.port = -1; vtun.svr_type = -1; vtun.syslog = LOG_DAEMON; /* Initialize default host options */ memset(&default_host, 0, sizeof(default_host)); default_host.flags = VTUN_TTY | VTUN_TCP|VTUN_SCTP; default_host.multi = VTUN_MULTI_ALLOW; default_host.timeout = VTUN_CONNECT_TIMEOUT; default_host.ka_interval = 30; default_host.ka_maxfail = 4; default_host.loc_fd = default_host.rmt_fd = -1; /* Start logging to syslog and stderr */ openlog("vtund", LOG_PID | LOG_NDELAY | LOG_PERROR, LOG_DAEMON); while( (opt=getopt(argc,argv,"misf:P:L:t:npq")) != EOF ){ switch(opt){ case 'm': if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) { perror("Unable to mlockall()"); exit(-1); } break; case 'i': vtun.svr_type = VTUN_INETD; case 's': svr = 1; break; case 'L': vtun.svr_addr = strdup(optarg); break; case 'P': vtun.bind_addr.port = atoi(optarg); break; case 'f': vtun.cfg_file = strdup(optarg); break; case 'n': daemon = 0; break; case 'p': vtun.persist = 1; break; case 't': vtun.timeout = atoi(optarg); break; case 'q': vtun.quiet = 1; break; default: usage(); exit(1); } } reread_config(0); if (vtun.syslog != LOG_DAEMON) { /* Restart logging to syslog using specified facility */ closelog(); openlog("vtund", LOG_PID|LOG_NDELAY|LOG_PERROR, vtun.syslog); } clear_nat_hack_flags(svr); if(!svr){ if( argc - optind < 2 ){ usage(); exit(1); } hst = argv[optind++]; if( !(host = find_host(hst)) ){ vtun_syslog(LOG_ERR,"Host %s not found in %s", hst, vtun.cfg_file); exit(1); } vtun.svr_name = strdup(argv[optind]); } /* * Now fill uninitialized fields of the options structure * with default values. */ if(vtun.bind_addr.port == -1) vtun.bind_addr.port = VTUN_PORT; if(vtun.persist == -1) vtun.persist = 0; if(vtun.timeout == -1) vtun.timeout = VTUN_TIMEOUT; switch( vtun.svr_type ){ case -1: vtun.svr_type = VTUN_STAND_ALONE; break; case VTUN_INETD: sock = dup(0); dofork = 0; break; } if( daemon ){ if( dofork && fork() ) exit(0); /* Direct stdin,stdout,stderr to '/dev/null' */ fd = open("/dev/null", O_RDWR); close(0); dup(fd); close(1); dup(fd); close(2); dup(fd); close(fd); setsid(); chdir("/"); } if(svr){ memset(&sa,0,sizeof(sa)); sa.sa_handler=reread_config; sigaction(SIGHUP,&sa,NULL); init_title(argc,argv,env,"vtund[s]: "); if( vtun.svr_type == VTUN_STAND_ALONE ) write_pid(); runmode=1; server(sock); } else { init_title(argc,argv,env,"vtund[c]: "); runmode=0; client(host); } closelog(); return 0; }
int sctp_session(struct vtun_host *host) { extern int runmode; int s, opt, newfd, i; int len; short port; struct sockaddr_in saddr, caddr; struct addrinfo hints, *srvinfo, *p; memset(&hints, 0, sizeof hints); memset(&caddr, 0, sizeof caddr); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_SCTP; len=0; vtun_syslog(LOG_ERR, "进入sctp"); if (runmode == 1) { //server vtun_syslog(LOG_ERR, "进入server"); hints.ai_flags = AI_PASSIVE; i = getaddrinfo(NULL, "9000", &hints, &srvinfo); if (i < 0) { fprintf(stderr, "getaddrinfo %s\n", gai_strerror(i)); return -1; } for (p = srvinfo; p != NULL; p = p->ai_next) { s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (s < 0) continue; i = bind(s, p->ai_addr, p->ai_addrlen); if (i == 0) break; } if (p == NULL) { perror("bind 失败\n"); return -1; } i = listen(s, 10); if (i < 0) { perror("listen 失败\n"); return -1; } vtun_syslog(LOG_ERR, "等待客户端连接..."); newfd = accept(s, (struct sockaddr *) &caddr, &len); if (newfd < 0) { vtun_syslog(LOG_ERR, "不能接受客户端链接!!"); return -1; } vtun_syslog(LOG_ERR, "切换fd"); close(host->rmt_fd); host->rmt_fd = newfd; } else { //client vtun_syslog(LOG_ERR, "进入client"); //debug i = getaddrinfo(vtun.svr_name, "9000", &hints, &srvinfo); vtun_syslog(LOG_ERR, "建立sctp socket"); if (i != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(i)); return -1; } for (p = srvinfo; p != NULL; p = p->ai_next) { s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (s == -1) { vtun_syslog(LOG_ERR, "建立socket失败"); continue; } sleep(2); if (connect(s, p->ai_addr, p->ai_addrlen) == -1) { vtun_syslog(LOG_ERR, "不能连接server.."); continue; } break; } if (p == NULL) { vtun_syslog(LOG_ERR, "sctp 失败.."); return -1; } vtun_syslog(LOG_ERR, "成功链接."); close(host->rmt_fd); host->rmt_fd = s; } return 0; }
int no_lzo(struct vtun_host *host) { vtun_syslog(LOG_INFO, "LZO compression is not supported"); return -1; }
static void sig_term(int sig) { vtun_syslog(LOG_INFO,"Terminated"); client_term = VTUN_SIG_TERM; }
int udp_session2(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = host->sport[0]; saddr.sin_addr.s_addr = inet_addr(host->saddr[0].ip); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } host->sopt.rport = htons(port); host->rmt_sock = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket2"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ saddr.sin_port = host->sport[1]; saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); vtun_syslog(LOG_ERR, "address %s:%d", host->saddr[0].ip, host->sport[0]); vtun_syslog(LOG_ERR, "address %s:%d", host->saddr[1].ip, host->sport[1]); vtun_syslog(LOG_ERR, "address %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket2 (%d:%s)", errno, strerror(errno)); return -1; } saddr.sin_port = host->dport[1]; saddr.sin_addr.s_addr = inet_addr(host->daddr[1].ip); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket2 "); return -1; } host->rmt_sock2 = saddr; host->rmt_fd2 = s; //vtun.rmt_sock2 = saddr; //vtun.rmt_fd2 = s; vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }
int udp_session(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; extern int is_rmt_fd_connected; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /* Set local address and port */ local_addr(&saddr, host, 1); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; /* if the config says to delay the UDP connection, we wait for an incoming packet and then force a connection back. We need to put this here because we need to keep that incoming triggering packet and pass it back up the chain. */ if (VTUN_USE_NAT_HACK(host)) is_rmt_fd_connected = 0; else { if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } is_rmt_fd_connected = 1; } host->sopt.rport = htons(port); /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }