+ 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;
+ }
+
+ listen_sockets = 0;
+
+ for(aip = ai; aip; aip = aip->ai_next) {
+ listen_socket[listen_sockets].tcp =
+ setup_listen_socket((sockaddr_t *) aip->ai_addr);
+
+ if(listen_socket[listen_sockets].tcp < 0)
+ continue;
+
+ listen_socket[listen_sockets].udp =
+ setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
+
+ if(listen_socket[listen_sockets].udp < 0)
+ continue;
+
+ ifdebug(CONNECTIONS) {
+ hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
+ logger(LOG_NOTICE, _("Listening on %s"), hostname);
+ free(hostname);
+ }
+
+ listen_socket[listen_sockets].sa.sa = *aip->ai_addr;
+ listen_sockets++;
+ }
+
+ freeaddrinfo(ai);
+
+ if(listen_sockets)
+ logger(LOG_NOTICE, _("Ready"));
+ else {
+ logger(LOG_ERR, _("Unable to create any listening socket!"));
+ return false;
+ }
+
+ return true;