- config_t const *cfg;
- subnet_t *net;
-cp
- myself = new_conn_list();
-
- asprintf(&myself->hostname, "MYSELF"); /* FIXME? Do hostlookup on ourselves? */
- myself->flags = 0;
- myself->protocol_version = PROT_CURRENT;
-
- if(!(cfg = get_config_val(config, tincname))) /* Not acceptable */
- {
- syslog(LOG_ERR, _("Name for tinc daemon required!"));
- return -1;
- }
- else
- asprintf(&myself->name, "%s", (char*)cfg->data.val);
-
- if(check_id(myself->name))
- {
- syslog(LOG_ERR, _("Invalid name for myself!"));
- return -1;
- }
-cp
- if(!(cfg = get_config_val(config, privatekey)))
- {
- syslog(LOG_ERR, _("Private key for tinc daemon required!"));
- return -1;
- }
- else
- {
- myself->rsa_key = RSA_new();
- BN_hex2bn(&myself->rsa_key->d, cfg->data.ptr);
- BN_hex2bn(&myself->rsa_key->e, "FFFF");
- }
-
- if(read_host_config(myself))
- {
- syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
- return -1;
- }
-cp
- if(!(cfg = get_config_val(myself->config, publickey)))
- {
- syslog(LOG_ERR, _("Public key for tinc daemon required!"));
- return -1;
- }
- else
- {
- BN_hex2bn(&myself->rsa_key->n, cfg->data.ptr);
- }
-/*
- if(RSA_check_key(myself->rsa_key) != 1)
- {
- syslog(LOG_ERR, _("Invalid public/private keypair!"));
- return -1;
- }
-*/
- if(!(cfg = get_config_val(myself->config, port)))
- myself->port = 655;
- else
- myself->port = cfg->data.val;
-
- if((cfg = get_config_val(myself->config, indirectdata)))
- if(cfg->data.val == stupid_true)
- myself->flags |= EXPORTINDIRECTDATA;
-
- if((cfg = get_config_val(myself->config, tcponly)))
- if(cfg->data.val == stupid_true)
- myself->flags |= TCPONLY;
-
-/* Read in all the subnets specified in the host configuration file */
-
- for(cfg = myself->config; (cfg = get_config_val(cfg, subnet)); cfg = cfg->next)
- {
- net = new_subnet();
- net->type = SUBNET_IPV4;
- net->net.ipv4.address = cfg->data.ip->address;
- net->net.ipv4.mask = cfg->data.ip->mask;
-
- /* Teach newbies what subnets are... */
-
- if((net->net.ipv4.address & net->net.ipv4.mask) != net->net.ipv4.address)
- {
- syslog(LOG_ERR, _("Network address and subnet mask do not match!"));
- return -1;
- }
-
- subnet_add(myself, net);
- }
-
- if((myself->meta_socket = setup_listen_meta_socket(myself->port)) < 0)
- {
- syslog(LOG_ERR, _("Unable to set up a listening socket!"));
- return -1;
- }
-
- if((myself->socket = setup_vpn_in_socket(myself->port)) < 0)
- {
- syslog(LOG_ERR, _("Unable to set up an incoming vpn data socket!"));
- close(myself->meta_socket);
- return -1;
- }
-
- /* Generate packet encryption key */
-
- myself->cipher_pkttype = EVP_bf_cfb();
-
- myself->cipher_pktkeylength = myself->cipher_pkttype->key_len + myself->cipher_pkttype->iv_len;
-
- myself->cipher_pktkey = (char *)xmalloc(myself->cipher_pktkeylength);
- RAND_bytes(myself->cipher_pktkey, myself->cipher_pktkeylength);
-
- if(!(cfg = get_config_val(config, keyexpire)))
- keylifetime = 3600;
- else
- keylifetime = cfg->data.val;
-
- keyexpires = time(NULL) + keylifetime;
-
- /* Activate ourselves */
-
- myself->status.active = 1;
-
- syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
-cp
- return 0;
+ avl_node_t *node, *next;
+ connection_t *c;
+
+ cp();
+
+ 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, 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, c->status.value);
+ 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, now - c->last_flushed_time, c->outbuflen);
+ c->status.timeout = true;
+ terminate_connection(c, true);
+ }
+ }
+ }