-int setup_vpn_in_socket(meshlink_handle_t *mesh, const sockaddr_t *sa) {
- int nfd;
- char *addrstr;
- int option;
-
- nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
-
- if(nfd < 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
- 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(DEBUG_ALWAYS, LOG_ERR, "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(DEBUG_ALWAYS, LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
- return -1;
- }
- }
-#endif
-
- option = 1;
- setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof option);
- setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof option);
-
-#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
- if(sa->sa.sa_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(SOL_IP) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = IP_PMTUDISC_DO;
- setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
- }
-#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = 1;
- setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
- }
-#else
-#warning No way to disable IPv4 fragmentation
-#endif
-
-#if defined(SOL_IPV6) && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = IPV6_PMTUDISC_DO;
- setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
- }
-#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = 1;
- setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
- }
-#else
-#warning No way to disable IPv6 fragmentation
-#endif
-
- if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
- closesocket(nfd);
- addrstr = sockaddr2hostname(sa);
- logger(DEBUG_ALWAYS, LOG_ERR, "Can't bind to %s/udp: %s", addrstr, sockstrerror(sockerrno));
- free(addrstr);
- return -1;
- }
-
- return nfd;
-} /* int setup_vpn_in_socket */
-