File indexing completed on 2024-05-19 04:06:39
0001 /* 0002 * Copyright (C) 2005,2006 Justin Karneges 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a 0005 * copy of this software and associated documentation files (the 0006 * "Software"), to deal in the Software without restriction, including 0007 * without limitation the rights to use, copy, modify, merge, publish, 0008 * distribute, sublicense, and/or sell copies of the Software, and to 0009 * permit persons to whom the Software is furnished to do so, subject to 0010 * the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included 0013 * in all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 0016 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 0017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 0018 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 0019 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 0020 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 0021 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0022 */ 0023 0024 #include "qjdns_sock.h" 0025 0026 #include <QtGlobal> 0027 #include <stdio.h> 0028 #include <stdlib.h> 0029 #include <string.h> 0030 0031 #ifdef Q_OS_WIN 0032 # include <winsock2.h> 0033 # include <ws2tcpip.h> 0034 #endif 0035 0036 #ifdef Q_OS_UNIX 0037 # include <sys/time.h> 0038 # include <sys/types.h> 0039 # include <sys/socket.h> 0040 # include <netinet/in.h> 0041 # include <fcntl.h> 0042 # include <errno.h> 0043 # include <signal.h> 0044 # include <arpa/inet.h> 0045 #endif 0046 0047 #ifndef QT_NO_IPV6 0048 # define HAVE_IPV6 0049 # ifndef s6_addr 0050 # define IPPROTO_IPV6 41 0051 struct in6_addr 0052 { 0053 union 0054 { 0055 unsigned char _S6_u8[16]; 0056 unsigned short _S6_u16[8]; 0057 unsigned long _S6_u32[4]; 0058 } _S6_un; 0059 }; 0060 # define s6_addr _S6_un._S6_u8 0061 # endif 0062 # ifndef IPV6_JOIN_GROUP 0063 # define IPV6_JOIN_GROUP 12 0064 # define IPV6_MULTICAST_HOPS 10 0065 struct ipv6_mreq 0066 { 0067 struct in6_addr ipv6mr_multiaddr; 0068 unsigned int ipv6mr_interface; 0069 }; 0070 # endif 0071 #endif 0072 0073 static int get_last_error() 0074 { 0075 int x; 0076 #ifdef Q_OS_WIN 0077 x = WSAGetLastError(); 0078 #else 0079 x = errno; 0080 #endif 0081 return x; 0082 } 0083 0084 bool qjdns_sock_setMulticast4(int s, unsigned long int addr, int *errorCode) 0085 { 0086 int ret; 0087 struct ip_mreq mc; 0088 0089 memset(&mc, 0, sizeof(mc)); 0090 mc.imr_multiaddr.s_addr = htonl(addr); 0091 mc.imr_interface.s_addr = INADDR_ANY; 0092 0093 ret = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&mc, sizeof(mc)); 0094 if(ret != 0) 0095 { 0096 if(errorCode) 0097 *errorCode = get_last_error(); 0098 return false; 0099 } 0100 return true; 0101 } 0102 0103 bool qjdns_sock_setMulticast6(int s, unsigned char *addr, int *errorCode) 0104 { 0105 #ifdef HAVE_IPV6 0106 int ret; 0107 struct ipv6_mreq mc; 0108 0109 memset(&mc, 0, sizeof(mc)); 0110 memcpy(mc.ipv6mr_multiaddr.s6_addr, addr, 16); 0111 mc.ipv6mr_interface = 0; 0112 0113 ret = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&mc, sizeof(mc)); 0114 if(ret != 0) 0115 { 0116 if(errorCode) 0117 *errorCode = get_last_error(); 0118 return false; 0119 } 0120 return true; 0121 #else 0122 Q_UNUSED(s); 0123 Q_UNUSED(addr); 0124 Q_UNUSED(errorCode); 0125 return false; 0126 #endif 0127 } 0128 0129 bool qjdns_sock_setTTL4(int s, int ttl) 0130 { 0131 unsigned char cttl; 0132 int ret, ittl; 0133 0134 cttl = ttl; 0135 ittl = ttl; 0136 0137 // IP_MULTICAST_TTL might take 1 byte or 4, try both 0138 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&cttl, sizeof(cttl)); 0139 if(ret != 0) 0140 { 0141 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ittl, sizeof(ittl)); 0142 if(ret != 0) 0143 return false; 0144 } 0145 return true; 0146 } 0147 0148 bool qjdns_sock_setTTL6(int s, int ttl) 0149 { 0150 #ifdef HAVE_IPV6 0151 unsigned char cttl; 0152 int ret, ittl; 0153 0154 cttl = ttl; 0155 ittl = ttl; 0156 0157 // IPV6_MULTICAST_HOPS might take 1 byte or 4, try both 0158 ret = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&cttl, sizeof(cttl)); 0159 if(ret != 0) 0160 { 0161 ret = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&ittl, sizeof(ittl)); 0162 if(ret != 0) 0163 return false; 0164 } 0165 return true; 0166 #else 0167 Q_UNUSED(s); 0168 Q_UNUSED(ttl); 0169 return false; 0170 #endif 0171 } 0172 0173 bool qjdns_sock_setIPv6Only(int s) 0174 { 0175 #if defined(HAVE_IPV6) && defined(IPV6_V6ONLY) 0176 int x = 1; 0177 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&x, sizeof(x)) != 0) 0178 return false; 0179 return true; 0180 #else 0181 Q_UNUSED(s); 0182 return false; 0183 #endif 0184 }