X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet_setup.c;h=a82d5d97817610ca611195927a264713e4129141;hb=4b6c01b1d5383b1a7417244a31ad4652aab2d5db;hp=b9cddeb00ccc2c7bd73dc69710ef7d148b63156c;hpb=db8e6e4221c974314fd8b05d79dbc94152f01108;p=meshlink diff --git a/src/net_setup.c b/src/net_setup.c index b9cddeb0..a82d5d97 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -301,6 +301,117 @@ static bool load_node(meshlink_handle_t *mesh, const char *name, void *priv) { return true; } +int setup_tcp_listen_socket(meshlink_handle_t *mesh, const struct addrinfo *aip) { + int nfd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP); + + if(nfd == -1) { + return -1; + } + +#ifdef FD_CLOEXEC + fcntl(nfd, F_SETFD, FD_CLOEXEC); +#endif + + int option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); + +#if defined(IPV6_V6ONLY) + + if(aip->ai_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + +#else +#warning IPV6_V6ONLY not defined +#endif + + if(bind(nfd, aip->ai_addr, aip->ai_addrlen)) { + closesocket(nfd); + return -1; + } + + if(listen(nfd, 3)) { + logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "listen", sockstrerror(sockerrno)); + closesocket(nfd); + return -1; + } + + return nfd; +} + +int setup_udp_listen_socket(meshlink_handle_t *mesh, const struct addrinfo *aip) { + int nfd = socket(aip->ai_family, SOCK_DGRAM, IPPROTO_UDP); + + if(nfd == -1) { + return -1; + } + +#ifdef FD_CLOEXEC + fcntl(nfd, F_SETFD, FD_CLOEXEC); +#endif + +#ifdef O_NONBLOCK + int flags = fcntl(nfd, F_GETFL); + + if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + closesocket(nfd); + logger(mesh, MESHLINK_ERROR, "System call `%s' failed: %s", "fcntl", strerror(errno)); + return -1; + } + +#elif defined(WIN32) + unsigned long arg = 1; + + if(ioctlsocket(nfd, FIONBIO, &arg) != 0) { + closesocket(nfd); + logger(mesh, MESHLINK_ERROR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno)); + return -1; + } + +#endif + + int option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option)); + setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option)); + +#if defined(IPV6_V6ONLY) + + if(aip->ai_family == AF_INET6) { + setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&option, sizeof(option)); + } + +#endif + +#if defined(IP_DONTFRAG) && !defined(IP_DONTFRAGMENT) +#define IP_DONTFRAGMENT IP_DONTFRAG +#endif + +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) + option = IP_PMTUDISC_DO; + setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option)); +#elif defined(IP_DONTFRAGMENT) + option = 1; + setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option)); +#endif + + if(aip->ai_family == AF_INET6) { +#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + option = IPV6_PMTUDISC_DO; + setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option)); +#elif defined(IPV6_DONTFRAG) + option = 1; + setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option)); +#endif + } + + if(bind(nfd, aip->ai_addr, aip->ai_addrlen)) { + closesocket(nfd); + return -1; + } + + return nfd; +} + /* Add listening sockets. */ @@ -311,7 +422,7 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, - .ai_flags = AI_PASSIVE, + .ai_flags = AI_PASSIVE | AI_NUMERICSERV, }; int err = getaddrinfo(NULL, mesh->myport, &hint, &ai); @@ -345,15 +456,9 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { /* Try to bind to TCP */ - int tcp_fd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP); + int tcp_fd = setup_tcp_listen_socket(mesh, aip); if(tcp_fd == -1) { - continue; - } - - if(bind(tcp_fd, aip->ai_addr, aip->ai_addrlen)) { - closesocket(tcp_fd); - if(errno == EADDRINUSE) { /* If this port is in use for any address family, avoid it. */ success = false; @@ -363,15 +468,9 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { } } - if(!setup_listen_socket(mesh, tcp_fd, aip->ai_family)) { - closesocket(tcp_fd); - success = false; - break; - } - /* If TCP worked, then we require that UDP works as well. */ - int udp_fd = socket(aip->ai_family, SOCK_DGRAM, IPPROTO_UDP); + int udp_fd = setup_udp_listen_socket(mesh, aip); if(udp_fd == -1) { closesocket(tcp_fd); @@ -379,17 +478,10 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { break; } - if(bind(udp_fd, aip->ai_addr, aip->ai_addrlen) || !setup_vpn_in_socket(mesh, udp_fd, aip->ai_family)) { - closesocket(tcp_fd); - closesocket(udp_fd); - success = false; - break; - } - io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].tcp, handle_new_meta_connection, &mesh->listen_socket[mesh->listen_sockets], tcp_fd, IO_READ); io_add(&mesh->loop, &mesh->listen_socket[mesh->listen_sockets].udp, handle_incoming_vpn_data, &mesh->listen_socket[mesh->listen_sockets], udp_fd, IO_READ); - if(mesh->log_level >= MESHLINK_INFO) { + if(mesh->log_level <= MESHLINK_INFO) { char *hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); logger(mesh, MESHLINK_INFO, "Listening on %s", hostname); free(hostname); @@ -429,13 +521,7 @@ static bool add_listen_sockets(meshlink_handle_t *mesh) { /* Configure node_t mesh->self and set up the local sockets (listen only) */ -bool setup_myself(meshlink_handle_t *mesh) { - /* Set some defaults */ - - mesh->maxtimeout = 900; - - /* Done */ - +static bool setup_myself(meshlink_handle_t *mesh) { mesh->self->nexthop = mesh->self; node_add(mesh, mesh->self); @@ -473,7 +559,6 @@ bool setup_myself(meshlink_handle_t *mesh) { /* Done. */ - mesh->last_config_check = mesh->loop.now.tv_sec; mesh->last_unreachable = mesh->loop.now.tv_sec; return true;