1
0
mirror of https://github.com/fwbuilder/fwbuilder synced 2026-06-25 02:19:37 +02:00

refactored InetAddr class, removed Inet6Addr class; all address manipulation operators now work with both address families

This commit is contained in:
Vadim Kurland
2008-05-24 04:30:18 +00:00
parent cf41530ff1
commit 7414c910c9
14 changed files with 551 additions and 630 deletions

View File

@@ -1,3 +1,14 @@
2008-05-23 Vadim Kurland <vadim@vk.crocodile.org>
* InetAddr.h (libfwbuilder): Class InetAddr represents both IPv4
and IPv6 addresses (depending on its member variable
address_family). This simplifies design of the operators that
perform address manipulations. The reason is that these operators
should not modify object they are called with but rather return
temporary object. The address family of this temporary object
depends on address family of arguments, which makes it hard to
use virtual operators.
2008-05-22 Vadim Kurland <vadim@vk.crocodile.org>
* Changes for IPv6 support. All compilers and OSConfigurator

View File

@@ -92,7 +92,7 @@ void IPv6::fromXML(xmlNodePtr root) throw(FWException)
n=FROMXMLCAST(xmlGetProp(root,TOXMLCAST("address")));
assert(n!=NULL);
setAddress(Inet6Addr(n));
setAddress(InetAddr(AF_INET6, n));
FREEXMLBUFF(n);
n=FROMXMLCAST(xmlGetProp(root,TOXMLCAST("netmask")));
@@ -101,15 +101,15 @@ void IPv6::fromXML(xmlNodePtr root) throw(FWException)
{
if (string(n).find(":")!=string::npos)
{
setNetmask(Inet6Addr(n));
setNetmask(InetAddr(AF_INET6, n));
} else
{
istringstream str(n);
int netm;
str >> netm;
setNetmask(Inet6Addr(netm));
setNetmask(InetAddr(AF_INET6, netm));
}
} else setNetmask(Inet6Addr(0));
} else setNetmask(InetAddr(AF_INET6, 0));
FREEXMLBUFF(n);
}

View File

@@ -1,179 +0,0 @@
/*
Firewall Builder
Copyright (C) 2008 NetCitadel, LLC
Author: Vadim Kurland vadim@vk.crocodile.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that 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.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fwbuilder/libfwbuilder-config.h>
#include <fwbuilder/Inet6Addr.h>
#include <fwbuilder/Interface.h>
#include <fwbuilder/inet_net.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#ifndef _WIN32
# include <sys/types.h>
# include <netinet/in.h>
#else
# include <winsock2.h>
#endif
using namespace std;
namespace libfwbuilder
{
Inet6Addr::Inet6Addr(const string &s)
throw(FWException, FWNotSupportedException)
{
if (inet_net_pton(PGSQL_AF_INET6, s.c_str(), &ipv6, sizeof(ipv6)) < 0)
throw FWException(string("Invalid IPv6 address: '")+s+"'");
}
Inet6Addr::Inet6Addr(const Inet6Addr &o) : InetAddr()
{
*this = o;
}
Inet6Addr::Inet6Addr(const char *data) throw(FWException) : InetAddr()
{
if(!data)
throw FWException("NULL IP address data..");
if (inet_net_pton(PGSQL_AF_INET6, data, &ipv6, sizeof(ipv6)) < 0)
throw FWException(string("Invalid IP address: '")+string(data)+"'");
}
Inet6Addr::Inet6Addr(const struct in6_addr *na) throw(FWException) : InetAddr()
{
_copy_in6_addr(&ipv6, na);
}
// Set netmask to 'n' bits
Inet6Addr::Inet6Addr(int len) throw(FWException)
{
if (len<0 || len>128) throw FWException(string("Invalid netmask length"));
((uint32_t *) (&ipv6))[0] = 0xffffffff;
((uint32_t *) (&ipv6))[1] = 0xffffffff;
((uint32_t *) (&ipv6))[2] = 0xffffffff;
((uint32_t *) (&ipv6))[3] = 0xffffffff;
// bits is number of zeros counting from the right end
int nbits = 128 - len;
for (int i=3; i>=0; --i)
{
if (nbits >= 32)
{
((uint32_t*)(&ipv6))[i] = 0;
nbits -= 32;
continue;
}
uint32_t t = 0xffffffff;
for (int k = nbits % 32; k; --k)
{
t <<= 1;
t &= 0xfffffffe;
}
((uint32_t*)(&ipv6))[i] = htonl(t);
break;
}
}
Inet6Addr& Inet6Addr::operator=(const Inet6Addr &addr)
{
Inet6Addr::_copy_in6_addr(&ipv6, &(addr.ipv6) );
return *this;
}
std::string Inet6Addr::toString() const
{
char ntop_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
char *cp;
cp = inet_net_ntop(PGSQL_AF_INET6, (const void*)(&ipv6), -1, ntop_buf, sizeof(ntop_buf));
if (cp==NULL)
{
ostringstream err;
switch (errno)
{
case EINVAL:
err << "Inet6Addr::toString() Invalid bit length 0";
throw FWException(err.str());
;;
case EMSGSIZE:
err << "Inet6Addr::toString() EMSGSIZE error";
throw FWException(err.str());
;;
case EAFNOSUPPORT:
err << "Inet6Addr::toString() EAFNOSUPPORT error";
throw FWException(err.str());
;;
default:
err << "Inet6Addr::toString() other error: " << errno;
throw FWException(err.str());
;;
}
}
return std::string(strdup(cp));
}
int Inet6Addr::getLength() const
{
int bits = 0;
for (int i=3; i>=0; --i)
{
uint32_t n = ntohl(((uint32_t*)(&ipv6))[i]);
if (n==0)
{
bits += 32;
continue;
}
while ((n & 1) == 0)
{
bits++;
n = n >> 1;
}
bits = 128 - bits;
break;
}
return bits;
}
Inet6Addr operator~(const Inet6Addr &a)
{
struct in6_addr res;
((uint32_t *) (&res))[0] = htonl(~(ntohl(((uint32_t *) (&a.ipv6))[0])));
((uint32_t *) (&res))[1] = htonl(~(ntohl(((uint32_t *) (&a.ipv6))[1])));
((uint32_t *) (&res))[2] = htonl(~(ntohl(((uint32_t *) (&a.ipv6))[2])));
((uint32_t *) (&res))[3] = htonl(~(ntohl(((uint32_t *) (&a.ipv6))[3])));
return Inet6Addr(&res);
}
}

View File

@@ -1,249 +0,0 @@
/*
Firewall Builder
Copyright (C) 2008 NetCitadel, LLC
Author: Vadim Kurland vadim@vk.crocodile.org
$Id$
This program is free software which we release under the GNU General Public
License. You may redistribute and/or modify this program under the terms
of that 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.
To get a copy of the GNU General Public License, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __INET6ADDR_HH_FLAG__
#define __INET6ADDR_HH_FLAG__
#include <string>
#include <vector>
#ifndef _WIN32
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
#else
# include <winsock2.h>
#endif
#include <fwbuilder/InetAddr.h>
namespace libfwbuilder
{
/**
* Class Inet6Addr is a wrapper for struct in6_addr
*
*/
class Inet6Addr : public InetAddr
{
protected:
friend class IPv6Network;
friend class Inet6AddrMask;
// Address in network order
struct in6_addr ipv6;
// copy in6_addr from sa to da
static inline void _copy_in6_addr(struct in6_addr* da,
const struct in6_addr* sa)
{
((uint32_t*)(da))[0] = ((uint32_t*)(sa))[0];
((uint32_t*)(da))[1] = ((uint32_t*)(sa))[1];
((uint32_t*)(da))[2] = ((uint32_t*)(sa))[2];
((uint32_t*)(da))[3] = ((uint32_t*)(sa))[3];
}
public:
explicit Inet6Addr()
{
((uint32_t *) (&ipv6))[0] = 0;
((uint32_t *) (&ipv6))[1] = 0;
((uint32_t *) (&ipv6))[2] = 0;
((uint32_t *) (&ipv6))[3] = 0;
}
virtual ~Inet6Addr() {}
Inet6Addr(const char *data) throw(FWException);
Inet6Addr(const struct in6_addr*) throw(FWException);
explicit Inet6Addr(const std::string&)
throw(FWException, FWNotSupportedException);
Inet6Addr(const Inet6Addr &);
Inet6Addr(int n) throw(FWException); // creates netmask 'n' bits long
Inet6Addr& operator=(const Inet6Addr &addr);
virtual bool isV4() const { return false; }
virtual bool isV6() const { return true; }
static inline Inet6Addr getAny()
{
return Inet6Addr();
}
static inline Inet6Addr getAllOnes()
{
struct in6_addr a;
((uint32_t *) (&a))[0] = 0xffffffff;
((uint32_t *) (&a))[1] = 0xffffffff;
((uint32_t *) (&a))[2] = 0xffffffff;
((uint32_t *) (&a))[3] = 0xffffffff;
return Inet6Addr(&a);
}
static inline Inet6Addr getLoopbackAddr()
{
struct in6_addr a;
((uint32_t *) (&a))[0] = 0;
((uint32_t *) (&a))[1] = 0;
((uint32_t *) (&a))[2] = 0;
((uint32_t *) (&a))[3] = htonl (1);
return Inet6Addr(&a);
}
/**
* Broadcast : there are no broadcast addresses in ipv6
* However some multicast addresses serve similar purpose. For example
* "link-scope all-hosts multicast" address ff02::1 corresponds to
* the ipv4 broadcast 255.255.255.255
*/
inline virtual bool isBroadcast() const
{
return IN6_IS_ADDR_MC_LINKLOCAL(&ipv6);
}
/**
* Multicast
*/
inline virtual bool isMulticast() const
{
return IN6_IS_ADDR_MULTICAST(&ipv6);
}
/**
* Unspecified ipv6 address
*/
inline virtual bool isAny() const
{
return (IN6_IS_ADDR_UNSPECIFIED(&ipv6));
}
/**
* calculate distance between _this_ address and address a2 and return
* it as int.
* This method is limited, it only calculates distance that fit in 32 bit
* number
*/
inline virtual int distance(const Inet6Addr &a2)
{
uint32_t *d1 = (uint32_t *)(&ipv6);
uint32_t *d2 = (uint32_t *)(&(a2.ipv6));
return *d2 - *d1 + 1;
}
virtual std::string toString() const;
/**
* returns the "length" of the netmask, that is number of bits set to '1'
* counting from left to right
*/
virtual int getLength() const;
/**
* for netmasks: return true if this is host mask, i.e. all '1'
*/
inline bool isHostMask() const
{
return (((uint32_t*)(&ipv6))[0] == 0xffffffff &&
((uint32_t*)(&ipv6))[1] == 0xffffffff &&
((uint32_t*)(&ipv6))[2] == 0xffffffff &&
((uint32_t*)(&ipv6))[3] == 0xffffffff);
}
/*****************************************************************/
inline friend Inet6Addr operator&(const Inet6Addr &addr,
const Inet6Addr &mask)
{
struct in6_addr res;
for (int i=0; i<4; ++i)
((uint32_t*)(&res))[i] =
htonl(ntohl(((uint32_t*)(&(addr.ipv6)))[i]) &
ntohl(((uint32_t*)(&(mask.ipv6)))[i]));
return Inet6Addr(&res);
}
inline friend Inet6Addr operator|(const Inet6Addr &addr,
const Inet6Addr &mask)
{
struct in6_addr res;
for (int i=0; i<4; ++i)
((uint32_t*)(&res))[i] =
htonl(ntohl(((uint32_t*)(&(addr.ipv6)))[i]) |
ntohl(((uint32_t*)(&(mask.ipv6)))[i]));
return Inet6Addr(&res);
}
inline friend Inet6Addr operator+(const Inet6Addr &addr, int increment)
{
struct in6_addr res;
Inet6Addr::_copy_in6_addr(&res, &(addr.ipv6) );
((uint32_t*)(&res))[3] =
htonl(ntohl( ((uint32_t*)(&(addr.ipv6)))[3] + increment));
return Inet6Addr(&res);
}
inline friend Inet6Addr operator-(const Inet6Addr &addr,int decrement)
{
struct in6_addr res;
Inet6Addr::_copy_in6_addr(&res, &(addr.ipv6) );
((uint32_t*)(&res))[3] =
htonl(ntohl( ((uint32_t*)(&(addr.ipv6)))[3] - decrement));
return Inet6Addr(&res);
}
inline friend bool operator<(const Inet6Addr &a, const Inet6Addr &b)
{
return (ntohl(((uint32_t*)(&(a.ipv6)))[3]) <
ntohl(((uint32_t*)(&(b.ipv6)))[3]));
}
inline friend bool operator>(const Inet6Addr &a, const Inet6Addr &b)
{
return (ntohl(((uint32_t*)(&(a.ipv6)))[3]) >
ntohl(((uint32_t*)(&(b.ipv6)))[3]));
}
inline friend bool operator==(const Inet6Addr &a, const Inet6Addr &b)
{
return (IN6_ARE_ADDR_EQUAL(&(a.ipv6), &(b.ipv6)));
}
inline friend bool operator!=(const Inet6Addr &a, const Inet6Addr &b)
{
return (!(IN6_ARE_ADDR_EQUAL(&(a.ipv6), &(b.ipv6))));
}
friend Inet6Addr operator~(const Inet6Addr &a);
};
}
#endif

View File

@@ -46,49 +46,15 @@
using namespace std;
using namespace libfwbuilder;
void Inet6AddrMask::setNetworkAndBroadcastAddress()
Inet6AddrMask::Inet6AddrMask() : InetAddrMask()
{
delete network_address;
network_address = new Inet6Addr(
dynamic_cast<const Inet6Addr&>(*address) & dynamic_cast<const Inet6Addr&>(*netmask));
delete broadcast_address;
broadcast_address = new Inet6Addr(
dynamic_cast<const Inet6Addr&>(*address) | (~(dynamic_cast<const Inet6Addr&>(*netmask))));
address->address_family = AF_INET6;
netmask->address_family = AF_INET6;
setNetworkAndBroadcastAddress();
}
Inet6AddrMask::Inet6AddrMask() : InetAddrMask(true)
{
address = new Inet6Addr();
netmask = new Inet6Addr();
broadcast_address = new Inet6Addr();
network_address = new Inet6Addr();
}
Inet6AddrMask::Inet6AddrMask(const Inet6Addr &a, const Inet6Addr &n) :
Inet6AddrMask::Inet6AddrMask(const string &s) throw(FWException) :
InetAddrMask(true)
{
address = new Inet6Addr(a & n);
netmask = new Inet6Addr(n);
broadcast_address = new Inet6Addr();
network_address = new Inet6Addr();
setNetworkAndBroadcastAddress();
}
Inet6AddrMask::Inet6AddrMask(const Inet6AddrMask& other) : InetAddrMask(true)
{
Inet6Addr *i6_addr = dynamic_cast<Inet6Addr*>(other.address);
assert(i6_addr);
Inet6Addr *i6_nm = dynamic_cast<Inet6Addr*>(other.netmask);
assert(i6_nm);
address = new Inet6Addr(*i6_addr);
netmask = new Inet6Addr(*i6_nm);
broadcast_address = new Inet6Addr();
network_address = new Inet6Addr();
setNetworkAndBroadcastAddress();
}
Inet6AddrMask::Inet6AddrMask(const string &s) throw(FWException) : InetAddrMask(true)
{
struct in6_addr a_ipv6;
int nbits;
@@ -96,43 +62,30 @@ Inet6AddrMask::Inet6AddrMask(const string &s) throw(FWException) : InetAddrMask(
if (nbits < 0)
throw FWException(string("Invalid IP address: '") + s + "'");
address = new Inet6Addr(&a_ipv6);
netmask = new Inet6Addr(nbits);
address = new InetAddr(&a_ipv6);
netmask = new InetAddr(AF_INET6, nbits);
broadcast_address = new Inet6Addr();
network_address = new Inet6Addr();
broadcast_address = new InetAddr();
network_address = new InetAddr();
setNetworkAndBroadcastAddress();
}
Inet6AddrMask::Inet6AddrMask(const InetAddr &a, const InetAddr &n) :
InetAddrMask(a, n)
{
}
Inet6AddrMask::~Inet6AddrMask()
{
// destructor of InetAddrMask deletes address, netmask
// and other member variables
}
void Inet6AddrMask::setAddress(const InetAddr &a)
{
assert(a.isV6());
delete address;
address = new Inet6Addr(dynamic_cast<const Inet6Addr&>(a));
setNetworkAndBroadcastAddress();
}
void Inet6AddrMask::setNetmask(const InetAddr &nm)
{
assert(nm.isV6());
delete netmask;
netmask = new Inet6Addr(dynamic_cast<const Inet6Addr&>(nm));
setNetworkAndBroadcastAddress();
}
std::string Inet6AddrMask::toString() const
{
char ntop_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
char *cp;
cp = inet_net_ntop(PGSQL_AF_INET6,
(const void*)(&(dynamic_cast<Inet6Addr*>(address)->ipv6)),
cp = inet_net_ntop(PGSQL_AF_INET6, (const void*)(&(address->ipv6)),
netmask->getLength(),
ntop_buf, sizeof(ntop_buf));
if (cp==NULL)

View File

@@ -48,27 +48,20 @@
#include <fwbuilder/FWException.h>
#include <fwbuilder/InetAddrMask.h>
#include <fwbuilder/Inet6Addr.h>
namespace libfwbuilder
{
class Inet6AddrMask : public InetAddrMask
{
private:
void setNetworkAndBroadcastAddress();
public:
Inet6AddrMask();
Inet6AddrMask(const Inet6Addr&, const Inet6Addr&);
Inet6AddrMask(const std::string &s) throw(FWException);
Inet6AddrMask(const Inet6AddrMask&);
Inet6AddrMask(const InetAddr&, const InetAddr&);
virtual ~Inet6AddrMask();
virtual void setAddress(const InetAddr &a);
virtual void setNetmask(const InetAddr &nm);
virtual std::string toString() const;
};

View File

@@ -29,8 +29,11 @@
#include <fwbuilder/InetAddr.h>
#include <fwbuilder/Interface.h>
#include <fwbuilder/inet_net.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <assert.h>
#ifndef _WIN32
@@ -41,18 +44,92 @@
#endif
using namespace std;
using namespace libfwbuilder;
namespace libfwbuilder
void InetAddr::init_from_string(const char* data)
{
if(!data) throw FWException("NULL IP address data..");
if (address_family == AF_INET)
{
if (inet_aton(data, &ipv4)==0)
throw FWException(string("Invalid IP address: '")+string(data)+"'");
} else
{
if (inet_net_pton(PGSQL_AF_INET6, data, &ipv6, sizeof(ipv6)) < 0)
throw FWException(string("Invalid IPv6 address: '")+string(data)+"'");
}
}
void InetAddr::init_from_int(int len)
{
if (address_family == AF_INET)
{
if (len<0 || len>32) throw FWException(string("Invalid netmask length"));
unsigned long nm_bits = 0;
int i = len;
while (i>0)
{
nm_bits >>= 1;
nm_bits |= 0x80000000;
i--;
}
ipv4.s_addr = htonl(nm_bits);
} else
{
if (len<0 || len>128)
throw FWException(string("Invalid netmask length"));
((uint32_t *) (&ipv6))[0] = 0xffffffff;
((uint32_t *) (&ipv6))[1] = 0xffffffff;
((uint32_t *) (&ipv6))[2] = 0xffffffff;
((uint32_t *) (&ipv6))[3] = 0xffffffff;
// bits is number of zeros counting from the right end
int nbits = 128 - len;
for (int i=3; i>=0; --i)
{
if (nbits >= 32)
{
((uint32_t*)(&ipv6))[i] = 0;
nbits -= 32;
continue;
}
uint32_t t = 0xffffffff;
for (int k = nbits % 32; k; --k)
{
t <<= 1;
t &= 0xfffffffe;
}
((uint32_t*)(&ipv6))[i] = htonl(t);
break;
}
}
}
InetAddr::InetAddr(const string &s)
throw(FWException, FWNotSupportedException)
{
address_family = AF_INET;
if (inet_aton(s.c_str(), &ipv4)==0)
throw FWException(string("Invalid IP address: '")+s+"'");
}
InetAddr::InetAddr(int af, const string &s)
throw(FWException, FWNotSupportedException)
{
address_family = af;
if (address_family==AF_INET)
{
if (inet_aton(s.c_str(), &ipv4)==0)
throw FWException(string("Invalid IP address: '")+s+"'");
} else
{
if (inet_net_pton(PGSQL_AF_INET6, s.c_str(), &ipv6, sizeof(ipv6)) < 0)
throw FWException(string("Invalid IPv6 address: '")+s+"'");
}
}
InetAddr::InetAddr(const InetAddr &o)
{
*this = o;
@@ -60,54 +137,268 @@ InetAddr::InetAddr(const InetAddr &o)
InetAddr::InetAddr(const char *data) throw(FWException)
{
if(!data)
throw FWException("NULL IP address data..");
if (inet_aton(data, &ipv4)==0)
throw FWException(string("Invalid IP address: '")+string(data)+"'");
address_family = AF_INET;
init_from_string(data);
}
InetAddr::InetAddr(int af, const char *data) throw(FWException)
{
address_family = af;
init_from_string(data);
}
InetAddr::InetAddr(const struct in_addr *na) throw(FWException)
{
address_family = AF_INET;
ipv4.s_addr = na->s_addr;
}
InetAddr::InetAddr(const struct in6_addr *na) throw(FWException)
{
address_family = AF_INET6;
_copy_in6_addr(&ipv6, na);
}
// Set netmask to 'n' bits
InetAddr::InetAddr(int n) throw(FWException)
{
if (n<0 || n>32) throw FWException(string("Invalid netmask length"));
unsigned long nm_bits = 0;
int i = n;
while (i>0)
{
nm_bits >>= 1;
nm_bits |= 0x80000000;
i--;
}
ipv4.s_addr = htonl(nm_bits);
address_family = AF_INET;
init_from_int(n);
}
InetAddr::InetAddr(int af, int n) throw(FWException)
{
address_family = af;
init_from_int(n);
}
InetAddr& InetAddr::operator=(const InetAddr &addr)
{
ipv4.s_addr = addr.ipv4.s_addr;
if ((address_family = addr.address_family)==AF_INET)
{
ipv4.s_addr = addr.ipv4.s_addr;
} else
{
InetAddr::_copy_in6_addr(&ipv6, &(addr.ipv6) );
}
return *this;
}
int InetAddr::getLength() const
{
if (ipv4.s_addr == INADDR_BROADCAST) return 32;
if (ipv4.s_addr == 0) return 0;
unsigned int n = ntohl(ipv4.s_addr);
int i=0;
while (n)
if (address_family==AF_INET)
{
n=n<<1;
i++;
if (ipv4.s_addr == INADDR_BROADCAST) return 32;
if (ipv4.s_addr == 0) return 0;
unsigned int n = ntohl(ipv4.s_addr);
int i=0;
while (n)
{
n=n<<1;
i++;
}
return i;
} else
{
int bits = 0;
for (int i=3; i>=0; --i)
{
uint32_t n = ntohl(((uint32_t*)(&ipv6))[i]);
if (n==0)
{
bits += 32;
continue;
}
while ((n & 1) == 0)
{
bits++;
n = n >> 1;
}
bits = 128 - bits;
break;
}
return bits;
}
return i;
}
string InetAddr::toString() const
{
if (address_family==AF_INET) return std::string(strdup(inet_ntoa(ipv4)));
else
{
char ntop_buf[sizeof
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
char *cp;
cp = inet_net_ntop(PGSQL_AF_INET6, (const void*)(&ipv6),
-1, ntop_buf, sizeof(ntop_buf));
if (cp==NULL)
{
ostringstream err;
switch (errno)
{
case EINVAL:
err << "InetAddr::toString() Invalid bit length 0";
throw FWException(err.str());
;;
case EMSGSIZE:
err << "InetAddr::toString() EMSGSIZE error";
throw FWException(err.str());
;;
case EAFNOSUPPORT:
err << "InetAddr::toString() EAFNOSUPPORT error";
throw FWException(err.str());
;;
default:
err << "InetAddr::toString() other error: " << errno;
throw FWException(err.str());
;;
}
}
return std::string(strdup(cp));
}
}
// note that address family of the result is dictated by the address family of
// "this". Address family of mask must be the same.
InetAddr InetAddr::opAnd(const InetAddr &mask) const
{
assert(address_family==mask.address_family);
if (address_family==AF_INET)
{
struct in_addr res;
res.s_addr = htonl(ntohl(ipv4.s_addr) & ntohl(mask.ipv4.s_addr));
return InetAddr(&res);
} else {
struct in6_addr res;
for (int i=0; i<4; ++i)
((uint32_t*)(&res))[i] =
htonl(ntohl(((uint32_t*)(&(ipv6)))[i]) &
ntohl(((uint32_t*)(&(mask.ipv6)))[i]));
return InetAddr(&res);
}
}
InetAddr InetAddr::opOr(const InetAddr &mask) const
{
assert(address_family==mask.address_family);
if (address_family==AF_INET)
{
struct in_addr res;
res.s_addr = htonl(ntohl(ipv4.s_addr) | ntohl(mask.ipv4.s_addr));
return InetAddr(&res);
} else
{
struct in6_addr res;
for (int i=0; i<4; ++i)
((uint32_t*)(&res))[i] =
htonl(ntohl(((uint32_t*)(&(ipv6)))[i]) |
ntohl(((uint32_t*)(&(mask.ipv6)))[i]));
return InetAddr(&res);
}
}
InetAddr InetAddr::opPlus(int increment) const
{
if (address_family==AF_INET)
{
struct in_addr res;
res.s_addr = htonl(ntohl(ipv4.s_addr) + increment);
return InetAddr(&res);
} else
{
struct in6_addr res;
InetAddr::_copy_in6_addr(&res, &(ipv6) );
((uint32_t*)(&res))[3] =
htonl(ntohl( ((uint32_t*)(&(ipv6)))[3] + increment));
return InetAddr(&res);
}
}
InetAddr InetAddr::opMinus(int decrement) const
{
if (address_family==AF_INET)
{
struct in_addr res;
res.s_addr = htonl(ntohl(ipv4.s_addr) - decrement);
return InetAddr(&res);
} else
{
struct in6_addr res;
InetAddr::_copy_in6_addr(&res, &(ipv6) );
((uint32_t*)(&res))[3] =
htonl(ntohl( ((uint32_t*)(&(ipv6)))[3] - decrement));
return InetAddr(&res);
}
}
bool InetAddr::opLT(const InetAddr &other) const
{
assert(address_family==other.address_family);
if (address_family==AF_INET)
{
return (ntohl( ipv4.s_addr ) < ntohl( other.ipv4.s_addr ));
} else
{
return (ntohl(((uint32_t*)(&(ipv6)))[3]) <
ntohl(((uint32_t*)(&(other.ipv6)))[3]));
}
}
bool InetAddr::opGT(const InetAddr &other) const
{
assert(address_family==other.address_family);
if (address_family==AF_INET)
{
return (ntohl( ipv4.s_addr ) > ntohl( other.ipv4.s_addr ));
} else
{
return (ntohl(((uint32_t*)(&(ipv6)))[3]) >
ntohl(((uint32_t*)(&(other.ipv6)))[3]));
}
}
bool InetAddr::opEQ(const InetAddr &other) const
{
assert(address_family==other.address_family);
if (address_family==AF_INET)
{
return ipv4.s_addr == other.ipv4.s_addr;
} else
{
return (IN6_ARE_ADDR_EQUAL(&(ipv6), &(other.ipv6)));
}
}
bool InetAddr::opNEQ(const InetAddr &other) const
{
assert(address_family==other.address_family);
if (address_family==AF_INET)
{
return ipv4.s_addr != other.ipv4.s_addr;
} else
{
return (!(IN6_ARE_ADDR_EQUAL(&(ipv6), &(other.ipv6))));
}
}
InetAddr InetAddr::opCompl() const
{
if (address_family==AF_INET)
{
struct in_addr res;
res.s_addr = htonl(~(ntohl(ipv4.s_addr)));
return InetAddr(&res);
} else
{
struct in6_addr res;
((uint32_t *) (&res))[0] = htonl(~(ntohl(((uint32_t *) (&ipv6))[0])));
((uint32_t *) (&res))[1] = htonl(~(ntohl(((uint32_t *) (&ipv6))[1])));
((uint32_t *) (&res))[2] = htonl(~(ntohl(((uint32_t *) (&ipv6))[2])));
((uint32_t *) (&res))[3] = htonl(~(ntohl(((uint32_t *) (&ipv6))[3])));
return InetAddr(&res);
}
}

View File

@@ -29,6 +29,8 @@
#include <string>
#include <vector>
#include <typeinfo>
#include <assert.h>
#ifndef _WIN32
# include <sys/types.h>
@@ -45,7 +47,15 @@ namespace libfwbuilder
{
/**
* Class InetAddr is a wrapper for struct inet_addr
* Class InetAddr is a wrapper for struct inet_addr and in6_addr
*
* Why both address families are implemented as the same class ? Mostly
* because I need to have a family of two-argument operators such as
* operator&, operator| etc which return new object of the class that
* represent the same address family as the arguments. These operators
* should be "friends" of class InetAddr since they return new object
* by value rather than modify "this". But how to do it if returned
* type should be different depending on the types of arguments ?
*
*/
class InetAddr
@@ -53,158 +63,250 @@ class InetAddr
protected:
friend class InetAddrMask;
friend class Inet6AddrMask;
int address_family;
// Address in network order
struct in_addr ipv4;
struct in_addr ipv4;
struct in6_addr ipv6;
// copy in6_addr from sa to da
static inline void _copy_in6_addr(struct in6_addr* da,
const struct in6_addr* sa)
{
((uint32_t*)(da))[0] = ((uint32_t*)(sa))[0];
((uint32_t*)(da))[1] = ((uint32_t*)(sa))[1];
((uint32_t*)(da))[2] = ((uint32_t*)(sa))[2];
((uint32_t*)(da))[3] = ((uint32_t*)(sa))[3];
}
void init_from_string(const char* data);
void init_from_int(int n);
public:
explicit InetAddr() { ipv4.s_addr = 0; }
explicit InetAddr()
{
address_family = AF_INET;
ipv4.s_addr = 0;
((uint32_t *) (&ipv6))[0] = 0;
((uint32_t *) (&ipv6))[1] = 0;
((uint32_t *) (&ipv6))[2] = 0;
((uint32_t *) (&ipv6))[3] = 0;
}
virtual ~InetAddr() {}
InetAddr(const char *data) throw(FWException);
InetAddr(int af, const char *data) throw(FWException);
InetAddr(const struct in_addr*) throw(FWException);
InetAddr(const struct in6_addr*) throw(FWException);
explicit InetAddr(const std::string&)
throw(FWException, FWNotSupportedException);
explicit InetAddr(int af, const std::string&)
throw(FWException, FWNotSupportedException);
InetAddr(const InetAddr &);
// creates netmask 'n' bits long
explicit InetAddr(int n) throw(FWException);
explicit InetAddr(int af, int n) throw(FWException);
InetAddr& operator=(const InetAddr &addr);
virtual bool isV4() const { return true; }
virtual bool isV6() const { return false; }
bool isV4() const { return (address_family==AF_INET); }
bool isV6() const { return (address_family==AF_INET6); }
static inline InetAddr getAny()
{
return InetAddr();
}
static inline InetAddr getAllOnes()
static inline InetAddr getAllOnes(int af=AF_INET)
{
struct in_addr allones;
allones.s_addr = 0xffffffff;
return InetAddr(&allones);
if (af==AF_INET)
{
struct in_addr allones;
allones.s_addr = 0xffffffff;
return InetAddr(&allones);
} else
{
struct in6_addr a;
((uint32_t *) (&a))[0] = 0xffffffff;
((uint32_t *) (&a))[1] = 0xffffffff;
((uint32_t *) (&a))[2] = 0xffffffff;
((uint32_t *) (&a))[3] = 0xffffffff;
return InetAddr(&a);
}
}
static inline InetAddr getLoopbackAddr()
static inline InetAddr getLoopbackAddr(int af=AF_INET)
{
struct in_addr loopback;
loopback.s_addr = htonl(INADDR_LOOPBACK);
return InetAddr(&loopback);
if (af==AF_INET)
{
struct in_addr loopback;
loopback.s_addr = htonl(INADDR_LOOPBACK);
return InetAddr(&loopback);
} else
{
struct in6_addr a;
((uint32_t *) (&a))[0] = 0;
((uint32_t *) (&a))[1] = 0;
((uint32_t *) (&a))[2] = 0;
((uint32_t *) (&a))[3] = htonl (1);
return InetAddr(&a);
}
}
inline virtual std::string toString() const
{
return std::string(strdup(inet_ntoa(ipv4)));
}
std::string toString() const;
/**
* Broadcast : 255.255.255.255
*
* there are no broadcast addresses in ipv6. However some multicast
* addresses serve similar purpose. For example "link-scope
* all-hosts multicast" address ff02::1 corresponds to the ipv4
* broadcast 255.255.255.255
*/
inline virtual bool isBroadcast() const
inline bool isBroadcast() const
{
return ipv4.s_addr == INADDR_BROADCAST;
if (address_family==AF_INET)
return ipv4.s_addr == INADDR_BROADCAST;
else
return IN6_IS_ADDR_MC_LINKLOCAL(&ipv6);
}
/**
* Multicast : 224.0.0.0 - 239.0.0.0
*/
inline virtual bool isMulticast() const
inline bool isMulticast() const
{
return IN_MULTICAST(ntohl(ipv4.s_addr));
if (address_family==AF_INET)
return IN_MULTICAST(ntohl(ipv4.s_addr));
else
return IN6_IS_ADDR_MULTICAST(&ipv6);
}
/**
* INADDR_ANY: 0
*/
inline virtual bool isAny() const
inline bool isAny() const
{
return ipv4.s_addr == INADDR_ANY;
if (address_family==AF_INET)
return ipv4.s_addr == INADDR_ANY;
else
return (IN6_IS_ADDR_UNSPECIFIED(&ipv6));
}
/**
* calculate distance between _this_ address and address a2 and return
* it as int
* This method is limited, it only calculates distance that fit in 32 bit
* number
*/
inline virtual int distance(const InetAddr &a2) const
inline int distance(const InetAddr &a2) const
{
return ntohl(a2.ipv4.s_addr) - ntohl(ipv4.s_addr) + 1;
if (address_family==AF_INET)
return ntohl(a2.ipv4.s_addr) - ntohl(ipv4.s_addr) + 1;
else
{
uint32_t *d1 = (uint32_t *)(&ipv6);
uint32_t *d2 = (uint32_t *)(&(a2.ipv6));
return *d2 - *d1 + 1;
}
}
/**
* returns the "length" of the netmask, that is number of bits set to '1'
* counting from left to right
*/
virtual int getLength() const;
int getLength() const;
/**
* for netmasks: return true if this is host mask, i.e. all '1'
*/
inline bool isHostMask() const
{
return ipv4.s_addr == INADDR_BROADCAST;
if (address_family==AF_INET)
return ipv4.s_addr == INADDR_BROADCAST;
else
return (((uint32_t*)(&ipv6))[0] == 0xffffffff &&
((uint32_t*)(&ipv6))[1] == 0xffffffff &&
((uint32_t*)(&ipv6))[2] == 0xffffffff &&
((uint32_t*)(&ipv6))[3] == 0xffffffff);
}
/*****************************************************************/
InetAddr opAnd(const InetAddr &mask) const;
InetAddr opOr(const InetAddr &mask) const;
InetAddr opPlus(int increment) const;
InetAddr opMinus(int decrement) const;
bool opLT(const InetAddr &other) const;
bool opGT(const InetAddr &other) const;
bool opEQ(const InetAddr &other) const;
bool opNEQ(const InetAddr &other) const;
InetAddr opCompl() const;
/*****************************************************************/
inline friend InetAddr operator&(const InetAddr &addr,
const InetAddr &mask)
{
struct in_addr res;
res.s_addr = htonl(ntohl(addr.ipv4.s_addr) & ntohl(mask.ipv4.s_addr));
return InetAddr(&res);
assert (typeid(addr) == typeid(mask));
return addr.opAnd(mask);
}
inline friend InetAddr operator|(const InetAddr &addr,
const InetAddr &mask)
{
struct in_addr res;
res.s_addr = htonl(ntohl(addr.ipv4.s_addr) | ntohl(mask.ipv4.s_addr));
return InetAddr(&res);
assert (typeid(addr) == typeid(mask));
return addr.opOr(mask);
}
inline friend InetAddr operator+(const InetAddr &addr, int increment)
{
struct in_addr res;
res.s_addr = htonl(ntohl(addr.ipv4.s_addr) + increment);
return InetAddr(&res);
return addr.opPlus(increment);
}
inline friend InetAddr operator-(const InetAddr &addr,int decrement)
inline friend InetAddr operator-(const InetAddr &addr, int decrement)
{
struct in_addr res;
res.s_addr = htonl(ntohl(addr.ipv4.s_addr) - decrement);
return InetAddr(&res);
return addr.opMinus(decrement);
}
inline friend bool operator<(const InetAddr &a, const InetAddr &b)
{
return (ntohl( a.ipv4.s_addr ) < ntohl( b.ipv4.s_addr ));
assert (typeid(a) == typeid(b));
return a.opLT(b);
}
inline friend bool operator>(const InetAddr &a, const InetAddr &b)
{
return (ntohl( a.ipv4.s_addr ) > ntohl( b.ipv4.s_addr ));
assert (typeid(a) == typeid(b));
return a.opGT(b);
}
inline friend bool operator==(const InetAddr &a, const InetAddr &b)
{
return a.ipv4.s_addr == b.ipv4.s_addr;
assert (typeid(a) == typeid(b));
return a.opEQ(b);
}
inline friend bool operator!=(const InetAddr &a, const InetAddr &b)
{
return a.ipv4.s_addr != b.ipv4.s_addr;
assert (typeid(a) == typeid(b));
return a.opNEQ(b);
}
inline friend InetAddr operator~(const InetAddr &a)
{
struct in_addr res;
res.s_addr = htonl(~(ntohl(a.ipv4.s_addr)));
return InetAddr(&res);
return a.opCompl();
}
};

View File

@@ -135,14 +135,12 @@ InetAddrMask::~InetAddrMask()
void InetAddrMask::setAddress(const InetAddr &a)
{
assert(a.isV4());
*address = a;
setNetworkAndBroadcastAddress();
}
void InetAddrMask::setNetmask(const InetAddr &nm)
{
assert(nm.isV4());
*netmask = nm;
setNetworkAndBroadcastAddress();
}

View File

@@ -67,8 +67,6 @@ namespace libfwbuilder
class InetAddrMask
{
private:
void setNetworkAndBroadcastAddress();
protected:
@@ -86,6 +84,7 @@ public:
InetAddrMask(const std::string &s) throw(FWException);
InetAddrMask(const InetAddrMask&);
virtual ~InetAddrMask();
void setNetworkAndBroadcastAddress();
virtual const InetAddr* getAddressPtr() const { return address; }
virtual const InetAddr* getNetmaskPtr() const { return netmask; }

View File

@@ -84,7 +84,7 @@ void NetworkIPv6::fromXML(xmlNodePtr root) throw(FWException)
const char *n=FROMXMLCAST(xmlGetProp(root,TOXMLCAST("address")));
assert(n!=NULL);
setAddress(Inet6Addr(n));
setAddress(InetAddr(AF_INET6, n));
FREEXMLBUFF(n);
n=FROMXMLCAST(xmlGetProp(root,TOXMLCAST("netmask")));
@@ -93,15 +93,15 @@ void NetworkIPv6::fromXML(xmlNodePtr root) throw(FWException)
{
if (string(n).find(":")!=string::npos)
{
setNetmask(Inet6Addr(n));
setNetmask(InetAddr(AF_INET6, n));
} else
{
istringstream str(n);
int netm;
str >> netm;
setNetmask(Inet6Addr(netm));
setNetmask(InetAddr(AF_INET6, netm));
}
} else setNetmask(Inet6Addr(0));
} else setNetmask(InetAddr(AF_INET6, 0));
FREEXMLBUFF(n);
}

View File

@@ -7,7 +7,6 @@ VERSION = $$SO_VERSION
SOURCES = inet_net_ntop.c \
inet_net_pton.c \
InetAddr.cpp \
Inet6Addr.cpp \
InetAddrMask.cpp \
Inet6AddrMask.cpp \
IPRoute.cpp \
@@ -68,7 +67,6 @@ SOURCES = inet_net_ntop.c \
HEADERS = inet_net.h \
InetAddr.h \
Inet6Addr.h \
InetAddrMask.h \
Inet6AddrMask.h \
IPRoute.h \

View File

@@ -80,30 +80,30 @@ int main(int, char * const *)
cout << endl;
cout << "Start test for Inet6AddrMask" << endl;
Inet6Addr x1(0);
InetAddr x1(AF_INET6, 0);
cout << "Inet6Addr::Inet6Addr(0) "
<< x1.toString() << " length=" << x1.getLength() << endl;
Inet6Addr x2(8);
InetAddr x2(AF_INET6, 8);
cout << "Inet6Addr::Inet6Addr(8) "
<< x2.toString() << " length=" << x2.getLength() << endl;
Inet6Addr x3(16);
InetAddr x3(AF_INET6, 16);
cout << "Inet6Addr::Inet6Addr(16) "
<< x3.toString() << " length=" << x3.getLength() << endl;
Inet6Addr x4(64);
InetAddr x4(AF_INET6, 64);
cout << "Inet6Addr::Inet6Addr(64) "
<< x4.toString() << " length=" << x4.getLength() << endl;
Inet6Addr x5(128);
InetAddr x5(AF_INET6, 128);
cout << "Inet6Addr::Inet6Addr(128) "
<< x5.toString() << " length=" << x5.getLength() << endl;
Inet6Addr x6("fe80::21d:9ff:fe8b:8e94");
Inet6Addr y6(64);
Inet6Addr z = x6 & y6;
InetAddr x6(AF_INET6, "fe80::21d:9ff:fe8b:8e94");
InetAddr y6(AF_INET6, 64);
InetAddr z = x6 & y6;
cout << "z=" << z.toString() << endl;
assert(z.toString()=="fe80::");
@@ -115,7 +115,7 @@ int main(int, char * const *)
cout << endl;
Inet6AddrMask *a1 = new Inet6AddrMask();
sa = a1->getAddress().toString();
sa = a1->getAddressPtr()->toString();
cout << "a1=" << sa << endl;
assert(sa=="::");
// assert(a1->dimension()==0);
@@ -123,16 +123,18 @@ int main(int, char * const *)
cout << endl;
Inet6AddrMask *a2 = new Inet6AddrMask(Inet6Addr("fe80::21d:9ff:fe8b:8e94"),
Inet6Addr(128));
sa = a2->getAddress().toString();
Inet6AddrMask *a2 = new Inet6AddrMask(
InetAddr(AF_INET6, "fe80::21d:9ff:fe8b:8e94"),
InetAddr(AF_INET6, 128));
sa = a2->getAddressPtr()->toString();
cout << "a2.address=" << sa << endl;
assert(sa=="fe80::21d:9ff:fe8b:8e94");
sa = a2->getNetmask().toString();
sa = a2->getNetmaskPtr()->toString();
cout << "a2.netmask=" << sa
<< " length=" << a2->getNetmask().getLength() << endl;
<< " length=" << a2->getNetmaskPtr()->getLength() << endl;
assert(sa=="ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
assert(a2->getNetmask().getLength()==128);
assert(a2->getNetmaskPtr()->getLength()==128);
// assert(a2->dimension()==18446744073709551616);
@@ -142,17 +144,19 @@ int main(int, char * const *)
cout << endl;
Inet6AddrMask *a3 = new Inet6AddrMask(Inet6Addr("fe80::21d:9ff:fe8b:8e94"),
Inet6Addr(128));
a3->setNetmask(Inet6Addr(64));
sa = a3->getAddress().toString();
Inet6AddrMask *a3 = new Inet6AddrMask(
InetAddr(AF_INET6, "fe80::21d:9ff:fe8b:8e94"),
InetAddr(AF_INET6, 128));
a3->setNetmask(InetAddr(AF_INET6, 64));
sa = a3->getAddressPtr()->toString();
cout << "a3.address=" << sa << endl;
assert(sa=="fe80::21d:9ff:fe8b:8e94");
sa = a3->getNetmask().toString();
sa = a3->getNetmaskPtr()->toString();
cout << "a3.netmask=" << sa
<< " length=" << a3->getNetmask().getLength() << endl;
<< " length=" << a3->getNetmaskPtr()->getLength() << endl;
assert(sa=="ffff:ffff:ffff:ffff::");
assert(a3->getNetmask().getLength()==64);
assert(a3->getNetmaskPtr()->getLength()==64);
// assert(a3->dimension()==18446744073709551616);
assert(a3->toString()=="fe80::21d:9ff:fe8b:8e94/64");
@@ -161,32 +165,32 @@ int main(int, char * const *)
Inet6AddrMask *a4 = new Inet6AddrMask(
string("fe80::21d:9ff:fe8b:8e94/64"));
sa = a4->getAddress().toString();
sa = a4->getAddressPtr()->toString();
cout << "a4.address=" << sa << endl;
assert(sa=="fe80::21d:9ff:fe8b:8e94");
sa = a4->getNetmask().toString();
sa = a4->getNetmaskPtr()->toString();
cout << "a4.netmask=" << sa << endl;
assert(sa=="ffff:ffff:ffff:ffff::");
// assert(a4->dimension()==1);
cout << "Checking Inet6AddrMask::belongs()" << endl;
assert(a4->belongs(a2->getAddress()));
assert(a4->belongs( *(a2->getAddressPtr()) ));
cout << endl;
Inet6AddrMask *a5 = new Inet6AddrMask(*a3);
sa = a5->getAddress().toString();
sa = a5->getAddressPtr()->toString();
assert(sa=="fe80::21d:9ff:fe8b:8e94");
sa = a5->getNetmask().toString();
sa = a5->getNetmaskPtr()->toString();
assert(sa=="ffff:ffff:ffff:ffff::");
// assert(a5->dimension()==1);
cout << "Checking Inet6AddrMask::setAddress()" << endl;
a5->setAddress(Inet6Addr("3ffe:1200:2001:1:8000::1"));
sa = a5->getAddress().toString();
a5->setAddress(InetAddr(AF_INET6, "3ffe:1200:2001:1:8000::1"));
sa = a5->getAddressPtr()->toString();
cout << "a5.address=" << sa << endl;
assert(sa=="3ffe:1200:2001:1:8000::1");
sa = a5->getNetmask().toString();
sa = a5->getNetmaskPtr()->toString();
assert(sa=="ffff:ffff:ffff:ffff::");
// assert(a5->dimension()==1);

View File

@@ -81,46 +81,46 @@ int main(int, char * const *)
cout << "Start test for InetAddrMask" << endl;
InetAddrMask *a1 = new InetAddrMask();
sa = a1->getAddress().toString();
sa = a1->getAddressPtr()->toString();
assert(sa=="0.0.0.0");
assert(a1->dimension()==0);
InetAddrMask *a2 = new InetAddrMask(InetAddr("1.1.1.1"), InetAddr("255.255.255.0"));
sa = a2->getAddress().toString();
sa = a2->getAddressPtr()->toString();
assert(sa=="1.1.1.0");
sa = a2->getNetmask().toString();
sa = a2->getNetmaskPtr()->toString();
assert(sa=="255.255.255.0");
assert(a2->dimension()==256);
assert(a2->toString()=="1.1.1.0/255.255.255.0");
InetAddrMask *a3 = new InetAddrMask(string("1.1.1.1"));
sa = a3->getAddress().toString();
sa = a3->getAddressPtr()->toString();
assert(sa=="1.1.1.1");
sa = a3->getNetmask().toString();
sa = a3->getNetmaskPtr()->toString();
assert(sa=="255.255.255.255");
assert(a3->dimension()==1);
assert(a2->belongs(a3->getAddress()));
assert(a2->belongs( *(a3->getAddressPtr()) ));
InetAddrMask *a4 = new InetAddrMask(*a3);
sa = a4->getAddress().toString();
sa = a4->getAddressPtr()->toString();
assert(sa=="1.1.1.1");
sa = a4->getNetmask().toString();
sa = a4->getNetmaskPtr()->toString();
assert(sa=="255.255.255.255");
assert(a4->dimension()==1);
a4->setAddress(InetAddr("2.2.2.2"));
sa = a4->getAddress().toString();
sa = a4->getAddressPtr()->toString();
assert(sa=="2.2.2.2");
sa = a4->getNetmask().toString();
sa = a4->getNetmaskPtr()->toString();
assert(sa=="255.255.255.255");
assert(a4->dimension()==1);
a4->setNetmask(InetAddr("255.255.0.0"));
sa = a4->getAddress().toString();
sa = a4->getAddressPtr()->toString();
assert(sa=="2.2.2.2");
sa = a4->getNetmask().toString();
sa = a4->getNetmaskPtr()->toString();
assert(sa=="255.255.0.0");
assert(a4->dimension()==256*256);