Added IPv6 support to SocketAddr and Socket classes.
git-svn-id: http://voip.null.ro/svn/yate@5656 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
c1dcd17eea
commit
bb49512cd1
|
@ -279,6 +279,8 @@ NETDB_FLAGS=""
|
|||
AC_CHECK_FUNC([inet_ntop],[NETDB_FLAGS="$NETDB_FLAGS -DHAVE_NTOP"])
|
||||
AC_CHECK_FUNC([inet_pton],[NETDB_FLAGS="$NETDB_FLAGS -DHAVE_PTON"])
|
||||
AC_CHECK_FUNC([gethostbyname_r],[NETDB_FLAGS="$NETDB_FLAGS -DHAVE_GHBN_R"])
|
||||
AC_CHECK_FUNC([gethostbyname2_r],[NETDB_FLAGS="$NETDB_FLAGS -DHAVE_GHBN2_R"])
|
||||
AC_CHECK_FUNC([gethostbyname2],[NETDB_FLAGS="$NETDB_FLAGS -DHAVE_GHBN2"])
|
||||
AC_SUBST(NETDB_FLAGS)
|
||||
|
||||
THREAD_KILL=""
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#ifndef _WINDOWS
|
||||
|
||||
#include <net/if.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
|
@ -106,6 +107,98 @@ static void epochToFt(unsigned int secEpoch, FILETIME& ft)
|
|||
#endif
|
||||
|
||||
|
||||
//
|
||||
// IPv6 module functions
|
||||
//
|
||||
#ifdef AF_INET6
|
||||
|
||||
#if defined(HAVE_GHBN2_R) || defined(HAVE_GHBN2)
|
||||
#define YATE_SOCKET_GHBN2_AVAILABLE
|
||||
|
||||
static inline bool ghbn2Set(struct sockaddr* addr, hostent* he, int family)
|
||||
{
|
||||
if (!(he && he->h_addrtype == family && he->h_addr_list))
|
||||
return false;
|
||||
char* val = he->h_addr_list[0];
|
||||
if (!val)
|
||||
return false;
|
||||
if (family == AF_INET6) {
|
||||
((struct sockaddr_in6*)addr)->sin6_addr = *(in6_addr*)val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolve an address using gethostbyname2_r or gethostbyname2
|
||||
// Return 1 on success, 0 on failure, -1 if not available
|
||||
static int resolveGHBN2(struct sockaddr* addr, const char* name)
|
||||
{
|
||||
if (!addr || TelEngine::null(name))
|
||||
return 0;
|
||||
int family = AF_INET6;
|
||||
#ifdef HAVE_GHBN2_R
|
||||
char buf[576];
|
||||
struct hostent h;
|
||||
struct hostent* hr = 0;
|
||||
int errn = 0;
|
||||
int r = gethostbyname2_r(name,family,&h,buf,sizeof(buf),&hr,&errn);
|
||||
if (r != ERANGE) {
|
||||
if (!r && ghbn2Set(addr,hr,family))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
// Buffer too short: fallback to gethostbyname2 if available
|
||||
#endif
|
||||
#ifdef HAVE_GHBN2
|
||||
Lock lck(s_mutex,MAX_RESWAIT);
|
||||
if (lck.locked()) {
|
||||
if (ghbn2Set(addr,gethostbyname2(name,family),family))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
Alarm("engine","socket",DebugWarn,"Resolver was busy, failing '%s'",name);
|
||||
#else
|
||||
#ifndef HAVE_GHBN2_R
|
||||
return -1;
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_GHBN2_R) || defined(HAVE_GHBN2)
|
||||
|
||||
// Resolve a domain to IPv6 address
|
||||
static inline bool resolveIPv6(struct sockaddr* addr, const char* name)
|
||||
{
|
||||
static bool s_noIPv6 = true;
|
||||
#ifdef YATE_SOCKET_GHBN2_AVAILABLE
|
||||
int res = resolveGHBN2(addr,name);
|
||||
if (res >= 0)
|
||||
return res > 0;
|
||||
#endif
|
||||
// TODO: implement AF_INET6 resolving
|
||||
if (s_noIPv6) {
|
||||
s_noIPv6 = false;
|
||||
Alarm("engine","socket",DebugWarn,"Resolver for %s is not available",
|
||||
SocketAddr::lookupFamily(SocketAddr::IPv6));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // AF_INET6
|
||||
|
||||
|
||||
const String s_ipv4NullAddr = "0.0.0.0";
|
||||
const String s_ipv6NullAddr = "::";
|
||||
|
||||
const TokenDict SocketAddr::s_familyName[] = {
|
||||
{"Unknown", Unknown},
|
||||
{"IPv4", IPv4},
|
||||
{"IPv6", IPv6},
|
||||
{"Unix", Unix},
|
||||
{0,0},
|
||||
};
|
||||
|
||||
SocketAddr::SocketAddr(const struct sockaddr* addr, socklen_t len)
|
||||
: m_address(0), m_length(0)
|
||||
{
|
||||
|
@ -127,6 +220,7 @@ void SocketAddr::clear()
|
|||
{
|
||||
m_length = 0;
|
||||
m_host.clear();
|
||||
m_addr.clear();
|
||||
void* tmp = m_address;
|
||||
m_address = 0;
|
||||
if (tmp)
|
||||
|
@ -221,6 +315,34 @@ bool SocketAddr::host(const String& name)
|
|||
return false;
|
||||
if (name == m_host)
|
||||
return true;
|
||||
if (!m_address) {
|
||||
int f = family(name);
|
||||
switch (f) {
|
||||
case Unix:
|
||||
#ifdef HAS_AF_UNIX
|
||||
if (assign(AF_UNIX) && host(name))
|
||||
return true;
|
||||
#endif
|
||||
break;
|
||||
case Unknown:
|
||||
// fall through to set IP host
|
||||
case IPv6:
|
||||
#ifdef AF_INET6
|
||||
if (assign(AF_INET6) && host(name))
|
||||
return true;
|
||||
#endif
|
||||
if (f == IPv6)
|
||||
break;
|
||||
// fall through to IPv4
|
||||
case IPv4:
|
||||
if (assign(AF_INET) && host(name))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
// Restore data
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
switch (family()) {
|
||||
case AF_INET:
|
||||
{
|
||||
|
@ -256,13 +378,29 @@ bool SocketAddr::host(const String& name)
|
|||
break;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
if (name.find('%') >= 0) {
|
||||
String tmp, iface;
|
||||
splitIface(name,tmp,&iface);
|
||||
if (!host(tmp))
|
||||
return false;
|
||||
if (iface)
|
||||
#ifndef _WINDOWS
|
||||
scopeId(if_nametoindex(iface));
|
||||
#else
|
||||
scopeId(iface.toInteger(0,0,0));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_PTON
|
||||
if (inet_pton(family(),name,&((struct sockaddr_in6*)m_address)->sin6_addr) > 0) {
|
||||
stringify();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
// TODO: implement AF_INET6 resolving
|
||||
if (resolveIPv6(m_address,name)) {
|
||||
stringify();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
#endif // AF_INET6
|
||||
#ifdef HAS_AF_UNIX
|
||||
|
@ -277,44 +415,185 @@ bool SocketAddr::host(const String& name)
|
|||
return false;
|
||||
}
|
||||
|
||||
void SocketAddr::stringify()
|
||||
// Retrieve the family of an address
|
||||
int SocketAddr::family(const String& addr)
|
||||
{
|
||||
m_host.clear();
|
||||
if (!(m_length && m_address))
|
||||
return;
|
||||
switch (family()) {
|
||||
if (!addr)
|
||||
return Unknown;
|
||||
bool ipv6 = false;
|
||||
for (unsigned int i = 0; i < addr.length(); i++) {
|
||||
if (addr[i] == '/')
|
||||
return Unix;
|
||||
if (addr[i] == ':')
|
||||
ipv6 = true;
|
||||
}
|
||||
if (ipv6)
|
||||
return IPv6;
|
||||
in_addr_t a = inet_addr(addr);
|
||||
if (a != INADDR_NONE || addr == YSTRING("255.255.255.255"))
|
||||
return IPv4;
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
// Convert the host address to a String
|
||||
bool SocketAddr::stringify(String& s, struct sockaddr* addr)
|
||||
{
|
||||
if (!addr)
|
||||
return false;
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
#ifdef HAVE_NTOP
|
||||
{
|
||||
char buf[16];
|
||||
buf[0] = '\0';
|
||||
m_host = inet_ntop(family(),&((struct sockaddr_in*)m_address)->sin_addr,
|
||||
s = inet_ntop(addr->sa_family,&((struct sockaddr_in*)addr)->sin_addr,
|
||||
buf,sizeof(buf));
|
||||
}
|
||||
#else
|
||||
s_mutex.lock();
|
||||
m_host = inet_ntoa(((struct sockaddr_in*)m_address)->sin_addr);
|
||||
s = inet_ntoa(((struct sockaddr_in*)addr)->sin_addr);
|
||||
s_mutex.unlock();
|
||||
#endif
|
||||
break;
|
||||
return true;
|
||||
#ifdef AF_INET6
|
||||
case AF_INET6:
|
||||
#ifdef HAVE_NTOP
|
||||
{
|
||||
char buf[48];
|
||||
buf[0] = '\0';
|
||||
m_host = inet_ntop(family(),&((struct sockaddr_in6*)m_address)->sin6_addr,
|
||||
s = inet_ntop(addr->sa_family,&((struct sockaddr_in6*)addr)->sin6_addr,
|
||||
buf,sizeof(buf));
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
break;
|
||||
#endif // AF_INET6
|
||||
#ifdef HAS_AF_UNIX
|
||||
case AF_UNIX:
|
||||
m_host = ((struct sockaddr_un*)m_address)->sun_path;
|
||||
break;
|
||||
s = ((struct sockaddr_un*)addr)->sun_path;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Append an address to a buffer
|
||||
String& SocketAddr::appendAddr(String& buf, const String& addr, int family)
|
||||
{
|
||||
if (!addr)
|
||||
return buf;
|
||||
// Address already starts with [
|
||||
if (addr[0] == '[') {
|
||||
buf << addr;
|
||||
return buf;
|
||||
}
|
||||
if (family == Unknown && addr.find(':') >= 0)
|
||||
family = IPv6;
|
||||
if (family != IPv6)
|
||||
buf << addr;
|
||||
else
|
||||
buf << "[" << addr << "]";
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Check if an address is empty or null
|
||||
bool SocketAddr::isNullAddr(const String& addr, int family)
|
||||
{
|
||||
if (!addr)
|
||||
return true;
|
||||
switch (family) {
|
||||
case IPv4:
|
||||
return addr == s_ipv4NullAddr;
|
||||
case IPv6:
|
||||
return addr == s_ipv6NullAddr;
|
||||
}
|
||||
return addr == s_ipv4NullAddr || addr == s_ipv6NullAddr;
|
||||
}
|
||||
|
||||
// Split an interface from address
|
||||
// An interface may be present in addr after a percent char (e.g. fe80::23%eth0)
|
||||
void SocketAddr::splitIface(const String& buf, String& addr, String* iface)
|
||||
{
|
||||
if (!buf) {
|
||||
addr.clear();
|
||||
if (iface)
|
||||
iface->clear();
|
||||
return;
|
||||
}
|
||||
int pos = buf.find('%');
|
||||
if (pos < 0) {
|
||||
if (iface)
|
||||
iface->clear();
|
||||
addr = buf;
|
||||
}
|
||||
else {
|
||||
if (iface)
|
||||
*iface = buf.substr(pos + 1);
|
||||
addr = buf.substr(0,pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Split an address into ip/port
|
||||
// Handle addr, addr:port, [addr], [addr]:port
|
||||
void SocketAddr::split(const String& buf, String& addr, int& port, bool portPresent)
|
||||
{
|
||||
if (!buf) {
|
||||
addr.clear();
|
||||
return;
|
||||
}
|
||||
if (buf[0] == '[') {
|
||||
int p = buf.find(']',1);
|
||||
if (p >= 1) {
|
||||
if (p < ((int)buf.length() - 1) && buf[p + 1] == ':')
|
||||
port = buf.substr(p + 2).toInteger();
|
||||
addr.assign(buf.c_str() + 1,p - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
int p = buf.find(':');
|
||||
if (p >= 0) {
|
||||
// Check for a second ':': it may be an IPv6 address
|
||||
// or we expect a port at the end of an IPv6 address
|
||||
int p2 = buf.rfind(':');
|
||||
if (p == p2 || portPresent) {
|
||||
port = buf.substr(p2 + 1).toInteger();
|
||||
addr.assign(buf.c_str(),p2);
|
||||
}
|
||||
else
|
||||
addr = buf;
|
||||
}
|
||||
else
|
||||
addr = buf;
|
||||
}
|
||||
|
||||
const String& SocketAddr::ipv4NullAddr()
|
||||
{
|
||||
return s_ipv4NullAddr;
|
||||
}
|
||||
|
||||
const String& SocketAddr::ipv6NullAddr()
|
||||
{
|
||||
return s_ipv6NullAddr;
|
||||
}
|
||||
|
||||
const TokenDict* SocketAddr::dictFamilyName()
|
||||
{
|
||||
return s_familyName;
|
||||
}
|
||||
|
||||
void SocketAddr::stringify()
|
||||
{
|
||||
m_host.clear();
|
||||
m_addr.clear();
|
||||
if (m_length && m_address)
|
||||
stringify(m_host,m_address);
|
||||
}
|
||||
|
||||
// Store host:port in m_addr
|
||||
void SocketAddr::updateAddr() const
|
||||
{
|
||||
m_addr.clear();
|
||||
appendTo(m_addr,host(),port(),family());
|
||||
}
|
||||
|
||||
int SocketAddr::port() const
|
||||
|
@ -348,6 +627,7 @@ bool SocketAddr::port(int newport)
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
m_addr.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
226
yateclass.h
226
yateclass.h
|
@ -5451,6 +5451,26 @@ class Socket;
|
|||
class YATE_API SocketAddr : public GenObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Known address families
|
||||
*/
|
||||
enum Family {
|
||||
Unknown = AF_UNSPEC,
|
||||
IPv4 = AF_INET,
|
||||
AfMax = AF_MAX,
|
||||
AfUnsupported = AfMax,
|
||||
#ifdef AF_INET6
|
||||
IPv6 = AF_INET6,
|
||||
#else
|
||||
IPv6 = AfUnsupported + 1,
|
||||
#endif
|
||||
#ifdef HAS_AF_UNIX
|
||||
Unix = AF_UNIX,
|
||||
#else
|
||||
Unix = AfUnsupported + 2,
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Default constructor of an empty address
|
||||
*/
|
||||
|
@ -5554,6 +5574,28 @@ public:
|
|||
inline int family() const
|
||||
{ return m_address ? m_address->sa_family : 0; }
|
||||
|
||||
/**
|
||||
* Retrieve address family name
|
||||
* @return Address family name
|
||||
*/
|
||||
inline const char* familyName()
|
||||
{ return lookupFamily(family()); }
|
||||
|
||||
/**
|
||||
* Retrieve the sin6_scope_id value of an IPv6 address
|
||||
* @return The requested value (it may be 0), 0 if not available
|
||||
*/
|
||||
inline unsigned int scopeId() const
|
||||
{ return scopeId(address()); }
|
||||
|
||||
/**
|
||||
* Set the sin6_scope_id value of an IPv6 address
|
||||
* @param val Value to set
|
||||
* @return True on success, false if not available
|
||||
*/
|
||||
inline bool scopeId(unsigned int val)
|
||||
{ return scopeId(address(),val); }
|
||||
|
||||
/**
|
||||
* Get the host of this address
|
||||
* @return Host name as String
|
||||
|
@ -5562,7 +5604,19 @@ public:
|
|||
{ return m_host; }
|
||||
|
||||
/**
|
||||
* Set the hostname of this address
|
||||
* Get the host and port of this address
|
||||
* @return Address String (host:port)
|
||||
*/
|
||||
inline const String& addr() const {
|
||||
if (!m_addr)
|
||||
updateAddr();
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hostname of this address.
|
||||
* Guess address family if not initialized
|
||||
* @param name Host to set
|
||||
* @return True if new host set, false if name could not be parsed
|
||||
*/
|
||||
virtual bool host(const String& name);
|
||||
|
@ -5594,6 +5648,13 @@ public:
|
|||
inline socklen_t length() const
|
||||
{ return m_length; }
|
||||
|
||||
/**
|
||||
* Check if this address is empty or null
|
||||
* @return True if the address is empty or '0.0.0.0' (IPv4) or '::' IPv6
|
||||
*/
|
||||
inline bool isNullAddr() const
|
||||
{ return isNullAddr(m_host,family()); }
|
||||
|
||||
/**
|
||||
* Check if an address family is supported by the library
|
||||
* @param family Family of the address to check
|
||||
|
@ -5601,15 +5662,161 @@ public:
|
|||
*/
|
||||
static bool supports(int family);
|
||||
|
||||
/**
|
||||
* Retrieve the family of an address
|
||||
* @param addr The address to check
|
||||
* @return Address family
|
||||
*/
|
||||
static int family(const String& addr);
|
||||
|
||||
/**
|
||||
* Convert the host address to a String
|
||||
* @param buf Destination buffer
|
||||
* @param addr Socket address
|
||||
* @return True on success, false if address family is not supported
|
||||
*/
|
||||
static bool stringify(String& buf, struct sockaddr* addr);
|
||||
|
||||
/**
|
||||
* Retrieve the scope id value of an IPv6 address
|
||||
* @param addr The address
|
||||
* @return The requested value (it may be 0), 0 if not available
|
||||
*/
|
||||
static inline unsigned int scopeId(struct sockaddr* addr) {
|
||||
#ifdef AF_INET6
|
||||
if (addr && addr->sa_family == AF_INET6)
|
||||
return ((struct sockaddr_in6*)addr)->sin6_scope_id;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scope id value of an IPv6 address
|
||||
* @param addr Address to set
|
||||
* @param val Value to set
|
||||
* @return True on success, false if not available
|
||||
*/
|
||||
static inline bool scopeId(struct sockaddr* addr, unsigned int val) {
|
||||
#ifdef AF_INET6
|
||||
if (addr && addr->sa_family == AF_INET6) {
|
||||
((struct sockaddr_in6*)addr)->sin6_scope_id = val;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an address to a buffer
|
||||
* @param buf Destination buffer
|
||||
* @param addr Address to append
|
||||
* @param family Address family, set it to Unknown to detect
|
||||
* @return Buffer address
|
||||
*/
|
||||
static String& appendAddr(String& buf, const String& addr, int family = Unknown);
|
||||
|
||||
/**
|
||||
* Append an address to a buffer in the form addr:port
|
||||
* @param buf Destination buffer
|
||||
* @param addr Address to append
|
||||
* @param port Port to append
|
||||
* @param family Address family, set it to Unknown to detect
|
||||
* @return Buffer address
|
||||
*/
|
||||
static inline String& appendTo(String& buf, const String& addr, int port,
|
||||
int family = Unknown) {
|
||||
appendAddr(buf,addr,family) << ":" << port;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an address to a buffer in the form addr:port
|
||||
* @param addr Address to append
|
||||
* @param port Port to append
|
||||
* @param family Address family, set it to Unknown to detect
|
||||
* @return A String with concatenated address and port
|
||||
*/
|
||||
static inline String appendTo(const String& addr, int port, int family = Unknown) {
|
||||
String buf;
|
||||
appendTo(buf,addr,port,family);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an address is empty or null
|
||||
* @param addr Address to check
|
||||
* @param family Address family, set it to Unknown to detect
|
||||
* @return True if the address is empty or '0.0.0.0' (IPv4) or '::' IPv6
|
||||
*/
|
||||
static bool isNullAddr(const String& addr, int family = Unknown);
|
||||
|
||||
/**
|
||||
* Split an interface from address
|
||||
* An interface may be present in addr after a percent char (e.g. fe80::23%eth0)
|
||||
* It is safe call this method with the same destination and source string
|
||||
* @param buf Source buffer
|
||||
* @param addr Destination buffer for address
|
||||
* @param iface Optional pointer to be filled with interface name
|
||||
*/
|
||||
static void splitIface(const String& buf, String& addr, String* iface = 0);
|
||||
|
||||
/**
|
||||
* Split an address into ip/port.
|
||||
* Handled formats: addr, addr:port, [addr], [addr]:port
|
||||
* It is safe call this method with the same destination and source string
|
||||
* @param buf Source buffer
|
||||
* @param addr Destination buffer for address
|
||||
* @param port Destination port
|
||||
* @param portPresent Set it to true if the port is always present after the last ':'.
|
||||
* This will handle IPv6 addresses without square brackets and port present
|
||||
* (e.g. fe80::23:5060 will split into addr=fe80::23 and port=5060)
|
||||
*/
|
||||
static void split(const String& buf, String& addr, int& port, bool portPresent = false);
|
||||
|
||||
/**
|
||||
* Retrieve address family name
|
||||
* @param family Address family to retrieve
|
||||
* @return Address family name
|
||||
*/
|
||||
static inline const char* lookupFamily(int family)
|
||||
{ return lookup(family,s_familyName); }
|
||||
|
||||
/**
|
||||
* Retrieve IPv4 null address
|
||||
* @return IPv4 null address (0.0.0.0)
|
||||
*/
|
||||
static const String& ipv4NullAddr();
|
||||
|
||||
/**
|
||||
* Retrieve IPv6 null address
|
||||
* @return IPv6 null address (::)
|
||||
*/
|
||||
static const String& ipv6NullAddr();
|
||||
|
||||
/**
|
||||
* Retrieve the family name dictionary
|
||||
* @return Pointer to family name dictionary
|
||||
*/
|
||||
static const TokenDict* dictFamilyName();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Convert the host address to a String stored in m_host
|
||||
*/
|
||||
virtual void stringify();
|
||||
|
||||
/**
|
||||
* Store host:port in m_addr
|
||||
*/
|
||||
virtual void updateAddr() const;
|
||||
|
||||
struct sockaddr* m_address;
|
||||
socklen_t m_length;
|
||||
String m_host;
|
||||
mutable String m_addr;
|
||||
|
||||
private:
|
||||
static const TokenDict s_familyName[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -6274,6 +6481,23 @@ public:
|
|||
*/
|
||||
virtual bool setOption(int level, int name, const void* value = 0, socklen_t length = 0);
|
||||
|
||||
/**
|
||||
* Set or reset socket IPv6 only option.
|
||||
* This option will tell to an IPv6 socket to accept only IPv6 packets.
|
||||
* IPv4 packets will be accepted if disabled.
|
||||
* This method will fail for non PF_INET6 sockets
|
||||
* @param on True to set, false to reset it
|
||||
* @return True if operation was successfull, false if an error occured
|
||||
*/
|
||||
inline bool setIpv6OnlyOption(bool on) {
|
||||
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||
int value = on ? 1 : 0;
|
||||
return setOption(IPPROTO_IPV6,IPV6_V6ONLY,&value,sizeof(value));
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get socket options
|
||||
* @param level Level of the option to set
|
||||
|
|
Loading…
Reference in New Issue