+ 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(config_tree, "Cipher"), &cipher)) {
+ if(!strcasecmp(cipher, "none")) {
+ myself->incipher = NULL;
+ } else {
+ myself->incipher = EVP_get_cipherbyname(cipher);
+
+ if(!myself->incipher) {
+ logger(LOG_ERR, "Unrecognized cipher type!");
+ return false;
+ }
+ }
+ } else
+ myself->incipher = EVP_bf_cbc();
+
+ if(myself->incipher)
+ myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len;
+ else
+ myself->inkeylength = 1;
+
+ myself->connection->outcipher = EVP_bf_ofb();
+
+ 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(config_tree, "Digest"), &digest)) {
+ if(!strcasecmp(digest, "none")) {
+ myself->indigest = NULL;
+ } else {
+ myself->indigest = EVP_get_digestbyname(digest);
+
+ if(!myself->indigest) {
+ logger(LOG_ERR, "Unrecognized digest type!");
+ return false;
+ }
+ }
+ } else
+ myself->indigest = EVP_sha1();
+
+ myself->connection->outdigest = EVP_sha1();
+
+ if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
+ if(myself->indigest) {
+ if(myself->inmaclength > myself->indigest->md_size) {
+ logger(LOG_ERR, "MAC length exceeds size of digest!");
+ return false;
+ } else if(myself->inmaclength < 0) {
+ logger(LOG_ERR, "Bogus MAC length!");
+ return false;
+ }
+ }
+ } else
+ myself->inmaclength = 4;
+
+ myself->connection->outmaclength = 0;
+
+ /* Compression */
+
+ if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
+ if(myself->incompression < 0 || myself->incompression > 11) {
+ logger(LOG_ERR, "Bogus compression level!");
+ return false;
+ }
+ } else
+ myself->incompression = 0;
+
+ myself->connection->outcompression = 0;
+
+ /* Done */
+
+ myself->nexthop = myself;
+ myself->via = myself;
+ myself->status.reachable = true;
+ node_add(myself);
+
+ graph();
+
+ if(strictsubnets)
+ load_all_subnets();
+
+ /* Open device */
+
+ if(!setup_device())
+ return false;
+
+ /* Run tinc-up script to further initialize the tap interface */
+ 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;
+
+ execute_script("tinc-up", envp);
+
+ for(i = 0; i < 5; i++)
+ free(envp[i]);
+
+ /* Run subnet-up scripts for our own subnets */
+
+ subnet_update(myself, NULL, true);
+
+ /* 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);
+ }
+
+ memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
+ 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;