+int setup_vpn_in_socket(const sockaddr_t *sa) {
+ int nfd;
+ char *addrstr;
+ int option;
+
+ nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
+
+ if(nfd < 0) {
+ logger(LOG_ERR, "Creating UDP socket failed: %s", sockstrerror(sockerrno));
+ return -1;
+ }
+
+#ifdef O_NONBLOCK
+ {
+ int flags = fcntl(nfd, F_GETFL);
+
+ if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ closesocket(nfd);
+ logger(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(LOG_ERR, "Call to `%s' failed: %s", "ioctlsocket", sockstrerror(sockerrno));
+ return -1;
+ }
+ }
+#endif
+
+ option = 1;
+ setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof option);
+
+#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
+ if(sa->sa.sa_family == AF_INET6)
+ setsockopt(nfd, IPPROTO_IPV6, IPV6_V6ONLY, &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(myself->options & OPTION_PMTU_DISCOVERY) {
+ option = IP_PMTUDISC_DO;
+ setsockopt(nfd, SOL_IP, IP_MTU_DISCOVER, &option, sizeof(option));
+ }
+#elif defined(IPPROTO_IP) && defined(IP_DONTFRAGMENT)
+ if(myself->options & OPTION_PMTU_DISCOVERY) {
+ option = 1;
+ setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, &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(myself->options & OPTION_PMTU_DISCOVERY) {
+ option = IPV6_PMTUDISC_DO;
+ setsockopt(nfd, SOL_IPV6, IPV6_MTU_DISCOVER, &option, sizeof(option));
+ }
+#elif defined(IPPROTO_IPV6) && defined(IPV6_DONTFRAG)
+ if(myself->options & OPTION_PMTU_DISCOVERY) {
+ option = 1;
+ setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, &option, sizeof(option));
+ }
+#else
+#warning No way to disable IPv6 fragmentation
+#endif