mirror of https://github.com/n7tae/new-xlxd.git
parent
e6f4096f2c
commit
30a47e1bd3
@ -1,91 +1,241 @@
|
||||
//
|
||||
// cip.cpp
|
||||
// xlxd
|
||||
//
|
||||
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// This file is part of xlxd.
|
||||
//
|
||||
// xlxd 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// xlxd is distributed in the hope that it will be useful,
|
||||
// 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"
|
||||
/*
|
||||
* Copyright (C) 2020 by Thomas Early N7TAE
|
||||
*
|
||||
* 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// constructors
|
||||
#include "cip.h"
|
||||
|
||||
CIp::CIp()
|
||||
{
|
||||
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||
m_Addr.sin_family = AF_INET;
|
||||
Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
CIp::CIp(const char *sz)
|
||||
bool CIp::operator==(const CIp &rhs) const // doesn't compare ports, only addresses and families
|
||||
{
|
||||
::memset(&m_Addr, 0, sizeof(m_Addr));
|
||||
m_Addr.sin_family = AF_INET;
|
||||
// try xxx.xxx.xxx.xxxx first
|
||||
m_Addr.sin_addr.s_addr = inet_addr(sz);
|
||||
if ( m_Addr.sin_addr.s_addr == INADDR_NONE )
|
||||
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
|
||||
{
|
||||
// otherwise try to resolve via dns
|
||||
hostent *record = gethostbyname(sz);
|
||||
if( record != NULL )
|
||||
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;
|
||||
}
|
||||
|
||||
bool CIp::AddressIsZero() const
|
||||
{
|
||||
m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr;
|
||||
if (AF_INET == addr.ss_family) {
|
||||
auto addr4 = (struct sockaddr_in *)&addr;
|
||||
return (addr4->sin_addr.s_addr == 0U);
|
||||
} else {
|
||||
auto addr6 = (struct sockaddr_in6 *)&addr;
|
||||
for (unsigned int i=0; i<16; i++) {
|
||||
if (addr6->sin6_addr.s6_addr[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CIp::ClearAddress()
|
||||
{
|
||||
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, "::");
|
||||
}
|
||||
}
|
||||
|
||||
CIp::CIp(const struct sockaddr_in *sa)
|
||||
const char *CIp::GetAddress() const
|
||||
{
|
||||
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||
if (straddr[0])
|
||||
return straddr;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
CIp::CIp(const CIp &ip)
|
||||
uint32_t CIp::GetAddr() const
|
||||
{
|
||||
::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// set
|
||||
int CIp::GetFamily() const
|
||||
{
|
||||
return addr.ss_family;
|
||||
}
|
||||
|
||||
void CIp::SetSockAddr(struct sockaddr_in *sa)
|
||||
uint16_t CIp::GetPort() const
|
||||
{
|
||||
::memcpy(&m_Addr, sa, sizeof(m_Addr));
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// operator
|
||||
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) &&
|
||||
(ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) &&
|
||||
(ip.m_Addr.sin_port == m_Addr.sin_port)) ;
|
||||
memset(straddr, 0, INET6_ADDRSTRLEN); // things might change
|
||||
return (struct sockaddr *)&addr;
|
||||
}
|
||||
|
||||
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 @@
|
||||
//
|
||||
// cip.h
|
||||
// xlxd
|
||||
//
|
||||
// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015.
|
||||
// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// This file is part of xlxd.
|
||||
//
|
||||
// xlxd 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// xlxd is distributed in the hope that it will be useful,
|
||||
// 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/>.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef cip_h
|
||||
#define cip_h
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// class
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 by Thomas Early N7TAE
|
||||
*
|
||||
* 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
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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 this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
class CIp
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
CIp();
|
||||
//CIp(uint8, uint8, uint8, uint8);
|
||||
CIp(const struct sockaddr_in *);
|
||||
CIp(const char *);
|
||||
CIp(const CIp &);
|
||||
CIp(const char *address, int family = AF_UNSPEC, int type = SOCK_DGRAM, uint16_t port = 0U);
|
||||
CIp(const int family, const uint16_t port = 0U, const char *address = NULL);
|
||||
|
||||
// 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
|
||||
virtual ~CIp() {};
|
||||
// state methods
|
||||
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
|
||||
void SetSockAddr(struct sockaddr_in *);
|
||||
struct sockaddr_in *GetSockAddr(void) { return &m_Addr; }
|
||||
// modifiers
|
||||
void SetPort(const uint16_t newport);
|
||||
|
||||
// convertor
|
||||
uint32 GetAddr(void) const { return m_Addr.sin_addr.s_addr; }
|
||||
uint16 GetPort(void) const { return m_Addr.sin_port; }
|
||||
// for i/o
|
||||
struct sockaddr *GetPointer();
|
||||
const struct sockaddr *GetCPointer() const;
|
||||
|
||||
// operator
|
||||
bool operator ==(const CIp &) const;
|
||||
operator const char *() const;
|
||||
void Clear();
|
||||
|
||||
protected:
|
||||
// data
|
||||
struct sockaddr_in m_Addr;
|
||||
private:
|
||||
struct sockaddr_storage addr;
|
||||
mutable char straddr[INET6_ADDRSTRLEN];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#endif /* cip_h */
|
||||
std::ostream &operator<<(std::ostream &stream, const CIp &Ip);
|
||||
|
||||
Loading…
Reference in new issue