- if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
- macexpire= 600;
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout))
- {
- if(maxtimeout <= 0)
- {
- syslog(LOG_ERR, _("Bogus maximum timeout!"));
- return -1;
- }
- }
- else
- maxtimeout = 900;
-
- if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname))
- {
- if(!strcasecmp(afname, "IPv4"))
- addressfamily = AF_INET;
- else if (!strcasecmp(afname, "IPv6"))
- addressfamily = AF_INET6;
- else if (!strcasecmp(afname, "any"))
- addressfamily = AF_UNSPEC;
- else
- {
- syslog(LOG_ERR, _("Invalid address family!"));
- return -1;
- }
- free(afname);
- }
- else
- addressfamily = AF_INET;
-
- get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
-cp
- /* Generate packet encryption key */
-
- if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
- {
- if(!strcasecmp(cipher, "none"))
- {
- myself->cipher = NULL;
- }
- else
- {
- if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
- {
- syslog(LOG_ERR, _("Unrecognized cipher type!"));
- return -1;
- }
- }
- }
- else
- myself->cipher = EVP_bf_cbc();
-
- if(myself->cipher)
- myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
- else
- myself->keylength = 1;
-
- myself->connection->outcipher = EVP_bf_ofb();
-
- myself->key = (char *)xmalloc(myself->keylength);
- RAND_pseudo_bytes(myself->key, myself->keylength);
-
- if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
- keylifetime = 3600;
-
- keyexpires = now + keylifetime;
-
- /* Check if we want to use message authentication codes... */
-
- if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
- {
- if(!strcasecmp(digest, "none"))
- {
- myself->digest = NULL;
- }
- else
- {
- if(!(myself->digest = EVP_get_digestbyname(digest)))
- {
- syslog(LOG_ERR, _("Unrecognized digest type!"));
- return -1;
- }
- }
- }
- else
- myself->digest = EVP_sha1();
-
- myself->connection->outdigest = EVP_sha1();
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
- {
- if(myself->digest)
- {
- if(myself->maclength > myself->digest->md_size)
- {
- syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
- return -1;
- }
- else if (myself->maclength < 0)
- {
- syslog(LOG_ERR, _("Bogus MAC length!"));
- return -1;
- }
- }
- }
- else
- myself->maclength = 4;
-
- myself->connection->outmaclength = 0;
-
- /* Compression */
-
- if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
- {
- if(myself->compression < 0 || myself->compression > 9)
- {
- syslog(LOG_ERR, _("Bogus compression level!"));
- return -1;
- }
- }
- else
- myself->compression = 0;
-
- myself->connection->outcompression = 0;
-cp
- /* Done */
-
- myself->nexthop = myself;
- myself->via = myself;
- myself->status.active = 1;
- node_add(myself);
-
- graph();
-
-cp
- /* Open sockets */
-
- memset(&hint, 0, sizeof(hint));
-
- hint.ai_family = addressfamily;
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_protocol = IPPROTO_TCP;
- hint.ai_flags = AI_PASSIVE;
-
- if((err = getaddrinfo(NULL, myport, &hint, &ai)) || !ai)
- {
- syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(err));
- return -1;
- }
-
- for(aip = ai; aip; aip = aip->ai_next)
- {
- if((tcp_socket[listen_sockets] = setup_listen_socket((sockaddr_t *)aip->ai_addr)) < 0)
- continue;
-
- if((udp_socket[listen_sockets] = setup_vpn_in_socket((sockaddr_t *)aip->ai_addr)) < 0)
- continue;
-
- if(debug_lvl >= DEBUG_CONNECTIONS)
- {
- hostname = sockaddr2hostname((sockaddr_t *)aip->ai_addr);
- syslog(LOG_NOTICE, _("Listening on %s"), hostname);
- free(hostname);
+ if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
+ macexpire = 600;
+
+ if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
+ if(maxtimeout <= 0) {
+ logger(LOG_ERR, _("Bogus maximum timeout!"));
+ return false;
+ }
+ } else
+ maxtimeout = 900;
+
+ if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
+ if(!strcasecmp(afname, "IPv4"))
+ addressfamily = AF_INET;
+ else if(!strcasecmp(afname, "IPv6"))
+ addressfamily = AF_INET6;
+ else if(!strcasecmp(afname, "any"))
+ addressfamily = AF_UNSPEC;
+ else {
+ logger(LOG_ERR, _("Invalid address family!"));
+ return false;
+ }
+ free(afname);
+ }
+
+ get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
+
+ /* Generate packet encryption key */
+
+ if(get_config_string (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) {
+ if(!strcasecmp(cipher, "none")) {
+ myself->cipher = GCRY_CIPHER_NONE;
+ } else {
+ myself->cipher = gcry_cipher_map_name(cipher);
+
+ if(!myself->cipher) {
+ logger(LOG_ERR, _("Unrecognized cipher type!"));
+ return false;
+ }
+ }
+ } else
+ myself->cipher = GCRY_CIPHER_AES;
+
+ if(myself->cipher) {
+ result = gcry_cipher_open(&myself->cipher_ctx, myself->cipher, GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_SECURE);
+
+ if(result) {
+ logger(LOG_ERR, _("Error during initialisation of cipher for %s (%s): %s"),
+ myself->name, myself->hostname, gcry_strerror(result));
+ return false;
+ }
+
+ }
+
+ if(myself->cipher) {
+ myself->cipherkeylen = gcry_cipher_get_algo_keylen(myself->cipher);
+ myself->cipherblklen = gcry_cipher_get_algo_blklen(myself->cipher);
+ } else {
+ myself->cipherkeylen = 1;
+ }
+
+ logger(LOG_DEBUG, _("Key %s len %d"), gcry_cipher_algo_name(myself->cipher), myself->cipherkeylen);
+ myself->cipherkey = xmalloc(myself->cipherkeylen);
+ gcry_randomize(myself->cipherkey, myself->cipherkeylen, GCRY_STRONG_RANDOM);
+ if(myself->cipher)
+ gcry_cipher_setkey(myself->cipher_ctx, myself->cipherkey, myself->cipherkeylen);
+
+ if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
+ keylifetime = 3600;
+
+ keyexpires = now + keylifetime;
+
+ /* Check if we want to use message authentication codes... */
+
+ if(get_config_string (lookup_config(myself->connection->config_tree, "Digest"), &digest)) {
+ if(!strcasecmp(digest, "none")) {
+ myself->digest = GCRY_MD_NONE;
+ } else {
+ myself->digest = gcry_md_map_name(digest);
+
+ if(!myself->digest) {
+ logger(LOG_ERR, _("Unrecognized digest type!"));
+ return false;
+ }
+ }
+ } else
+ myself->digest = GCRY_MD_SHA1;
+
+
+ if(myself->digest) {
+ result = gcry_md_open(&myself->digest_ctx, myself->digest, GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC);
+
+ if(result) {
+ logger(LOG_ERR, _("Error during initialisation of digest for %s (%s): %s"),
+ myself->name, myself->hostname, gcry_strerror(result));
+ return false;
+ }
+
+ }
+
+ if(myself->digest) {
+ myself->digestlen = gcry_md_get_algo_dlen(myself->digest);
+ } else {
+ myself->digestlen = 1;
+ }
+
+ myself->digestkey = xmalloc(myself->digestlen);
+ gcry_randomize(myself->digestkey, myself->digestlen, GCRY_STRONG_RANDOM);
+ if(myself->digest)
+ gcry_md_setkey(myself->digest_ctx, myself->digestkey, myself->digestlen);
+
+ if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength)) {
+ if(myself->digest) {
+ if(myself->maclength > myself->digestlen) {
+ logger(LOG_ERR, _("MAC length exceeds size of digest!"));
+ return false;
+ } else if(myself->maclength < 0) {
+ logger(LOG_ERR, _("Bogus MAC length!"));
+ return false;
+ }
+ }
+ } else
+ myself->maclength = 4;
+
+ /* Compression */
+
+ if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"),
+ &myself->compression)) {
+ if(myself->compression < 0 || myself->compression > 11) {
+ logger(LOG_ERR, _("Bogus compression level!"));
+ return false;
+ }
+ } else
+ myself->compression = 0;
+
+ /* Done */
+
+ myself->nexthop = myself;
+ myself->via = myself;
+ myself->status.active = true;
+ myself->status.reachable = true;
+ node_add(myself);
+
+ graph();
+
+ /* Open device */
+
+ if(!setup_device())
+ return false;
+
+ /* Run tinc-up script to further initialize the tap interface */
+ asprintf(&envp[0], "NETNAME=%s", netname ? : "");
+ asprintf(&envp[1], "DEVICE=%s", device ? : "");
+ asprintf(&envp[2], "INTERFACE=%s", iface ? : "");
+ asprintf(&envp[3], "NAME=%s", myself->name);
+ envp[4] = NULL;
+
+ execute_script("tinc-up", envp);
+
+ for(i = 0; i < 5; i++)
+ free(envp[i]);
+
+ /* Open sockets */
+
+ get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
+
+ hint.ai_family = addressfamily;
+ hint.ai_socktype = SOCK_STREAM;
+ hint.ai_protocol = IPPROTO_TCP;
+ hint.ai_flags = AI_PASSIVE;
+
+ err = getaddrinfo(address, myport, &hint, &ai);
+
+ if(err || !ai) {
+ logger(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo",
+ gai_strerror(err));
+ return false;