| 823 | } |
| 824 | |
| 825 | static int priv_net_create_socket(int domain, int type, const NETADDR *bindaddr) |
| 826 | { |
| 827 | int sock = socket(domain, type, 0); |
| 828 | if(sock < 0) |
| 829 | { |
| 830 | log_error("net", "Failed to create socket with domain %d and type %d (%s)", domain, type, net_error_message().c_str()); |
| 831 | return -1; |
| 832 | } |
| 833 | |
| 834 | #if defined(CONF_FAMILY_UNIX) |
| 835 | // On TCP sockets set SO_REUSEADDR to fix port rebind on restart |
| 836 | if(domain == AF_INET && type == SOCK_STREAM) |
| 837 | { |
| 838 | int reuse_addr = 1; |
| 839 | if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)) != 0) |
| 840 | { |
| 841 | log_error("net", "Setting SO_REUSEADDR failed with domain %d and type %d (%s)", domain, type, net_error_message().c_str()); |
| 842 | } |
| 843 | } |
| 844 | #elif defined(CONF_FAMILY_WINDOWS) |
| 845 | { |
| 846 | // Ensure exclusive use of address, otherwise it's possible on Windows to bind to the same address and port with another socket. |
| 847 | // See https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse (last update 06/14/2022) |
| 848 | int exclusive_addr_use = 1; |
| 849 | if(setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char *)&exclusive_addr_use, sizeof(exclusive_addr_use)) != 0) |
| 850 | { |
| 851 | log_error("net", "Setting SO_EXCLUSIVEADDRUSE failed with domain %d and type %d (%s)", domain, type, net_error_message().c_str()); |
| 852 | } |
| 853 | } |
| 854 | #endif |
| 855 | |
| 856 | // Set to IPv6-only if that's what we are creating, to ensure that dual-stack does not block the same IPv4 port. |
| 857 | #if defined(IPV6_V6ONLY) |
| 858 | if(domain == AF_INET6) |
| 859 | { |
| 860 | int ipv6only = 1; |
| 861 | if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6only, sizeof(ipv6only)) != 0) |
| 862 | { |
| 863 | log_error("net", "Setting IPV6_V6ONLY failed with domain %d and type %d (%s)", domain, type, net_error_message().c_str()); |
| 864 | } |
| 865 | } |
| 866 | #endif |
| 867 | |
| 868 | sockaddr_storage addr; |
| 869 | socklen_t addr_len; |
| 870 | if(bindaddr->type == NETTYPE_IPV4) |
| 871 | { |
| 872 | netaddr_to_sockaddr_in(bindaddr, (sockaddr_in *)&addr); |
| 873 | addr_len = sizeof(sockaddr_in); |
| 874 | } |
| 875 | else if(bindaddr->type == NETTYPE_IPV6) |
| 876 | { |
| 877 | netaddr_to_sockaddr_in6(bindaddr, (sockaddr_in6 *)&addr); |
| 878 | addr_len = sizeof(sockaddr_in6); |
| 879 | } |
| 880 | else |
| 881 | { |
| 882 | dbg_assert_failed("socket type invalid: %d", type); |
no test coverage detected