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 }