mirror of https://github.com/n7tae/new-xlxd.git
parent
e6f4096f2c
commit
30a47e1bd3
@ -1,91 +1,241 @@
|
|||||||
//
|
/*
|
||||||
// cip.cpp
|
* Copyright (C) 2020 by Thomas Early N7TAE
|
||||||
// xlxd
|
*
|
||||||
//
|
* This program is free software; you can redistribute it and/or modify
|
||||||
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
* it under the terms of the GNU General Public License as published by
|
||||||
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
//
|
* (at your option) any later version.
|
||||||
// ----------------------------------------------------------------------------
|
*
|
||||||
// This file is part of xlxd.
|
* This program is distributed in the hope that it will be useful,
|
||||||
//
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// xlxd is free software: you can redistribute it and/or modify
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// it under the terms of the GNU General Public License as published by
|
* GNU General Public License for more details.
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
*
|
||||||
// (at your option) any later version.
|
* You should have received a copy of the GNU General Public License
|
||||||
//
|
* along with this program; if not, write to the Free Software
|
||||||
// xlxd is distributed in the hope that it will be useful,
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
*/
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <string.h>
|
|
||||||
#include "cip.h"
|
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include "cip.h"
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// constructors
|
|
||||||
|
|
||||||
CIp::CIp()
|
CIp::CIp()
|
||||||
{
|
{
|
||||||
::memset(&m_Addr, 0, sizeof(m_Addr));
|
Clear();
|
||||||
m_Addr.sin_family = AF_INET;
|
}
|
||||||
|
|
||||||
|
CIp::CIp(const char *address, int family, int type, uint16_t port)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
struct addrinfo hints, *result;
|
||||||
|
bzero(&hints, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = family;
|
||||||
|
hints.ai_socktype = type;
|
||||||
|
if (0 == getaddrinfo(address, (port ? std::to_string(port).c_str() : NULL), &hints, &result)) {
|
||||||
|
memcpy(&addr, result->ai_addr, result->ai_addrlen);
|
||||||
|
addr.ss_family = result->ai_family;
|
||||||
|
freeaddrinfo(result);
|
||||||
|
}
|
||||||
|
SetPort(port);
|
||||||
|
}
|
||||||
|
CIp::CIp(const int family, const uint16_t port, const char *address)
|
||||||
|
{
|
||||||
|
Initialize(family, port, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIp::Initialize(const int family, const uint16_t port, const char *address)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
addr.ss_family = family;
|
||||||
|
if (AF_INET == family) {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
addr4->sin_port = htons(port);
|
||||||
|
if (address) {
|
||||||
|
if (0 == strncasecmp(address, "loc", 3))
|
||||||
|
inet_pton(AF_INET, "127.0.0.1", &(addr4->sin_addr));
|
||||||
|
else if (0 == strncasecmp(address, "any", 3))
|
||||||
|
inet_pton(AF_INET, "0.0.0.0", &(addr4->sin_addr));
|
||||||
|
else if (0 == strncasecmp(address, "none", 4))
|
||||||
|
addr.ss_family = AF_UNSPEC;
|
||||||
|
else {
|
||||||
|
if (1 > inet_pton(AF_INET, address, &(addr4->sin_addr)))
|
||||||
|
std::cerr << "Address Initialization Error: '" << address << "' is not a valdid IPV4 address!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (AF_INET6 == family) {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
addr6->sin6_port = htons(port);
|
||||||
|
if (address) {
|
||||||
|
if (0 == strncasecmp(address, "loc", 3))
|
||||||
|
inet_pton(AF_INET6, "::1", &(addr6->sin6_addr));
|
||||||
|
else if (0 == strncasecmp(address, "any", 3))
|
||||||
|
inet_pton(AF_INET6, "::", &(addr6->sin6_addr));
|
||||||
|
else if (0 == strncasecmp(address, "none", 4))
|
||||||
|
addr.ss_family = AF_UNSPEC;
|
||||||
|
else {
|
||||||
|
if (1 > inet_pton(AF_INET6, address, &(addr6->sin6_addr)))
|
||||||
|
std::cerr << "Address Initialization Error: '" << address << "' is not a valid IPV6 address!" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
std::cerr << "Error: Wrong address family type:" << family << " for [" << (address ? address : "NULL") << "]:" << port << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIp::operator==(const CIp &rhs) const // doesn't compare ports, only addresses and families
|
||||||
|
{
|
||||||
|
if (addr.ss_family != rhs.addr.ss_family)
|
||||||
|
return false;
|
||||||
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto l = (struct sockaddr_in *)&addr;
|
||||||
|
auto r = (struct sockaddr_in *)&rhs.addr;
|
||||||
|
return (l->sin_addr.s_addr == r->sin_addr.s_addr);
|
||||||
|
} else if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto l = (struct sockaddr_in6 *)&addr;
|
||||||
|
auto r = (struct sockaddr_in6 *)&rhs.addr;
|
||||||
|
return (0 == memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIp::operator!=(const CIp &rhs) const // doesn't compare ports, only addresses and families
|
||||||
|
{
|
||||||
|
if (addr.ss_family != rhs.addr.ss_family)
|
||||||
|
return true;
|
||||||
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto l = (struct sockaddr_in *)&addr;
|
||||||
|
auto r = (struct sockaddr_in *)&rhs.addr;
|
||||||
|
return (l->sin_addr.s_addr != r->sin_addr.s_addr);
|
||||||
|
} else if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto l = (struct sockaddr_in6 *)&addr;
|
||||||
|
auto r = (struct sockaddr_in6 *)&rhs.addr;
|
||||||
|
return (0 != memcmp(&(l->sin6_addr), &(r->sin6_addr), sizeof(struct in6_addr)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CIp::CIp(const char *sz)
|
bool CIp::AddressIsZero() const
|
||||||
{
|
{
|
||||||
::memset(&m_Addr, 0, sizeof(m_Addr));
|
if (AF_INET == addr.ss_family) {
|
||||||
m_Addr.sin_family = AF_INET;
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
// try xxx.xxx.xxx.xxxx first
|
return (addr4->sin_addr.s_addr == 0U);
|
||||||
m_Addr.sin_addr.s_addr = inet_addr(sz);
|
} else {
|
||||||
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
{
|
for (unsigned int i=0; i<16; i++) {
|
||||||
// otherwise try to resolve via dns
|
if (addr6->sin6_addr.s6_addr[i])
|
||||||
hostent *record = gethostbyname(sz);
|
return false;
|
||||||
if( record != NULL )
|
|
||||||
{
|
|
||||||
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIp::CIp(const struct sockaddr_in *sa)
|
void CIp::ClearAddress()
|
||||||
{
|
{
|
||||||
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
addr4->sin_addr.s_addr = 0U;
|
||||||
|
strcpy(straddr, "0.0.0.0");
|
||||||
|
} else {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
memset(&(addr6->sin6_addr.s6_addr), 0, 16);
|
||||||
|
strcpy(straddr, "::");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *CIp::GetAddress() const
|
||||||
|
{
|
||||||
|
if (straddr[0])
|
||||||
|
return straddr;
|
||||||
|
|
||||||
CIp::CIp(const CIp &ip)
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
inet_ntop(AF_INET, &(addr4->sin_addr), straddr, INET6_ADDRSTRLEN);
|
||||||
|
} else if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
inet_ntop(AF_INET6, &(addr6->sin6_addr), straddr, INET6_ADDRSTRLEN);
|
||||||
|
} else {
|
||||||
|
std::cerr << "CIp::GetAddress: unknown socket family=" << addr.ss_family << std::endl;
|
||||||
|
}
|
||||||
|
return straddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &stream, const CIp &Ip)
|
||||||
{
|
{
|
||||||
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
|
const char *sz = Ip;
|
||||||
|
if (AF_INET6 == Ip.GetFamily())
|
||||||
|
stream << "[" << sz << "]";
|
||||||
|
else
|
||||||
|
stream << sz;
|
||||||
|
const uint16_t port = Ip.GetPort();
|
||||||
|
if (port)
|
||||||
|
stream << ":" << port;
|
||||||
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
uint32_t CIp::GetAddr() const
|
||||||
// set
|
{
|
||||||
|
if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
// hash the results
|
||||||
|
auto *a = (const uint32_t *)&(addr6->sin6_addr.s6_addr);
|
||||||
|
return a[0] ^ a[1] ^ a[2] ^ a[3];
|
||||||
|
} else {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
return addr4->sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CIp::SetSockAddr(struct sockaddr_in *sa)
|
int CIp::GetFamily() const
|
||||||
{
|
{
|
||||||
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
return addr.ss_family;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
uint16_t CIp::GetPort() const
|
||||||
// operator
|
{
|
||||||
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
return ntohs(addr4->sin_port);
|
||||||
|
} else if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
return ntohs(addr6->sin6_port);
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIp::SetPort(const uint16_t newport)
|
||||||
|
{
|
||||||
|
if (AF_INET == addr.ss_family) {
|
||||||
|
auto addr4 = (struct sockaddr_in *)&addr;
|
||||||
|
addr4->sin_port = htons(newport);
|
||||||
|
} else if (AF_INET6 == addr.ss_family) {
|
||||||
|
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
addr6->sin6_port = htons(newport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CIp::operator ==(const CIp &ip) const
|
struct sockaddr *CIp::GetPointer()
|
||||||
{
|
{
|
||||||
return ( (ip.m_Addr.sin_family == m_Addr.sin_family) &&
|
memset(straddr, 0, INET6_ADDRSTRLEN); // things might change
|
||||||
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) &&
|
return (struct sockaddr *)&addr;
|
||||||
(ip.m_Addr.sin_port == m_Addr.sin_port)) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CIp::operator const char *() const
|
const struct sockaddr *CIp::GetCPointer() const
|
||||||
{
|
{
|
||||||
return ::inet_ntoa(m_Addr.sin_addr);
|
return (const struct sockaddr *)&addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t CIp::GetSize() const
|
||||||
|
{
|
||||||
|
if (AF_INET == addr.ss_family)
|
||||||
|
return sizeof(struct sockaddr_in);
|
||||||
|
else
|
||||||
|
return sizeof(struct sockaddr_in6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIp::Clear()
|
||||||
|
{
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_storage));
|
||||||
|
memset(straddr, 0, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,63 +1,73 @@
|
|||||||
//
|
#pragma once
|
||||||
// cip.h
|
|
||||||
// xlxd
|
/*
|
||||||
//
|
* Copyright (C) 2020 by Thomas Early N7TAE
|
||||||
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
*
|
||||||
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
* This program is free software; you can redistribute it and/or modify
|
||||||
//
|
* it under the terms of the GNU General Public License as published by
|
||||||
// ----------------------------------------------------------------------------
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
// This file is part of xlxd.
|
* (at your option) any later version.
|
||||||
//
|
*
|
||||||
// xlxd is free software: you can redistribute it and/or modify
|
* This program is distributed in the hope that it will be useful,
|
||||||
// it under the terms of the GNU General Public License as published by
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// (at your option) any later version.
|
* GNU General Public License for more details.
|
||||||
//
|
*
|
||||||
// xlxd is distributed in the hope that it will be useful,
|
* You should have received a copy of the GNU General Public License
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* along with this program; if not, write to the Free Software
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
// GNU General Public License for more details.
|
*/
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
#include <iostream>
|
||||||
// along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
#include <cstring>
|
||||||
// ----------------------------------------------------------------------------
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
#ifndef cip_h
|
|
||||||
#define cip_h
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
#include <netdb.h>
|
||||||
// class
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
class CIp
|
class CIp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
CIp();
|
CIp();
|
||||||
//CIp(uint8, uint8, uint8, uint8);
|
CIp(const char *address, int family = AF_UNSPEC, int type = SOCK_DGRAM, uint16_t port = 0U);
|
||||||
CIp(const struct sockaddr_in *);
|
CIp(const int family, const uint16_t port = 0U, const char *address = NULL);
|
||||||
CIp(const char *);
|
|
||||||
CIp(const CIp &);
|
// initializer for empty constructor
|
||||||
|
void Initialize(const int family, const uint16_t port = 0U, const char *address = NULL);
|
||||||
|
|
||||||
|
// comparison operators
|
||||||
|
bool operator==(const CIp &rhs) const;
|
||||||
|
bool operator!=(const CIp &rhs) const;
|
||||||
|
|
||||||
// destructor
|
// state methods
|
||||||
virtual ~CIp() {};
|
bool AddressIsZero() const;
|
||||||
|
void ClearAddress();
|
||||||
|
const char *GetAddress() const;
|
||||||
|
operator const char *() const { return GetAddress(); }
|
||||||
|
friend std::ostream &operator<<(std::ostream &stream, const CIp &Ip);
|
||||||
|
int GetFamily() const;
|
||||||
|
uint16_t GetPort() const;
|
||||||
|
size_t GetSize() const;
|
||||||
|
uint32_t GetAddr() const;
|
||||||
|
|
||||||
// sockaddr
|
// modifiers
|
||||||
void SetSockAddr(struct sockaddr_in *);
|
void SetPort(const uint16_t newport);
|
||||||
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
|
|
||||||
|
|
||||||
// convertor
|
// for i/o
|
||||||
uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; }
|
struct sockaddr *GetPointer();
|
||||||
uint16 GetPort(void) const { return m_Addr.sin_port; }
|
const struct sockaddr *GetCPointer() const;
|
||||||
|
|
||||||
// operator
|
void Clear();
|
||||||
bool operator ==(const CIp &) const;
|
|
||||||
operator const char *() const;
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
// data
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr_in m_Addr;
|
mutable char straddr[INET6_ADDRSTRLEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
std::ostream &operator<<(std::ostream &stream, const CIp &Ip);
|
||||||
#endif /* cip_h */
|
|
||||||
|
|||||||
Loading…
Reference in new issue