Пример #1
0
void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
{
	int val = 0;
	int sockets[2] = {-1, -1};

	udpsocks = Memory_safeCalloc(nofServerSocks / 2, sizeof(int));

	if (hasv4) {
		sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
		if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0) {
			char *addressString = Util_addressToString(addresses[0]);
			Log_fatal("bind %s %d: %s", addressString, Util_addressToPort(addresses[0]), strerror(errno));
			free(addressString);
		}
		val = 0xe0;
		if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
			Log_warn("Server: Failed to set TOS for UDP Socket");
		val = 0x80;
		if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
			Log_warn("Server: Failed to set TOS for UDP Socket");

		fcntl(sockets[0], F_SETFL, O_NONBLOCK);
		pollfds[(hasv6) ? 2 : 1].fd = sockets[0];
		pollfds[(hasv6) ? 2 : 1].events = POLLIN | POLLHUP | POLLERR;
		udpsocks[0] = sockets[0];
	}

	if (hasv6) {
		sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
		if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
			Log_fatal("setsockopt IPv6: %s", strerror(errno));
		if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0) {
			char *addressString = Util_addressToString(addresses[1]);
			Log_fatal("bind %s %d: %s", addressString, Util_addressToPort(addresses[1]), strerror(errno));
			free(addressString);
		}
		val = 0xe0;
		if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
			Log_warn("Server: Failed to set TOS for UDP Socket");
		val = 0x80;
		if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
			Log_warn("Server: Failed to set TOS for UDP Socket");

		fcntl(sockets[1], F_SETFL, O_NONBLOCK);
		pollfds[(hasv4) ? 3 : 1].fd = sockets[1];
		pollfds[(hasv4) ? 3 : 1].events = POLLIN | POLLHUP | POLLERR;
		udpsocks[(hasv4) ? 1 : 0] = sockets[1];
	}

}
Пример #2
0
void * Memory_safeMalloc(size_t nmem, size_t size) {
	// Check if we're going to overflow.
	if (size && nmem > SIZE_MAX / size)
		Log_fatal("Request for memory would've overflowed.");

	// Allocate the memory requested.
	void * retPtr = malloc(nmem * size);

	// Check if we had an error.
	if (retPtr == NULL)
		Log_fatal("Out of memory.");

	return retPtr;
}
Пример #3
0
/* Check which IP versions are supported by the system. */
void checkIPversions()
{
	int testsocket = -1;

	testsocket = socket(PF_INET, SOCK_STREAM, 0);
	hasv4 = (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) ? false : true;
	if (!(testsocket < 0)) close(testsocket);

	testsocket = socket(PF_INET6, SOCK_STREAM, 0);
	hasv6 = (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) ? false : true;
	if (!(testsocket < 0)) close(testsocket);

	if(!hasv4)
	{
		Log_info("IPv4 is not supported by this system");
		nofServerSocks -= 2;
	}

	if(!hasv6)
	{
		Log_info("IPv6 is not supported by this system");
		nofServerSocks -= 2;
	}
	if(nofServerSocks == 0)
	{
		Log_fatal("Neither IPv4 nor IPv6 are supported by this system");
	}
}
Пример #4
0
void lockfile(const char *pidfile)
{
	int lfp, flags;
	char str[16];

	/* Don't use O_TRUNC here -- we want to leave the PID file
	 * unmodified if we cannot lock it.
	 */
	lfp = open(pidfile, O_WRONLY|O_CREAT, 0640);

	if (lfp < 0)
		Log_fatal("Cannot open PID-file %s for writing", pidfile);

	/* Try to lock the file. */
	if (lockf(lfp, F_TLOCK, 0) < 0) {
		close(lfp);

		if (errno == EACCES || errno == EAGAIN)
			Log_fatal("PID file is locked -- uMurmur already running?");

		Log_fatal("Cannot lock PID file: %s", strerror(errno));
	}

	/* Now that we locked the file, erase its contents. */
	if (ftruncate(lfp, 0) < 0) {
		close(lfp);
		Log_fatal("Cannot truncate PID file: %s", strerror(errno));
	}

	snprintf(str,16,"%d\n", getpid());
	(void)write(lfp, str, strlen(str)); /* record pid to lockfile */
	Log_info("PID-file: %s", pidfile);

	/* If uMurmur ever starts to fork()+exec(), we don't want it to
	 * leak the fd to the forked process though. Set the close-on-exec
	 * flag to prevent leakage.
	 */
	flags = fcntl(lfp, F_GETFD, 0);
	flags |= FD_CLOEXEC;
	fcntl(lfp, F_SETFD, (long) flags);

	/* Don't close(lfp) here!
	 * We want the fd to remain opened so the lock is held until the
	 * process exits.
	 */
	lfp = -1;
}
Пример #5
0
void Server_setupTCPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
{
	int yes = 1;
	int sockets[2];

	if (hasv4) {
		/* IPv4 socket setup */
		sockets[0] = socket(PF_INET, SOCK_STREAM, 0);
		if (sockets[0] < 0)
			Log_fatal("socket IPv4");
		if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
			Log_fatal("setsockopt IPv4: %s", strerror(errno));
		if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0) {
			char *addressString = Util_addressToString(addresses[0]);
			Log_fatal("bind %s %d: %s", addressString, Util_addressToPort(addresses[0]), strerror(errno));
			free(addressString);
		}
		if (listen(sockets[0], 3) < 0)
			Log_fatal("listen IPv4");
		fcntl(sockets[0], F_SETFL, O_NONBLOCK);

		pollfds[0].fd = sockets[0];
		pollfds[0].events = POLLIN;
	}

	if (hasv6) {
		/* IPv6 socket setup */
		sockets[1] = socket(PF_INET6, SOCK_STREAM, 0);
		if (sockets[1] < 0)
			Log_fatal("socket IPv6: %s", strerror(errno));
		if (setsockopt(sockets[1], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
			Log_fatal("setsockopt IPv6: %s", strerror(errno));
		if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
			Log_fatal("setsockopt IPv6: %s", strerror(errno));
		if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0) {
			char *addressString = Util_addressToString(addresses[1]);
			Log_fatal("bind %s %d: %s", addressString, Util_addressToPort(addresses[1]), strerror(errno));
			free(addressString);
		}
		if (listen(sockets[1], 3) < 0)
			Log_fatal("listen IPv6");
		fcntl(sockets[1], F_SETFL, O_NONBLOCK);


		/* If  there is an IPv4 address, then IPv6 will use the second socket, otherwise it uses the first */
		pollfds[(hasv4) ? 1 : 0].fd = sockets[1];
		pollfds[(hasv4) ? 1 : 0].events = POLLIN;
	}
}
Пример #6
0
void Conf_init(const char *conffile)
{
	config_init(&configuration);
	if (conffile == NULL)
		conffile = defaultconfig;
	if (config_read_file(&configuration, conffile) != CONFIG_TRUE) {
		Log_fatal("Error in config file %s line %d: %s", conffile,
			config_error_line(&configuration), config_error_text(&configuration));
	}
}
Пример #7
0
void * Memory_safeCalloc(size_t nmem, size_t size) {
	// Allocate the memory requested.
	void * retPtr = calloc(nmem, size);

	// Check if we had an error.
	if (retPtr == NULL)
		Log_fatal("Out of memory.");

	return retPtr;
}
Пример #8
0
void Sharedmemory_init( int bindport, int bindport6 ) 
{
                 
  int server_max_clients = getIntConf(MAX_CLIENTS);  
  int shmtotal_size =  sizeof( shm_t  ) + (sizeof( shmclient_t ) * server_max_clients);

  if( !bindport )
  {
    bindport = getIntConf(BINDPORT);  
  }

  sprintf( shm_file_name, "/umurmurd:%i", bindport );
  Log_info("SHM_API: shm_fd=\"%s\"", shm_file_name  );

    shm_fd = shm_open( shm_file_name, O_CREAT | O_RDWR, 0660 );
        if(shm_fd == -1)
        {
            Log_fatal( "SHM_API: Open failed:%s\n", strerror(errno));
            exit(EXIT_FAILURE);
        }  

        if( ftruncate( shm_fd, shmtotal_size ) == -1 )
        {
            Log_fatal( "SHM_API: ftruncate : %s\n", strerror(errno));  
            exit(EXIT_FAILURE);
        }

        shmptr = mmap( 0, shmtotal_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0 );
        if (shmptr == MAP_FAILED) 
        {
            Log_fatal( "SHM_API: mmap failed : %s\n", strerror(errno));
            exit(EXIT_FAILURE);
        } 

  memset( shmptr, 0, shmtotal_size );

  shmptr->umurmurd_pid = getpid();
  shmptr->server_max_clients = server_max_clients;   
  shmptr->shmtotal_size = shmtotal_size;
  shmptr->shmclient_size = sizeof( shmclient_t ) * shmptr->server_max_clients;                           
 
}
Пример #9
0
Файл: pds.c Проект: swak/umurmur
pds_t *Pds_create(uint8_t *buf, int size)
{
	pds_t *pds = malloc(sizeof(pds_t));
	if (pds == NULL)
		Log_fatal("Out of memory");
	pds->data = buf;
	pds->offset = pds->overshoot = 0;
	pds->maxsize = size;
	pds->bOk = true;
	return pds;
}
Пример #10
0
void SSLi_init()
{
	if(gnutls_priority_init(&cipherCache, ciphers, NULL) != GNUTLS_E_SUCCESS)
	{
		Log_fatal("Failed to set priorities");
	}

	initializeCertificate();

	Log_info("Sucessfully initialized GNUTLS version %s", gnutls_check_version(NULL));
}
Пример #11
0
void initializeCertificate()
{
	char* certificatePath = (char*) getStrConf(CERTIFICATE);

	if(!certificatePath) {
		Log_fatal("No certificate file specified.");
	}

	char* keyPath = (char*) getStrConf(KEY);

	if(!keyPath) {
		Log_fatal("No key file specified");
	}

	gnutls_certificate_allocate_credentials(&certificate);

	int error = gnutls_certificate_set_x509_key_file(certificate, certificatePath, keyPath, GNUTLS_X509_FMT_PEM);

	if( error != GNUTLS_E_SUCCESS ) {
		Log_fatal("Could not open key (%s) or certificate (%s).", keyPath, certificatePath);
	}
}
Пример #12
0
static void openlogfile(const char *logfilename)
{
	int fd, flags;
	logfile = fopen(logfilename, "a");
	if (logfile == NULL) {
		Log_fatal("Failed to open log file '%s' for writing: %s\n", logfilename, strerror(errno));
	}

	/* Set the stream as line buffered */
	if (setvbuf(logfile, NULL, _IOLBF, 0) < 0)
		Log_fatal("setvbuf() failed: %s\n", strerror(errno));
	
	/* XXX - Is it neccessary/appropriate that logging to file is non-blocking?
	 * If not, there's a risk that execution blocks, meaning that voice blocks
	 * as well since uMurmur is single threaded by design. OTOH, what could
	 * cause a block? If the disk causes blocking, it is probably br0ken, but
	 * the log could be on a nfs or smb share, so let's set it up as
	 * non-blocking and we'll see what happens.
	 */
	fd = fileno(logfile);
	flags = fcntl(fd, F_GETFL, 0);
	fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
Пример #13
0
/* Drops privileges (if configured to do so). */
static void switch_user(void)
{
	struct passwd *pwd;
	struct group *grp = NULL;
	const char *username, *groupname;
	gid_t gid;

	username = getStrConf(USERNAME);
	groupname = getStrConf(GROUPNAME);

	if (!*username) {
		/* It's an error to specify groupname
		 * but leave username empty.
		 */
		if (*groupname)
			Log_fatal("username missing");

		/* Nothing to do. */
		return;
	}

	pwd = getpwnam(username);
	if (!pwd)
		Log_fatal("Unknown user '%s'", username);

	if (!*groupname)
		gid = pwd->pw_gid;
	else {
		grp = getgrnam(groupname);

		if (!grp)
			Log_fatal("Unknown group '%s'", groupname);

		gid = grp->gr_gid;
	}

	if (initgroups(pwd->pw_name, gid))
		Log_fatal("initgroups() failed: %s", strerror(errno));

	if (setgid(gid))
		Log_fatal("setgid() failed: %s", strerror(errno));

	if (setuid(pwd->pw_uid))
		Log_fatal("setuid() failed: %s", strerror(errno));

	if (!grp)
		grp = getgrgid(gid);
	if (!grp)
		Log_fatal("getgrgid() failed: %s", strerror(errno));

	Log_info("Switch to user '%s' group '%s'", pwd->pw_name, grp->gr_name);
}
Пример #14
0
void Server_runLoop(struct pollfd* pollfds)
{
	int timeout, rc, clientcount;

	etimer_t janitorTimer;
	Timer_init(&janitorTimer);

	while (!shutdown_server) {
		struct sockaddr_storage remote;
		int i;

#ifdef USE_SHAREDMEMORY_API
    Sharedmemory_alivetick();
#endif

		for(i = 0; i < nofServerSocks; i++) {
			pollfds[i].revents = 0;
		}

		clientcount = Client_getfds(&pollfds[nofServerSocks]);

		timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		if (timeout <= 0) {
			Client_janitor();
			Timer_restart(&janitorTimer);
			timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		}
		rc = poll(pollfds, clientcount + nofServerSocks, timeout);
		if (rc == 0) {
			/* Poll timed out, do maintenance */
			Timer_restart(&janitorTimer);
			Client_janitor();
			continue;
		}
		if (rc < 0) {
			if (errno == EINTR) /* signal */
				continue;
			else
				Log_fatal("poll: error %d (%s)", errno, strerror(errno));
		}

		/* Check for new connection */
		for (i = 0; i < nofServerSocks / 2; i++) {
			if (pollfds[i].revents) {
				int tcpfd;
				uint32_t addrlen = sizeof(struct sockaddr_storage);
				tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
				fcntl(tcpfd, F_SETFL, O_NONBLOCK);
				setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
				char *addressString = Util_addressToString(&remote);
				Log_debug("Connection from %s port %d\n", addressString, Util_addressToPort(&remote));
				free(addressString);
				if (Client_add(tcpfd, &remote) < 0)
					close(tcpfd);
			}
		}

		for (i = nofServerSocks / 2; i < nofServerSocks; i++) {
			if (pollfds[i].revents)
				Client_read_udp(udpsocks[i - nofServerSocks / 2]);
		}

		for (i = 0; i < clientcount; i++) {
			if (pollfds[nofServerSocks + i].revents & POLLIN)
				Client_read_fd(pollfds[nofServerSocks + i].fd);

			if (pollfds[nofServerSocks + i].revents & POLLOUT)
				Client_write_fd(pollfds[nofServerSocks + i].fd);
		}
#ifdef USE_SHAREDMEMORY_API
    Sharedmemory_update();
#endif
	}
}
Пример #15
0
void Server_run()
{
	int timeout = 1000, rc;
	struct pollfd *pollfds;
	int tcpsock, sockopt = 1;
	struct sockaddr_storage sin;
	int val, clientcount;
	etimer_t janitorTimer;
	const char *port;
	const char *addr;
	struct addrinfo hints, *res;
	bool_t enable_ipv6;

	/* max clients + listen sock + udp sock + client connecting that will be disconnected */
	pollfds = malloc((getIntConf(MAX_CLIENTS) + 3) * sizeof(struct pollfd));
	if (pollfds == NULL)
		Log_fatal("out of memory");

	/* Figure out bind address and port */
	if (bindport != 0)
		port = bindport;
	else
		port = getStrConf(BINDPORT);

	if (bindaddr != 0)
		addr = bindaddr;
	else
		addr = getStrConf(BINDADDR);
	
	/* Prepare TCP socket */

	enable_ipv6 = getBoolConf(ENABLE_IPV6);
	if (enable_ipv6) { /* Test if supported */
		int testsock = socket(AF_INET6, SOCK_STREAM, 0);
		if (testsock < 0 && errno == EAFNOSUPPORT) {
			Log_warn("IPv6 is not supported on this machine. Falling back to IPv4.");
			enable_ipv6 = false;
		}
		if (testsock > 0) close(testsock);
	}

	memset(&hints, 0, sizeof hints);
	if (enable_ipv6) {
		hints.ai_family = AF_INET6;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_PASSIVE | AI_V4MAPPED;
		hints.ai_protocol = 0;
	} else { /* IPv4 */
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_PASSIVE;
		hints.ai_protocol = 0;
	}
	rc = getaddrinfo(addr, port, &hints, &res);
	if (rc != 0)
		Log_fatal("getaddrinfo: %s", gai_strerror(rc));

	Log_info("Bind to [%s]:%s", addr ? addr : "::" , port);

	tcpsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (tcpsock < 0)
		Log_fatal("socket: %s", strerror(errno));
	if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) != 0)
		Log_fatal("setsockopt: %s",strerror(errno));
	rc = bind(tcpsock, res->ai_addr, res->ai_addrlen);
	if (rc < 0)
		Log_fatal("bind: %s", strerror(errno));
	rc = listen(tcpsock, 3);
	if (rc < 0)
		Log_fatal("listen");
	fcntl(tcpsock, F_SETFL, O_NONBLOCK);

	pollfds[LISTEN_SOCK].fd = tcpsock;
	pollfds[LISTEN_SOCK].events = POLLIN;
	freeaddrinfo(res);

	/* Prepare UDP socket */

	memset(&hints, 0, sizeof hints);
	if (enable_ipv6) {
		hints.ai_family = AF_INET6;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_flags = AI_PASSIVE | AI_V4MAPPED;
		hints.ai_protocol = 0;
	} else { /* IPv4 */
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_DGRAM;
		hints.ai_flags = AI_PASSIVE;
		hints.ai_protocol = 0;
	}
	rc = getaddrinfo(addr, port, &hints, &res);
	if (rc != 0) Log_fatal("getaddrinfo: %s", gai_strerror(rc));

	udpsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	rc = bind(udpsock, res->ai_addr, res->ai_addrlen);
	if (rc < 0)
		Log_fatal("bind %d %s: %s", bindport, bindaddr, strerror(errno));
	val = 0xe0;
	rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
	if (rc < 0)
		Log_warn("Server: Failed to set TOS for UDP Socket");
	val = 0x80;
	rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
	if (rc < 0)
		Log_warn("Server: Failed to set TOS for UDP Socket");
	fcntl(udpsock, F_SETFL, O_NONBLOCK);
	listen(udpsock, 10);

	pollfds[UDP_SOCK].fd = udpsock;
	pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
	freeaddrinfo(res);

	Timer_init(&janitorTimer);
	
	Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
	         UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
	Log_info("Visit http://code.google.com/p/umurmur/");
	
	/* Main server loop */
	while (!shutdown_server) {
		struct sockaddr_storage remote;
		int i;
		
		pollfds[UDP_SOCK].revents = 0;
		pollfds[TCP_SOCK].revents = 0;
		clientcount = Client_getfds(&pollfds[2]);
		
		timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		if (timeout <= 0) {
			Client_janitor();
			Timer_restart(&janitorTimer);
			timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		}
		rc = poll(pollfds, clientcount + 2, timeout);
		if (rc == 0) { /* Timeout */
			/* Do maintenance */
			Timer_restart(&janitorTimer);
			Client_janitor();
			continue;
		}
		if (rc < 0) {
			if (errno == EINTR) /* signal */
				continue;
			else
				Log_fatal("poll: error %d", errno);
		}
		if (pollfds[LISTEN_SOCK].revents) { /* New tcp connection */
			int tcpfd, flag = 1;
			uint32_t addrlen;
			addrlen = sizeof(struct sockaddr_storage);
			tcpfd = accept(pollfds[LISTEN_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
			fcntl(tcpfd, F_SETFL, O_NONBLOCK);
			setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
			Log_debug("Connection from %s port %d\n", inet_ntoa(remote.sin_addr),
					ntohs(remote.sin_port));
			if (Client_add(tcpfd, &remote) < 0)
				close(tcpfd);
		}

		if (pollfds[UDP_SOCK].revents) {
			Client_read_udp();
		}
		for (i = 0; i < clientcount; i++) {
			if (pollfds[i + 2].revents & POLLIN) {
				Client_read_fd(pollfds[i + 2].fd);
			}
			if (pollfds[i + 2].revents & POLLOUT) {
				Client_write_fd(pollfds[i + 2].fd);
			}
		}
	}

	/* Disconnect clients */
	Client_disconnect_all();
	free(pollfds);
}
Пример #16
0
int main (int argc, char**argv)
{
	int ret = 0;
	int heartbeat_usec = 50000; //20Hz is ok by default
	uint64_t last_beat = 0;

	Log_info ("cloudvpn starting");
	Log (0, "You are using CloudVPN, which is Free software.");
	Log (0, "For more information please see the GNU GPL license,");
	Log (0, "which you should have received along with this program.");

	setup_sighandler (kill_cloudvpn);

	/*
	 * initialization
	 */

	if (!config_parse (argc, argv) ) {
		Log_error ("failed to parse config, terminating.");
		ret = 1;
		goto failed_config;
	}

	if (!config_get_int ("heartbeat", heartbeat_usec) )
		heartbeat_usec = 50000;
	Log_info ("heartbeat is set to %d usec", heartbeat_usec);

	timestamp_update(); //get initial timestamp

	status_init();
	route_init();
	squeue_init();
	network_init();

	if (poll_init() ) {
		Log_fatal ("poll initialization failed");
		ret = 2;
		goto failed_poll;
	}

	if (do_memlock() ) {
		Log_fatal ("locking process to memory failed");
		ret = 3;
		goto failed_poll;
	}

	if (comm_load() ) {
		Log_fatal ("failed to load comm data");
		ret = 4;
		goto failed_poll;
	}

	if (comm_init() ) {
		Log_fatal ("communication initialization failed");
		ret = 5;
		goto failed_comm;
	}

	if (gate_init() ) {
		Log_fatal ("gate initialization failed");
		ret = 6;
		goto failed_gate;
	}
	if (do_chroot() ) {
		Log_fatal ("chrooting failed");
		ret = 7;
		goto failed_sec;
	}

	if (do_switch_user() ) {
		Log_fatal ("user switch failed");
		ret = 8;
		goto failed_sec;
	}


	/*
	 * main loop
	 */

	Log_info ("initialization complete, entering main loop");

	last_beat = 0; //update immediately.

	while (!g_terminate) {

		timestamp_update();

		if ( (timestamp() - last_beat)
		        < (unsigned int) heartbeat_usec) {
			//poll more stuff
			poll_wait_for_event (heartbeat_usec
			                     - timestamp()
			                     + last_beat);
			//send the results
			comm_flush_data();
			gate_flush_data();
			continue;
		}

		last_beat = timestamp();

		gate_periodic_update();
		comm_periodic_update();
		route_periodic_update();

		status_try_export();
	}

	/*
	 * deinitialization
	 */

	Log_info ("shutting down");

failed_sec:

	gate_shutdown();

failed_gate:

	comm_shutdown();

failed_comm:

	if (poll_deinit() )
		Log_warn ("poll_deinit somehow failed!");

failed_poll:
failed_config:
	if (!ret) Log_info ("cloudvpn exiting gracefully");
	else Log_error ("cloudvpn exiting with code %d", ret);
	return ret;
}
Пример #17
0
void Server_run()
{
	int timeout = 1000, rc;
	struct pollfd *pollfds;
	int tcpsock, sockopt = 1;
	struct sockaddr_in sin;
	int val, clientcount;
	etimer_t janitorTimer;
	unsigned short port;
	in_addr_t inet_address;

	/* max clients + listen sock + udp sock + client connecting that will be disconnected */
	pollfds = malloc((getIntConf(MAX_CLIENTS) + 3) * sizeof(struct pollfd));
	if (pollfds == NULL)
		Log_fatal("out of memory");

	/* Figure out bind address and port */
	if (bindport != 0)
		port = htons(bindport);
	else
		port = htons(getIntConf(BINDPORT));

	if (bindaddr != NULL && inet_addr(bindaddr) != -1)
		inet_address = inet_addr(bindaddr);
	else if (inet_addr(getStrConf(BINDADDR)) !=  -1)
		inet_address = inet_addr(getStrConf(BINDADDR));
	else
		inet_address = inet_addr("0.0.0.0");
	Log_info("Bind to %s:%hu", inet_address == 0 ? "*" : inet_ntoa(*((struct in_addr *)&inet_address)), ntohs(port));

	/* Prepare TCP socket */
	memset(&sin, 0, sizeof(sin));
	tcpsock = socket(PF_INET, SOCK_STREAM, 0);
	if (tcpsock < 0)
		Log_fatal("socket");
	if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) != 0)
		Log_fatal("setsockopt: %s", strerror(errno));
	sin.sin_family = AF_INET;
	sin.sin_port = port;
	sin.sin_addr.s_addr = inet_address;

	rc = bind(tcpsock, (struct sockaddr *) &sin, sizeof (struct sockaddr_in));
	if (rc < 0) Log_fatal("bind: %s", strerror(errno));
	rc = listen(tcpsock, 3);
	if (rc < 0) Log_fatal("listen");
	fcntl(tcpsock, F_SETFL, O_NONBLOCK);

	pollfds[LISTEN_SOCK].fd = tcpsock;
	pollfds[LISTEN_SOCK].events = POLLIN;

	/* Prepare UDP socket */
	memset(&sin, 0, sizeof(sin));
	udpsock = socket(PF_INET, SOCK_DGRAM, 0);
	sin.sin_family = AF_INET;
	sin.sin_port = port;
	sin.sin_addr.s_addr = inet_address;

	rc = bind(udpsock, (struct sockaddr *) &sin, sizeof (struct sockaddr_in));
	if (rc < 0)
		Log_fatal("bind %d %s: %s", getIntConf(BINDPORT), getStrConf(BINDADDR), strerror(errno));
	val = 0xe0;
	rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
	if (rc < 0)
		Log_warn("Server: Failed to set TOS for UDP Socket");
	val = 0x80;
	rc = setsockopt(udpsock, IPPROTO_IP, IP_TOS, &val, sizeof(val));
	if (rc < 0)
		Log_warn("Server: Failed to set TOS for UDP Socket");

	fcntl(udpsock, F_SETFL, O_NONBLOCK);
	pollfds[UDP_SOCK].fd = udpsock;
	pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;

	Timer_init(&janitorTimer);

	Log_info("uMurmur version %s ('%s') protocol version %d.%d.%d",
	         UMURMUR_VERSION, UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
	Log_info("Visit http://code.google.com/p/umurmur/");

	/* Main server loop */
	while (!shutdown_server) {
		struct sockaddr_in remote;
		int i;

		pollfds[UDP_SOCK].revents = 0;
		pollfds[TCP_SOCK].revents = 0;
		clientcount = Client_getfds(&pollfds[2]);

		timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		if (timeout <= 0) {
			Client_janitor();
			Timer_restart(&janitorTimer);
			timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
		}
		rc = poll(pollfds, clientcount + 2, timeout);
		if (rc == 0) { /* Timeout */
			/* Do maintenance */
			Timer_restart(&janitorTimer);
			Client_janitor();
			continue;
		}
		if (rc < 0) {
			if (errno == EINTR) /* signal */
				continue;
			else
				Log_fatal("poll: error %d", errno);
		}
		if (pollfds[LISTEN_SOCK].revents) { /* New tcp connection */
			int tcpfd, flag = 1;
			uint32_t addrlen;
			addrlen = sizeof(struct sockaddr_in);
			tcpfd = accept(pollfds[LISTEN_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
			fcntl(tcpfd, F_SETFL, O_NONBLOCK);
			setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
			Log_debug("Connection from %s port %d\n", inet_ntoa(remote.sin_addr),
					  ntohs(remote.sin_port));
			if (Client_add(tcpfd, &remote) < 0)
				close(tcpfd);
		}

		if (pollfds[UDP_SOCK].revents) {
			Client_read_udp();
		}
		for (i = 0; i < clientcount; i++) {
			if (pollfds[i + 2].revents & POLLIN) {
				Client_read_fd(pollfds[i + 2].fd);
			}
			if (pollfds[i + 2].revents & POLLOUT) {
				Client_write_fd(pollfds[i + 2].fd);
			}
		}
	}

	/* Disconnect clients */
	Client_disconnect_all();
	free(pollfds);
}