Exemple #1
0
/*
  close all open network connections
*/
void close_network_connections(meshlink_handle_t *mesh) {
	if(mesh->connections) {
		for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
			next = node->next;
			connection_t *c = node->data;
			c->outgoing = NULL;
			terminate_connection(mesh, c, false);
		}
	}

	if(mesh->outgoings)
		list_delete_list(mesh->outgoings);

	if(mesh->self && mesh->self->connection) {
		terminate_connection(mesh, mesh->self->connection, false);
		free_connection(mesh->self->connection);
	}

	for(int i = 0; i < mesh->listen_sockets; i++) {
		io_del(&mesh->loop, &mesh->listen_socket[i].tcp);
		io_del(&mesh->loop, &mesh->listen_socket[i].udp);
		close(mesh->listen_socket[i].tcp.fd);
		close(mesh->listen_socket[i].udp.fd);
	}

	exit_requests(mesh);
	exit_edges(mesh);
	exit_nodes(mesh);
	exit_connections(mesh);

	if(mesh->myport) free(mesh->myport);

	return;
}
Exemple #2
0
/*
  close all open network connections
*/
void close_network_connections(void) {
    avl_node_t *node, *next;
    connection_t *c;
    char *envp[5];
    int i;

    for(node = connection_tree->head; node; node = next) {
        next = node->next;
        c = node->data;
        c->outgoing = NULL;
        terminate_connection(c, false);
    }

    for(list_node_t *node = outgoing_list->head; node; node = node->next) {
        outgoing_t *outgoing = node->data;

        if(outgoing->event)
            event_del(outgoing->event);
    }

    list_delete_list(outgoing_list);

    if(myself && myself->connection) {
        subnet_update(myself, NULL, false);
        terminate_connection(myself->connection, false);
        free_connection(myself->connection);
    }

    for(i = 0; i < listen_sockets; i++) {
        close(listen_socket[i].tcp);
        close(listen_socket[i].udp);
    }

    xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
    xasprintf(&envp[1], "DEVICE=%s", device ? : "");
    xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
    xasprintf(&envp[3], "NAME=%s", myself->name);
    envp[4] = NULL;

    exit_requests();
    exit_edges();
    exit_subnets();
    exit_nodes();
    exit_connections();
    exit_events();

    execute_script("tinc-down", envp);

    if(myport) free(myport);

    for(i = 0; i < 4; i++)
        free(envp[i]);

    close_device();

    return;
}
Exemple #3
0
void retrans_task() {

  if(log_g) printf ("log:retrans_task PID=%d\r\n", nrk_get_pid ());
	uint8_t cnt = 0;
	uint8_t connection_l;
	uint8_t data_cnt;
	uint8_t prev_data_seq = 0;  
//	while (!bmac_started ())
    nrk_wait_until_next_period ();

	while(1) {
		nrk_sem_pend(conn_sem);
		connection_l = connection_g;
		nrk_sem_post(conn_sem);	

		if(pending_retransmit_g == 1)  {
				if(log_g) printf("log:Re-transmitting packet\r\n");	
				bmac_tx_pkt(uart_rx_buf, strlen(uart_rx_buf));
				retransmit_count_g++;
				if(retransmit_count_g==5)
				terminate_connection();
			} else {
				// this checks if there is a connection and one is receivng data then 
				// if the sender shuts down then the connection is terminated after a while	
				if(connection_l == 1 && data_index_g < 0) {
					if(recv_data_seq_g == prev_data_seq) 
							data_cnt++;
					if(recv_data_seq_g > prev_data_seq)
					{
							data_cnt = 0; 	
							prev_data_seq = recv_data_seq_g;
					}
					if(data_cnt > 5) {
						if(log_g)nrk_kprintf(PSTR("log:Recv cn term\n"));
						terminate_connection();
						data_cnt = 0; 
					}
				}

				cnt++;
				//if(log_g) printf("log:ver activ con:%d cnt:%d\n",connection_l,cnt);
				if(cnt>0 && connection_l == 0) {
				cnt = 0;
				vertsk_active_g = 1; 
				}
			}

		nrk_wait_until_next_period();

	}
}
Exemple #4
0
/*
  Check if the other end is active.
  If we have sent packets, but didn't receive any,
  then possibly the other end is dead. We send a
  PING request over the meta connection. If the other
  end does not reply in time, we consider them dead
  and close the connection.
*/
static void check_dead_connections(void) {
	avl_node_t *node, *next;
	connection_t *c;

	for(node = connection_tree->head; node; node = next) {
		next = node->next;
		c = node->data;

		if(c->last_ping_time + pingtimeout <= now) {
			if(c->status.active) {
				if(c->status.pinged) {
					ifdebug(CONNECTIONS) logger(LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds",
							   c->name, c->hostname, (long)now - c->last_ping_time);
					c->status.timeout = true;
					terminate_connection(c, true);
				} else if(c->last_ping_time + pinginterval <= now) {
					send_ping(c);
				}
			} else {
				if(c->status.remove) {
					logger(LOG_WARNING, "Old connection_t for %s (%s) status %04x still lingering, deleting...",
						   c->name, c->hostname, bitfield_to_int(&c->status, sizeof c->status));
					connection_del(c);
					continue;
				}
				ifdebug(CONNECTIONS) logger(LOG_WARNING, "Timeout from %s (%s) during authentication",
						   c->name, c->hostname);
				if(c->status.connecting) {
					c->status.connecting = false;
					closesocket(c->socket);
					do_outgoing_connection(c);
				} else {
					terminate_connection(c, false);
				}
			}
		}

		if(c->outbuflen > 0 && c->last_flushed_time + pingtimeout <= now) {
			if(c->status.active) {
				ifdebug(CONNECTIONS) logger(LOG_INFO,
						"%s (%s) could not flush for %ld seconds (%d bytes remaining)",
						c->name, c->hostname, (long)now - c->last_flushed_time, c->outbuflen);
				c->status.timeout = true;
				terminate_connection(c, true);
			}
		}
	}
}
Exemple #5
0
void listen_to_connections() {
	/* Print status message */
	pstatus("Start of the listen");

	/* Start listen for connections */
	listen(sock_fd, 5);	

	/* Launch the main loop */
	while(1) {

		/* Get the address length */
		addr_size = sizeof(cli_addr);
		/* Accept connection */
		client_fd = accept(sock_fd, (struct sockaddr*) &cli_addr, &addr_size);

		pstatus("New connection arrived");

		/* Check if everything is correct */
		if (client_fd < 0) {
			error("Error on socket accept");
		}

		create_new_thread(client_fd);

	}

	terminate_connection();
	
}
Exemple #6
0
bool error_h(connection_t *c) {
	int err;
	char errorstring[MAX_STRING_SIZE];

	if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
		logger(LOG_ERR, "Got bad %s from %s (%s)", "ERROR",
			   c->name, c->hostname);
		return false;
	}

	ifdebug(ERROR) logger(LOG_NOTICE, "Error message from %s (%s): %d: %s",
			   c->name, c->hostname, err, errorstring);

	terminate_connection(c, c->status.active);

	return true;
}
Exemple #7
0
void
restart_connections_by_peer(struct connection *c)
{
    struct connection *d;

    if (c->host_pair == NULL)
   	   return;

    d = c->host_pair->connections;
    for (; d != NULL; d = d->hp_next) {
	   if (
#ifdef DYNAMICDNS
	       (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0))
	   	|| (c->dnshostname == NULL && d->dnshostname == NULL &&
#endif /* DYNAMICDNS */
		sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr)
#ifdef DYNAMICDNS
		)
#endif /* DYNAMICDNS */
		)
	       terminate_connection(d->name);
    }

#ifdef DYNAMICDNS
    update_host_pairs(c);
#endif /* DYNAMICDNS */

    if (c->host_pair == NULL)
    	   return;
    d = c->host_pair->connections;
    for (; d != NULL; d = d->hp_next) {
    	   if (
#ifdef DYNAMICDNS
	       (c->dnshostname && d->dnshostname && (strcmp(c->dnshostname, d->dnshostname) == 0))
	   	|| (c->dnshostname == NULL && d->dnshostname == NULL &&
#endif /* DYNAMICDNS */
		sameaddr(&d->spd.that.host_addr, &c->spd.that.host_addr)
#ifdef DYNAMICDNS
		)
#endif /* DYNAMICDNS */
		)
	       initiate_connection(d->name, NULL_FD, 0, pcim_demand_crypto);
    }
}
Exemple #8
0
/*
  this is where it all happens...
*/
int main_loop(void) {
	fd_set readset, writeset;
#ifdef HAVE_PSELECT
	struct timespec tv;
	sigset_t omask, block_mask;
	time_t next_event;
#else
	struct timeval tv;
#endif
	int r, maxfd;
	time_t last_ping_check, last_config_check, last_graph_dump;
	event_t *event;

	last_ping_check = now;
	last_config_check = now;
	last_graph_dump = now;
	
	srand(now);

#ifdef HAVE_PSELECT
	if(lookup_config(config_tree, "GraphDumpFile"))
		graph_dump = true;
	/* Block SIGHUP & SIGALRM */
	sigemptyset(&block_mask);
	sigaddset(&block_mask, SIGHUP);
	sigaddset(&block_mask, SIGALRM);
	sigprocmask(SIG_BLOCK, &block_mask, &omask);
#endif

	running = true;

	while(running) {
#ifdef HAVE_PSELECT
		next_event = last_ping_check + pingtimeout;
		if(graph_dump && next_event > last_graph_dump + 60)
			next_event = last_graph_dump + 60;

		if((event = peek_next_event()) && next_event > event->time)
			next_event = event->time;

		if(next_event <= now)
			tv.tv_sec = 0;
		else
			tv.tv_sec = next_event - now;
		tv.tv_nsec = 0;
#else
		tv.tv_sec = 1;
		tv.tv_usec = 0;
#endif

		maxfd = build_fdset(&readset, &writeset);

#ifdef HAVE_MINGW
		LeaveCriticalSection(&mutex);
#endif
#ifdef HAVE_PSELECT
		r = pselect(maxfd + 1, &readset, &writeset, NULL, &tv, &omask);
#else
		r = select(maxfd + 1, &readset, &writeset, NULL, &tv);
#endif
		now = time(NULL);
#ifdef HAVE_MINGW
		EnterCriticalSection(&mutex);
#endif

		if(r < 0) {
			if(!sockwouldblock(sockerrno)) {
				logger(LOG_ERR, "Error while waiting for input: %s", sockstrerror(sockerrno));
				dump_connections();
				return 1;
			}
		}

		if(r > 0)
			check_network_activity(&readset, &writeset);

		if(do_purge) {
			purge();
			do_purge = false;
		}

		/* Let's check if everybody is still alive */

		if(last_ping_check + pingtimeout <= now) {
			check_dead_connections();
			last_ping_check = now;

			if(routing_mode == RMODE_SWITCH)
				age_subnets();

			age_past_requests();

			/* Should we regenerate our key? */

			if(keyexpires <= now) {
				avl_node_t *node;
				node_t *n;

				ifdebug(STATUS) logger(LOG_INFO, "Expiring symmetric keys");

				for(node = node_tree->head; node; node = node->next) {
					n = node->data;
					if(n->inkey) {
						free(n->inkey);
						n->inkey = NULL;
					}
				}

				send_key_changed();
				keyexpires = now + keylifetime;
			}

			/* Detect ADD_EDGE/DEL_EDGE storms that are caused when
			 * two tinc daemons with the same name are on the VPN.
			 * If so, sleep a while. If this happens multiple times
			 * in a row, sleep longer. */

			if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
				logger(LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
				usleep(sleeptime * 1000000LL);
				sleeptime *= 2;
				if(sleeptime < 0)
					sleeptime = 3600;
			} else {
				sleeptime /= 2;
				if(sleeptime < 10)
					sleeptime = 10;
			}

			contradicting_add_edge = 0;
			contradicting_del_edge = 0;
		}

		if(sigalrm) {
			avl_node_t *node;
			logger(LOG_INFO, "Flushing event queue");
			expire_events();
			for(node = connection_tree->head; node; node = node->next) {
				connection_t *c = node->data;
				if(c->status.active)
					send_ping(c);
			}
			sigalrm = false;
		}

		while((event = get_expired_event())) {
			event->handler(event->data);
			free_event(event);
		}

		if(sighup) {
			connection_t *c;
			avl_node_t *node, *next;
			char *fname;
			struct stat s;
			
			sighup = false;

			reopenlogger();
			
			/* Reread our own configuration file */

			exit_configuration(&config_tree);
			init_configuration(&config_tree);

			if(!read_server_config()) {
				logger(LOG_ERR, "Unable to reread configuration file, exitting.");
				return 1;
			}

			/* Cancel non-active outgoing connections */

			for(node = connection_tree->head; node; node = next) {
				next = node->next;
				c = node->data;

				c->outgoing = NULL;

				if(c->status.connecting) {
					terminate_connection(c, false);
					connection_del(c);
				}
			}

			/* Wipe list of outgoing connections */

			for(list_node_t *node = outgoing_list->head; node; node = node->next) {
				outgoing_t *outgoing = node->data;

				if(outgoing->event)
					event_del(outgoing->event);
			}

			list_delete_list(outgoing_list);

			/* Close connections to hosts that have a changed or deleted host config file */
			
			for(node = connection_tree->head; node; node = node->next) {
				c = node->data;
				
				xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
				if(stat(fname, &s) || s.st_mtime > last_config_check)
					terminate_connection(c, c->status.active);
				free(fname);
			}

			last_config_check = now;

			/* If StrictSubnet is set, expire deleted Subnets and read new ones in */

			if(strictsubnets) {
				subnet_t *subnet;

				for(node = subnet_tree->head; node; node = node->next) {
					subnet = node->data;
					subnet->expires = 1;
				}

				load_all_subnets();

				for(node = subnet_tree->head; node; node = next) {
					next = node->next;
					subnet = node->data;
					if(subnet->expires == 1) {
						send_del_subnet(everyone, subnet);
						if(subnet->owner->status.reachable)
							subnet_update(subnet->owner, subnet, false);
						subnet_del(subnet->owner, subnet);
					} else if(subnet->expires == -1) {
						subnet->expires = 0;
					} else {
						send_add_subnet(everyone, subnet);
						if(subnet->owner->status.reachable)
							subnet_update(subnet->owner, subnet, true);
					}
				}
			}

			/* Try to make outgoing connections */
			
			try_outgoing_connections();
		}
		
		/* Dump graph if wanted every 60 seconds*/

		if(last_graph_dump + 60 <= now) {
			dump_graph();
			last_graph_dump = now;
		}
	}

#ifdef HAVE_PSELECT
	/* Restore SIGHUP & SIGALARM mask */
	sigprocmask(SIG_SETMASK, &omask, NULL);
#endif

	return 0;
}
Exemple #9
0
/*
  check all connections to see if anything
  happened on their sockets
*/
static void check_network_activity(fd_set * readset, fd_set * writeset) {
	connection_t *c;
	avl_node_t *node;
	int result, i;
	socklen_t len = sizeof(result);
	vpn_packet_t packet;
	static int errors = 0;

	/* check input from kernel */
	if(device_fd >= 0 && FD_ISSET(device_fd, readset)) {
		if(devops.read(&packet)) {
			if(packet.len) {
				errors = 0;
				packet.priority = 0;
				route(myself, &packet);
			}
		} else {
			usleep(errors * 50000);
			errors++;
			if(errors > 10) {
				logger(LOG_ERR, "Too many errors from %s, exiting!", device);
				running = false;
			}
		}
	}

	/* check meta connections */
	for(node = connection_tree->head; node; node = node->next) {
		c = node->data;

		if(c->status.remove)
			continue;

		if(FD_ISSET(c->socket, writeset)) {
			if(c->status.connecting) {
				c->status.connecting = false;
				getsockopt(c->socket, SOL_SOCKET, SO_ERROR, (void *)&result, &len);

				if(!result)
					finish_connecting(c);
				else {
					ifdebug(CONNECTIONS) logger(LOG_DEBUG,
							   "Error while connecting to %s (%s): %s",
							   c->name, c->hostname, sockstrerror(result));
					closesocket(c->socket);
					do_outgoing_connection(c);
					continue;
				}
			}

			if(!flush_meta(c)) {
				terminate_connection(c, c->status.active);
				continue;
			}
		}

		if(FD_ISSET(c->socket, readset)) {
			if(!receive_meta(c)) {
				terminate_connection(c, c->status.active);
				continue;
			}
		}
	}

	for(i = 0; i < listen_sockets; i++) {
		if(FD_ISSET(listen_socket[i].udp, readset))
			handle_incoming_vpn_data(i);

		if(FD_ISSET(listen_socket[i].tcp, readset))
			handle_new_meta_connection(listen_socket[i].tcp);
	}
}
Exemple #10
0
bool ack_h(connection_t *c, const char *request) {
	if(c->protocol_minor == 1)
		return upgrade_h(c, request);

	char hisport[MAX_STRING_SIZE];
	char *hisaddress;
	int weight, mtu;
	uint32_t options;
	node_t *n;
	bool choice;

	if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
			   c->hostname);
		return false;
	}

	/* Check if we already have a node_t for him */

	n = lookup_node(c->name);

	if(!n) {
		n = new_node();
		n->name = xstrdup(c->name);
		node_add(n);
	} else {
		if(n->connection) {
			/* Oh dear, we already have a connection to this node. */
			logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", n->connection->name, n->connection->hostname);

			if(n->connection->outgoing) {
				if(c->outgoing)
					logger(DEBUG_ALWAYS, LOG_WARNING, "Two outgoing connections to the same node!");
				else
					c->outgoing = n->connection->outgoing;

				n->connection->outgoing = NULL;
			}

			terminate_connection(n->connection, false);
			/* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */
			graph();
		}
	}

	n->connection = c;
	c->node = n;
	if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
		c->options &= ~OPTION_PMTU_DISCOVERY;
		options &= ~OPTION_PMTU_DISCOVERY;
	}
	c->options |= options;

	if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
		n->mtu = mtu;

	if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu)
		n->mtu = mtu;

	if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
		if(choice)
			c->options |= OPTION_CLAMP_MSS;
		else
			c->options &= ~OPTION_CLAMP_MSS;
	}

	/* Activate this connection */

	c->allow_request = ALL;

	logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection with %s (%s) activated", c->name,
			   c->hostname);

	/* Send him everything we know */

	send_everything(c);

	/* Create an edge_t for this connection */

	c->edge = new_edge();
	c->edge->from = myself;
	c->edge->to = n;
	sockaddr2str(&c->address, &hisaddress, NULL);
	c->edge->address = str2sockaddr(hisaddress, hisport);
	free(hisaddress);
	sockaddr_t local_sa;
	socklen_t local_salen = sizeof local_sa;
	if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0)
		logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name);
	else {
		char *local_address;
		sockaddr2str(&local_sa, &local_address, NULL);
		c->edge->local_address = str2sockaddr(local_address, myport);
		free(local_address);
	}
	c->edge->weight = (weight + c->estimated_weight) / 2;
	c->edge->connection = c;
	c->edge->options = c->options;

	edge_add(c->edge);

	/* Notify everyone of the new edge */

	if(tunnelserver)
		send_add_edge(c, c->edge);
	else
		send_add_edge(everyone, c->edge);

	/* Run MST and SSSP algorithms */

	graph();

	return true;
}
Exemple #11
0
bool termreq_h(connection_t *c) {
	terminate_connection(c, c->status.active);

	return true;
}
Exemple #12
0
void	StopNetwork(SWORD slot)			//-1 for all player quit
{
	SBYTE	name[20];
	SWORD	c1;
	UBYTE	network_active[NETWORK_MAXIMUM_SLOTS];
	SLONG	t_slot;

	if (Network.Active && Network.SessionActive)
	{
		if (Network.HostSlot == slot)
		{
			if (Network.Slot == slot)
			{
				for (t_slot = 0; t_slot < Network.MaxNumberOfSlots; t_slot++)
				{
					if (Network.Status[t_slot] == S_SESSION_ESTABLISHED)
					{
						network_active[t_slot] = 1;
					}
					else
					{
						network_active[t_slot] = 0;
					}
				}
				for (t_slot = 0; t_slot < Network.MaxNumberOfSlots; t_slot++)
				{
					if (network_active[t_slot] == 1)
					{
						SendNetwork(t_slot, network_active, sizeof(network_active) );
					}
				}
				terminate_connection(slot);
			}
			else
			{
				ReceiveNetwork(Network.HostSlot, network_active, sizeof(network_active) );
				terminate_connection(slot);

				for (t_slot = 0; t_slot < Network.MaxNumberOfSlots; t_slot++)
				{
					if (network_active[t_slot] == 1)
					{
						Network.HostSlot = t_slot;
						network_active[t_slot] = 0;
						break;
					}
				}

				if (Network.HostSlot == Network.Slot)
				{
					for (t_slot = 0; t_slot < Network.MaxNumberOfSlots; t_slot++)
					{
						if (t_slot != Network.Slot)
						{
							__NETListen__(t_slot);
							if (network_active[t_slot] == 1)
							{
								for(; Network.UserNcb[t_slot]->CmdCPlt == 0xff; );
							}
						}
					}
				}
				else
				{
					__NETCall__(Network.HostSlot);
					for(; Network.UserNcb[Network.HostSlot]->CmdCPlt == 0xff; );

					if (Network.UserNcb[Network.HostSlot]->CmdCPlt != 0)
					{
						printf("ERROR.>>>>> UNABLE TO CONNECT WITH THE NEW HOST!!!!!!\n");
					}

				}
			}
		}
		else
		{
			terminate_connection(slot);
		}
	}
}