/* 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 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); }
static 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); server_term = 0; set_title("waiting for connections on port %d", vtun.bind_addr.port); 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); connection(s1); break; case -1: vtun_syslog(LOG_ERR, "Couldn't fork()"); default: close(s1); break; } } }