mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Improvement CORE-3226: IPv6 support (3/9) socket address abstraction class
This commit is contained in:
parent
5efd039202
commit
d3c1d72515
206
src/remote/SockAddr.h
Normal file
206
src/remote/SockAddr.h
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Michal Kubecek
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2014 Michal Kubecek <mike@mk-sys.cz>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef REMOTE_SOCKADDR_H
|
||||
#define REMOTE_SOCKADDR_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifndef WIN_NT
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "../remote/remote.h"
|
||||
|
||||
|
||||
class SockAddr {
|
||||
private:
|
||||
static const unsigned maxLen = sizeof(struct sockaddr_in6);
|
||||
char data[maxLen];
|
||||
socklen_t len;
|
||||
|
||||
public:
|
||||
void clear();
|
||||
const SockAddr& operator = (const SockAddr& x);
|
||||
|
||||
SockAddr() { clear(); }
|
||||
SockAddr(const SockAddr& x) { *this = x; }
|
||||
SockAddr(const unsigned char* p_data, unsigned p_len);
|
||||
~SockAddr() {}
|
||||
|
||||
struct sockaddr* ptr() { return (struct sockaddr*) data; }
|
||||
struct sockaddr_in* ptrIn() { return (struct sockaddr_in*) data; }
|
||||
struct sockaddr_in6* ptrIn6() { return (struct sockaddr_in6*) data; }
|
||||
|
||||
unsigned length() const { return len; }
|
||||
unsigned short family() const;
|
||||
unsigned short port() const;
|
||||
bool isLocalhost() const;
|
||||
void setPort(unsigned short x);
|
||||
int connect(SOCKET s) const;
|
||||
int accept(SOCKET s);
|
||||
int getsockname(SOCKET s);
|
||||
int getpeername(SOCKET s);
|
||||
void unmapV4();
|
||||
};
|
||||
|
||||
|
||||
inline void SockAddr::clear()
|
||||
{
|
||||
len = 0;
|
||||
memset(data, 0, maxLen);
|
||||
}
|
||||
|
||||
|
||||
inline const SockAddr& SockAddr::operator = (const SockAddr& x)
|
||||
{
|
||||
memcpy(data, x.data, maxLen);
|
||||
len = x.len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SockAddr::SockAddr(const unsigned char* p_data, unsigned p_len)
|
||||
{
|
||||
if (p_len > maxLen)
|
||||
p_len = maxLen;
|
||||
memcpy(data, p_data, p_len);
|
||||
len = p_len;
|
||||
}
|
||||
|
||||
|
||||
inline int SockAddr::connect(SOCKET s) const
|
||||
{
|
||||
return ::connect(s, (struct sockaddr*) data, len);
|
||||
}
|
||||
|
||||
|
||||
inline int SockAddr::accept(SOCKET s)
|
||||
{
|
||||
return ::accept(s, (struct sockaddr*) data, &len);
|
||||
}
|
||||
|
||||
|
||||
inline int SockAddr::getsockname(SOCKET s)
|
||||
{
|
||||
len = maxLen;
|
||||
int R = ::getsockname(s, (struct sockaddr*) data, &len);
|
||||
if (R < 0)
|
||||
clear();
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
inline int SockAddr::getpeername(SOCKET s)
|
||||
{
|
||||
len = maxLen;
|
||||
int R = ::getpeername(s, (struct sockaddr*) data, &len);
|
||||
if (R < 0)
|
||||
clear();
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned short SockAddr::family() const
|
||||
{
|
||||
const struct sockaddr* sa = (const struct sockaddr*) data;
|
||||
return sa->sa_family;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned short SockAddr::port() const
|
||||
{
|
||||
const struct sockaddr* sa = (const struct sockaddr*) data;
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
return ntohs(((const struct sockaddr_in*) data)->sin_port);
|
||||
case AF_INET6:
|
||||
return ntohs(((const struct sockaddr_in6*) data)->sin6_port);
|
||||
}
|
||||
return 0; // exception?
|
||||
}
|
||||
|
||||
|
||||
inline void SockAddr::setPort(unsigned short x)
|
||||
{
|
||||
const struct sockaddr* sa = (const struct sockaddr*) data;
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
((struct sockaddr_in*) data)->sin_port = htons(x);
|
||||
return;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6*) data)->sin6_port = htons(x);
|
||||
return;
|
||||
}
|
||||
// exception?
|
||||
}
|
||||
|
||||
|
||||
inline bool SockAddr::isLocalhost() const
|
||||
{
|
||||
const struct sockaddr* sa = (const struct sockaddr*) data;
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
const struct sockaddr_in* sa4 = (const struct sockaddr_in*) data;
|
||||
return ((ntohl(sa4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET);
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
const struct sockaddr_in6* sa6 = (const struct sockaddr_in6*) data;
|
||||
return (memcmp(&sa6->sin6_addr, &in6addr_loopback, sizeof(in6_addr)) == 0);
|
||||
}
|
||||
}
|
||||
return 0; // exception?
|
||||
}
|
||||
|
||||
|
||||
// if address is embedded IPv4, convert it to normal IPv4
|
||||
inline void SockAddr::unmapV4()
|
||||
{
|
||||
if (family() != AF_INET6)
|
||||
return;
|
||||
|
||||
const struct sockaddr_in6* sa6 = (const struct sockaddr_in6*) data;
|
||||
// IPv6 mapped IPv4 addresses are ::ffff:0:0/32
|
||||
static const unsigned char v4mapped_pfx[12]
|
||||
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
|
||||
if (memcmp(sa6->sin6_addr.s6_addr, v4mapped_pfx, sizeof(v4mapped_pfx)) != 0)
|
||||
return;
|
||||
|
||||
unsigned short port = ntohs(sa6->sin6_port);
|
||||
struct in_addr addr;
|
||||
memcpy(&addr, sa6->sin6_addr.s6_addr + sizeof(v4mapped_pfx), sizeof(addr));
|
||||
|
||||
struct sockaddr_in* sa4 = (struct sockaddr_in*) data;
|
||||
sa4->sin_family = AF_INET;
|
||||
sa4->sin_port = htons(port);
|
||||
sa4->sin_addr.s_addr = addr.s_addr;
|
||||
len = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
|
||||
#endif // REMOTE_SOCKADDR_H
|
Loading…
Reference in New Issue
Block a user