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; }
static int get_connecting_socket(struct descriptor_set d_set) { #ifdef HAVE_SOCKLEN_T socklen_t size; #else int size; #endif static int nfd; int shandle, ahandle; fd_set backupset; struct sockaddr_in sin; size = sizeof(sin); memcpy(&backupset, &d_set.set, sizeof(fd_set)); /* is there no remaining ready fd from the last select() ? */ if (nfd == 0) { while (1) { /* eternal select() */ /* nfd returns the number of fds that are ready */ nfd = select(d_set.maxfd + 1, &d_set.set, 0, 0, 0); if (nfd > 0) { break; } if (errno == EINTR) { memcpy(&d_set.set, &backupset, sizeof(fd_set)); if (chlds_exited > 0) { get_chld_pid(); } if (should_read_config) { jlog(9, "Re-reading configuration"); reread_config(); } continue; } jlog(1, "select() failed: %s, nfd: %d", strerror(errno), nfd); return -1; } } /* a descriptor is ready */ shandle = 0; while (!FD_ISSET(shandle, &d_set.set)) { shandle++; } /* one descriptor less is ready in the set */ nfd--; while(1) { ahandle = accept(shandle, (struct sockaddr *) &sin, &size); if (ahandle < 0) { switch(errno) { case EINTR: /* signal */ case ECONNRESET: /* client quit before three-way-handshake */ case ENETDOWN: /* the others: see manpage */ #ifdef EPROTO case EPROTO: #endif case ENOPROTOOPT: case EHOSTDOWN: #ifdef ENONET case ENONET: #endif case EHOSTUNREACH: case EOPNOTSUPP: case ENETUNREACH: continue; } jlog(1, "accept() failed: %s", strerror(errno)); return -1; } break; } return ahandle; }