X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet_setup.c;h=daa296bd693d4318a22c4ebd4e29bf278fa15f41;hp=6157993cccd3deabdf7eee7aafbfb5b9e5ae3ea8;hb=38adc8bf548c2c465d5f4147866c3d3f9112d3a8;hpb=51bddfd4dd95161afae2cac4aa5d31970fef5714 diff --git a/src/net_setup.c b/src/net_setup.c index 6157993c..daa296bd 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -86,10 +86,8 @@ bool node_read_ecdsa_public_key(node_t *n) { fp = fopen(pubname, "r"); - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading ECDSA public key file `%s': %s", pubname, strerror(errno)); + if(!fp) goto exit; - } n->ecdsa = ecdsa_read_pem_public_key(fp); fclose(fp); @@ -643,12 +641,92 @@ bool setup_myself_reloadable(void) { return true; } +/* + Add listening sockets. +*/ +static bool add_listen_address(char *address, bool bindto) { + char *port = myport; + + if(address) { + char *space = strchr(address, ' '); + if(space) { + *space++ = 0; + port = space; + } + + if(!strcmp(address, "*")) + *address = 0; + } + + struct addrinfo *ai, hint = {0}; + hint.ai_family = addressfamily; + hint.ai_socktype = SOCK_STREAM; + hint.ai_protocol = IPPROTO_TCP; + hint.ai_flags = AI_PASSIVE; + + int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); + free(address); + + if(err || !ai) { + logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err)); + return false; + } + + for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { + // Ignore duplicate addresses + bool found = false; + + for(int i = 0; i < listen_sockets; i++) + if(!memcmp(&listen_socket[i].sa, aip->ai_addr, aip->ai_addrlen)) { + found = true; + break; + } + + if(found) + continue; + + if(listen_sockets >= MAXSOCKETS) { + logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); + return false; + } + + int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); + + if(tcp_fd < 0) + continue; + + int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); + + if(tcp_fd < 0) { + close(tcp_fd); + continue; + } + + io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ); + io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ); + + if(debug_level >= DEBUG_CONNECTIONS) { + char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); + logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname); + free(hostname); + } + + listen_socket[listen_sockets].bindto = bindto; + memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen); + listen_sockets++; + } + + freeaddrinfo(ai); + return true; +} + /* Configure node_t myself and set up the local sockets (listen only) */ static bool setup_myself(void) { char *name, *hostname, *cipher, *digest, *type; char *address = NULL; + bool port_specified = false; if(!(name = get_name())) { logger(DEBUG_ALWAYS, LOG_ERR, "Name for tinc daemon required!"); @@ -663,9 +741,8 @@ static bool setup_myself(void) { if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) myport = xstrdup("655"); - - xasprintf(&myself->hostname, "MYSELF port %s", myport); - myself->connection->hostname = xstrdup(myself->hostname); + else + port_specified = true; myself->connection->options = 0; myself->connection->protocol_major = PROT_MAJOR; @@ -673,14 +750,20 @@ static bool setup_myself(void) { myself->options |= PROT_MINOR << 24; - get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental); - - if(experimental && !read_ecdsa_private_key()) - return false; + if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) { + experimental = read_ecdsa_private_key(); + if(!experimental) + logger(DEBUG_ALWAYS, LOG_WARNING, "Support for SPTPS disabled."); + } else { + if(experimental && !read_ecdsa_private_key()) + return false; + } if(!read_rsa_private_key()) return false; + /* Ensure myport is numeric */ + if(!atoi(myport)) { struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); sockaddr_t sa; @@ -879,73 +962,25 @@ static bool setup_myself(void) { } } else { listen_sockets = 0; - config_t *cfg = lookup_config(config_tree, "BindToAddress"); + int cfgs = 0; - do { + for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) { + cfgs++; get_config_string(cfg, &address); - if(cfg) - cfg = lookup_config_next(config_tree, cfg); - - char *port = myport; - - if(address) { - char *space = strchr(address, ' '); - if(space) { - *space++ = 0; - port = space; - } - - if(!strcmp(address, "*")) - *address = 0; - } - - struct addrinfo *ai, hint = {0}; - hint.ai_family = addressfamily; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - hint.ai_flags = AI_PASSIVE; - - int err = getaddrinfo(address && *address ? address : NULL, port, &hint, &ai); - free(address); - - if(err || !ai) { - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", err == EAI_SYSTEM ? strerror(err) : gai_strerror(err)); + if(!add_listen_address(address, true)) return false; - } - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - if(listen_sockets >= MAXSOCKETS) { - logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); - return false; - } - - int tcp_fd = setup_listen_socket((sockaddr_t *) aip->ai_addr); - - if(tcp_fd < 0) - continue; - - int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); - - if(tcp_fd < 0) { - close(tcp_fd); - continue; - } - - io_add(&listen_socket[listen_sockets].tcp, handle_new_meta_connection, &listen_socket[listen_sockets], tcp_fd, IO_READ); - io_add(&listen_socket[listen_sockets].udp, handle_incoming_vpn_data, &listen_socket[listen_sockets], udp_fd, IO_READ); - - if(debug_level >= DEBUG_CONNECTIONS) { - hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); - logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Listening on %s", hostname); - free(hostname); - } + } - memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen); - listen_sockets++; - } + for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) { + cfgs++; + get_config_string(cfg, &address); + if(!add_listen_address(address, false)) + return false; + } - freeaddrinfo(ai); - } while(cfg); + if(!cfgs) + if(!add_listen_address(address, NULL)) + return false; } if(!listen_sockets) { @@ -953,6 +988,24 @@ static bool setup_myself(void) { return false; } + /* If no Port option was specified, set myport to the port used by the first listening socket. */ + + if(!port_specified) { + sockaddr_t sa; + socklen_t salen = sizeof sa; + if(!getsockname(listen_socket[0].udp.fd, &sa.sa, &salen)) { + free(myport); + sockaddr2str(&sa, NULL, &myport); + if(!myport) + myport = xstrdup("655"); + } + } + + xasprintf(&myself->hostname, "MYSELF port %s", myport); + myself->connection->hostname = xstrdup(myself->hostname); + + /* Done. */ + last_config_check = now.tv_sec; return true; @@ -1023,7 +1076,8 @@ void close_network_connections(void) { terminate_connection(c, false); } - list_delete_list(outgoing_list); + if(outgoing_list) + list_delete_list(outgoing_list); if(myself && myself->connection) { subnet_update(myself, NULL, false);