Browse Source

Leave IP addresses alone instead of deleting them from tap if they are not members of any of the networks under management.

Adam Ierymenko 11 years ago
parent
commit
f82c7006ea
3 changed files with 189 additions and 179 deletions
  1. 18 5
      node/EthernetTap.hpp
  2. 120 8
      node/InetAddress.cpp
  3. 51 166
      node/InetAddress.hpp

+ 18 - 5
node/EthernetTap.hpp

@@ -115,7 +115,8 @@ public:
 	/**
 	/**
 	 * Set this tap's IP addresses to exactly this set of IPs
 	 * Set this tap's IP addresses to exactly this set of IPs
 	 *
 	 *
-	 * New IPs are created, ones not in this list are removed.
+	 * New IPs are created. Any IP that overlaps with the network of an IP in
+	 * this list is removed, but other IPs are left intact.
 	 *
 	 *
 	 * @param ips IP addresses with netmask in port field
 	 * @param ips IP addresses with netmask in port field
 	 */
 	 */
@@ -130,15 +131,27 @@ public:
 			if (i->isLinkLocal()) {
 			if (i->isLinkLocal()) {
 				if (i->isV6())
 				if (i->isV6())
 					haveV6LinkLocal = true;
 					haveV6LinkLocal = true;
-			} else if (!allIps.count(*i))
-				removeIP(*i);
+			} else if (!allIps.count(*i)) {
+				for(std::set<InetAddress>::const_iterator i2(allIps.begin());i2!=allIps.end();++i2) {
+					if (i->sameNetworkAs(*i2)) {
+						removeIP(*i);
+						break;
+					}
+				}
+			}
 		}
 		}
 		if (!haveV6LinkLocal)
 		if (!haveV6LinkLocal)
 			addIP(InetAddress::makeIpv6LinkLocal(_mac));
 			addIP(InetAddress::makeIpv6LinkLocal(_mac));
 #else
 #else
 		for(std::set<InetAddress>::iterator i(myIps.begin());i!=myIps.end();++i) {
 		for(std::set<InetAddress>::iterator i(myIps.begin());i!=myIps.end();++i) {
-			if ((!i->isLinkLocal())&&(!allIps.count(*i)))
-				removeIP(*i);
+			if ((!i->isLinkLocal())&&(!allIps.count(*i))) {
+				for(std::set<InetAddress>::const_iterator i2(allIps.begin());i2!=allIps.end();++i2) {
+					if (i->sameNetworkAs(*i2)) {
+						removeIP(*i);
+						break;
+					}
+				}
+			}
 		}
 		}
 #endif
 #endif
 	}
 	}

+ 120 - 8
node/InetAddress.cpp

@@ -46,17 +46,51 @@ void InetAddress::set(const std::string &ip,unsigned int port)
 	memset(&_sa,0,sizeof(_sa));
 	memset(&_sa,0,sizeof(_sa));
 	if (ip.find(':') != std::string::npos) {
 	if (ip.find(':') != std::string::npos) {
 		_sa.sin6.sin6_family = AF_INET6;
 		_sa.sin6.sin6_family = AF_INET6;
-		_sa.sin6.sin6_port = htons((uint16_t)port);
+		_sa.sin6.sin6_port = Utils::hton((uint16_t)port);
 		if (inet_pton(AF_INET6,ip.c_str(),(void *)&(_sa.sin6.sin6_addr.s6_addr)) <= 0)
 		if (inet_pton(AF_INET6,ip.c_str(),(void *)&(_sa.sin6.sin6_addr.s6_addr)) <= 0)
 			_sa.saddr.sa_family = 0;
 			_sa.saddr.sa_family = 0;
 	} else {
 	} else {
 		_sa.sin.sin_family = AF_INET;
 		_sa.sin.sin_family = AF_INET;
-		_sa.sin.sin_port = htons((uint16_t)port);
+		_sa.sin.sin_port = Utils::hton((uint16_t)port);
 		if (inet_pton(AF_INET,ip.c_str(),(void *)&(_sa.sin.sin_addr.s_addr)) <= 0)
 		if (inet_pton(AF_INET,ip.c_str(),(void *)&(_sa.sin.sin_addr.s_addr)) <= 0)
 			_sa.saddr.sa_family = 0;
 			_sa.saddr.sa_family = 0;
 	}
 	}
 }
 }
 
 
+void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
+	throw()
+{
+	memset(&_sa,0,sizeof(_sa));
+	if (ipLen == 4) {
+		setV4();
+		memcpy(rawIpData(),ipBytes,4);
+		setPort(port);
+	} else if (ipLen == 16) {
+		setV6();
+		memcpy(rawIpData(),ipBytes,16);
+		setPort(port);
+	}
+}
+
+bool InetAddress::isLinkLocal() const
+	throw()
+{
+	if (_sa.saddr.sa_family == AF_INET)
+		return ((Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000);
+	else if (_sa.saddr.sa_family == AF_INET6) {
+		if (_sa.sin6.sin6_addr.s6_addr[0] != 0xfe) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[1] != 0x80) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[2] != 0x00) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[3] != 0x00) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[4] != 0x00) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[5] != 0x00) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[6] != 0x00) return false;
+		if (_sa.sin6.sin6_addr.s6_addr[7] != 0x00) return false;
+		return true;
+	}
+	return false;
+}
+
 std::string InetAddress::toString() const
 std::string InetAddress::toString() const
 {
 {
 	char buf[128],buf2[128];
 	char buf[128],buf2[128];
@@ -103,7 +137,6 @@ void InetAddress::fromString(const std::string &ipSlashPort)
 std::string InetAddress::toIpString() const
 std::string InetAddress::toIpString() const
 {
 {
 	char buf[128];
 	char buf[128];
-
 	switch(_sa.saddr.sa_family) {
 	switch(_sa.saddr.sa_family) {
 		case AF_INET:
 		case AF_INET:
 #ifdef __WINDOWS__
 #ifdef __WINDOWS__
@@ -124,10 +157,64 @@ std::string InetAddress::toIpString() const
 #endif
 #endif
 			break;
 			break;
 	}
 	}
-
 	return std::string();
 	return std::string();
 }
 }
 
 
+InetAddress InetAddress::netmask() const
+	throw()
+{
+	InetAddress r(*this);
+	switch(_sa.saddr.sa_family) {
+		case AF_INET:
+			r._sa.sin.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
+			break;
+		case AF_INET6: {
+			unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr;
+			signed int bitsLeft = (signed int)netmaskBits();
+			for(unsigned int i=0;i<16;++i) {
+				if (bitsLeft > 0) {
+					bf[i] = (unsigned char)((bitsLeft >= 8) ? 0xff : (0xff << (8 - bitsLeft)));
+					bitsLeft -= 8;
+				} else bf[i] = (unsigned char)0;
+			}
+		}	break;
+	}
+	return r;
+}
+
+bool InetAddress::sameNetworkAs(const InetAddress &ipnet) const
+	throw()
+{
+	if (_sa.saddr.sa_family != ipnet._sa.saddr.sa_family)
+		return false;
+
+	unsigned int bits = netmaskBits();
+	if (bits != ipnet.netmaskBits())
+		return false;
+	if (!bits)
+		return true;
+	switch(_sa.saddr.sa_family) {
+		case AF_INET:
+			if (bits >= 32) bits = 32;
+			break;
+		case AF_INET6:
+			if (bits >= 128) bits = 128;
+			break;
+		default:
+			return false;
+	}
+
+	const uint8_t *a = (const uint8_t *)rawIpData();
+	const uint8_t *b = (const uint8_t *)ipnet.rawIpData();
+	while (bits >= 8) {
+		if (*(a++) != *(b++))
+			return false;
+		bits -= 8;
+	}
+	bits = 8 - bits;
+	return ((*a >> bits) == (*b >> bits));
+}
+
 bool InetAddress::operator==(const InetAddress &a) const
 bool InetAddress::operator==(const InetAddress &a) const
 	throw()
 	throw()
 {
 {
@@ -151,19 +238,44 @@ bool InetAddress::operator<(const InetAddress &a) const
 		return true;
 		return true;
 	else if (_sa.saddr.sa_family == a._sa.saddr.sa_family) {
 	else if (_sa.saddr.sa_family == a._sa.saddr.sa_family) {
 		if (_sa.saddr.sa_family == AF_INET) {
 		if (_sa.saddr.sa_family == AF_INET) {
-			unsigned long x = ntohl(_sa.sin.sin_addr.s_addr);
-			unsigned long y = ntohl(a._sa.sin.sin_addr.s_addr);
+			unsigned long x = Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr);
+			unsigned long y = Utils::ntoh((uint32_t)a._sa.sin.sin_addr.s_addr);
 			if (x == y)
 			if (x == y)
-				return (ntohs(_sa.sin.sin_port) < ntohs(a._sa.sin.sin_port));
+				return (Utils::ntoh((uint16_t)_sa.sin.sin_port) < Utils::ntoh((uint16_t)a._sa.sin.sin_port));
 			else return (x < y);
 			else return (x < y);
 		} else if (_sa.saddr.sa_family == AF_INET6) {
 		} else if (_sa.saddr.sa_family == AF_INET6) {
 			int cmp = (int)memcmp(_sa.sin6.sin6_addr.s6_addr,a._sa.sin6.sin6_addr.s6_addr,16);
 			int cmp = (int)memcmp(_sa.sin6.sin6_addr.s6_addr,a._sa.sin6.sin6_addr.s6_addr,16);
 			if (cmp == 0)
 			if (cmp == 0)
-				return (ntohs(_sa.sin6.sin6_port) < ntohs(a._sa.sin6.sin6_port));
+				return (Utils::ntoh((uint16_t)_sa.sin6.sin6_port) < Utils::ntoh((uint16_t)a._sa.sin6.sin6_port));
 			else return (cmp < 0);
 			else return (cmp < 0);
 		} else return (memcmp(&_sa,&a._sa,sizeof(_sa)) < 0);
 		} else return (memcmp(&_sa,&a._sa,sizeof(_sa)) < 0);
 	}
 	}
 	return false;
 	return false;
 }
 }
 
 
+InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac)
+	throw()
+{
+	InetAddress ip;
+	ip._sa.saddr.sa_family = AF_INET6;
+	ip._sa.sin6.sin6_addr.s6_addr[0] = 0xfe;
+	ip._sa.sin6.sin6_addr.s6_addr[1] = 0x80;
+	ip._sa.sin6.sin6_addr.s6_addr[2] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[3] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[4] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[5] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[6] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[7] = 0x00;
+	ip._sa.sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd;
+	ip._sa.sin6.sin6_addr.s6_addr[9] = mac[1];
+	ip._sa.sin6.sin6_addr.s6_addr[10] = mac[2];
+	ip._sa.sin6.sin6_addr.s6_addr[11] = 0xff;
+	ip._sa.sin6.sin6_addr.s6_addr[12] = 0xfe;
+	ip._sa.sin6.sin6_addr.s6_addr[13] = mac[3];
+	ip._sa.sin6.sin6_addr.s6_addr[14] = mac[4];
+	ip._sa.sin6.sin6_addr.s6_addr[15] = mac[5];
+	ip._sa.sin6.sin6_port = Utils::hton((uint16_t)64);
+	return ip;
+}
+
 } // namespace ZeroTier
 } // namespace ZeroTier

+ 51 - 166
node/InetAddress.hpp

@@ -77,53 +77,14 @@ public:
 	 */
 	 */
 	static const InetAddress LO6;
 	static const InetAddress LO6;
 
 
-	InetAddress()
-		throw()
-	{
-		memset(&_sa,0,sizeof(_sa));
-	}
-
-	InetAddress(const InetAddress &a)
-		throw()
-	{
-		memcpy(&_sa,&a._sa,sizeof(_sa));
-	}
-
-	InetAddress(const struct sockaddr *sa)
-		throw()
-	{
-		this->set(sa);
-	}
-
-	InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port)
-		throw()
-	{
-		this->set(ipBytes,ipLen,port);
-	}
-
-	InetAddress(const uint32_t ipv4,unsigned int port)
-		throw()
-	{
-		this->set(&ipv4,4,port);
-	}
-
-	InetAddress(const std::string &ip,unsigned int port)
-		throw()
-	{
-		this->set(ip,port);
-	}
-
-	InetAddress(const std::string &ipSlashPort)
-		throw()
-	{
-		this->fromString(ipSlashPort);
-	}
-
-	InetAddress(const char *ipSlashPort)
-		throw()
-	{
-		this->fromString(std::string(ipSlashPort));
-	}
+	InetAddress() throw() { memset(&_sa,0,sizeof(_sa)); }
+	InetAddress(const InetAddress &a) throw() { memcpy(&_sa,&a._sa,sizeof(_sa)); }
+	InetAddress(const struct sockaddr *sa) throw() { this->set(sa); }
+	InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) throw() { this->set(ipBytes,ipLen,port); }
+	InetAddress(const uint32_t ipv4,unsigned int port) throw() { this->set(&ipv4,4,port); }
+	InetAddress(const std::string &ip,unsigned int port) throw() { this->set(ip,port); }
+	InetAddress(const std::string &ipSlashPort) throw() { this->fromString(ipSlashPort); }
+	InetAddress(const char *ipSlashPort) throw() { this->fromString(std::string(ipSlashPort)); }
 
 
 	inline InetAddress &operator=(const InetAddress &a)
 	inline InetAddress &operator=(const InetAddress &a)
 		throw()
 		throw()
@@ -141,15 +102,9 @@ public:
 		throw()
 		throw()
 	{
 	{
 		switch(sa->sa_family) {
 		switch(sa->sa_family) {
-			case AF_INET:
-				memcpy(&_sa.sin,sa,sizeof(struct sockaddr_in));
-				break;
-			case AF_INET6:
-				memcpy(&_sa.sin6,sa,sizeof(struct sockaddr_in6));
-				break;
-			default:
-				_sa.saddr.sa_family = 0;
-				break;
+			case AF_INET: memcpy(&_sa.sin,sa,sizeof(struct sockaddr_in)); break;
+			case AF_INET6: memcpy(&_sa.sin6,sa,sizeof(struct sockaddr_in6)); break;
+			default: memset(&_sa,0,sizeof(_sa)); break;
 		}
 		}
 	}
 	}
 
 
@@ -169,20 +124,8 @@ public:
 	 * @param ipLen Length of IP address: 4 or 16
 	 * @param ipLen Length of IP address: 4 or 16
 	 * @param port Port number or 0 for none
 	 * @param port Port number or 0 for none
 	 */
 	 */
-	inline void set(const void *ipBytes,unsigned int ipLen,unsigned int port)
-		throw()
-	{
-		_sa.saddr.sa_family = 0;
-		if (ipLen == 4) {
-			setV4();
-			memcpy(rawIpData(),ipBytes,4);
-			setPort(port);
-		} else if (ipLen == 16) {
-			setV6();
-			memcpy(rawIpData(),ipBytes,16);
-			setPort(port);
-		}
-	}
+	void set(const void *ipBytes,unsigned int ipLen,unsigned int port)
+		throw();
 
 
 	/**
 	/**
 	 * Set the port component
 	 * Set the port component
@@ -193,32 +136,16 @@ public:
 		throw()
 		throw()
 	{
 	{
 		if (_sa.saddr.sa_family == AF_INET)
 		if (_sa.saddr.sa_family == AF_INET)
-			_sa.sin.sin_port = htons((uint16_t)port);
+			_sa.sin.sin_port = Utils::hton((uint16_t)port);
 		else if (_sa.saddr.sa_family == AF_INET6)
 		else if (_sa.saddr.sa_family == AF_INET6)
-			_sa.sin6.sin6_port = htons((uint16_t)port);
+			_sa.sin6.sin6_port = Utils::hton((uint16_t)port);
 	}
 	}
 
 
 	/**
 	/**
 	 * @return True if this is a link-local IP address
 	 * @return True if this is a link-local IP address
 	 */
 	 */
-	inline bool isLinkLocal() const
-		throw()
-	{
-		if (_sa.saddr.sa_family == AF_INET)
-			return ((Utils::ntoh((uint32_t)_sa.sin.sin_addr.s_addr) & 0xffff0000) == 0xa9fe0000);
-		else if (_sa.saddr.sa_family == AF_INET6) {
-			if (_sa.sin6.sin6_addr.s6_addr[0] != 0xfe) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[1] != 0x80) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[2] != 0x00) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[3] != 0x00) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[4] != 0x00) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[5] != 0x00) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[6] != 0x00) return false;
-			if (_sa.sin6.sin6_addr.s6_addr[7] != 0x00) return false;
-			return true;
-		}
-		return false;
-	}
+	bool isLinkLocal() const
+		throw();
 
 
 	/**
 	/**
 	 * @return ASCII IP/port format representation
 	 * @return ASCII IP/port format representation
@@ -242,12 +169,10 @@ public:
 		throw()
 		throw()
 	{
 	{
 		switch(_sa.saddr.sa_family) {
 		switch(_sa.saddr.sa_family) {
-			case AF_INET:
-				return ntohs(_sa.sin.sin_port);
-			case AF_INET6:
-				return ntohs(_sa.sin6.sin6_port);
+			case AF_INET: return Utils::ntoh((uint16_t)_sa.sin.sin_port);
+			case AF_INET6: return Utils::ntoh((uint16_t)_sa.sin6.sin6_port);
+			default: return 0;
 		}
 		}
-		return 0;
 	}
 	}
 
 
 	/**
 	/**
@@ -259,36 +184,13 @@ public:
 	 *
 	 *
 	 * @return Netmask bits
 	 * @return Netmask bits
 	 */
 	 */
-	inline unsigned int netmaskBits() const
-		throw()
-	{
-		return port();
-	}
+	inline unsigned int netmaskBits() const throw() { return port(); }
 
 
 	/**
 	/**
 	 * Construct a full netmask as an InetAddress
 	 * Construct a full netmask as an InetAddress
 	 */
 	 */
-	inline InetAddress netmask() const
-		throw()
-	{
-		InetAddress r(*this);
-		switch(_sa.saddr.sa_family) {
-			case AF_INET:
-				r._sa.sin.sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits())));
-				break;
-			case AF_INET6: {
-				unsigned char *bf = (unsigned char *)r._sa.sin6.sin6_addr.s6_addr;
-				signed int bitsLeft = (signed int)netmaskBits();
-				for(unsigned int i=0;i<16;++i) {
-					if (bitsLeft > 0) {
-						bf[i] = (unsigned char)((bitsLeft >= 8) ? 0xff : (0xff << (8 - bitsLeft)));
-						bitsLeft -= 8;
-					} else bf[i] = (unsigned char)0;
-				}
-			}	break;
-		}
-		return r;
-	}
+	InetAddress netmask() const
+		throw();
 
 
 	/**
 	/**
 	 * @return True if this is an IPv4 address
 	 * @return True if this is an IPv4 address
@@ -327,17 +229,17 @@ public:
 	inline unsigned int saddrLen() const
 	inline unsigned int saddrLen() const
 		throw()
 		throw()
 	{
 	{
-		return (isV4() ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
+		switch(_sa.saddr.sa_family) {
+			case AF_INET: return sizeof(struct sockaddr_in);
+			case AF_INET6: return sizeof(struct sockaddr_in6);
+			default: return 0;
+		}
 	}
 	}
 
 
 	/**
 	/**
 	 * @return Combined length of internal structure, room for either V4 or V6
 	 * @return Combined length of internal structure, room for either V4 or V6
 	 */
 	 */
-	inline unsigned int saddrSpaceLen() const
-		throw()
-	{
-		return sizeof(_sa);
-	}
+	inline unsigned int saddrSpaceLen() const throw() { return sizeof(_sa); }
 
 
 	/**
 	/**
 	 * @return Raw sockaddr_in structure (valid if IPv4)
 	 * @return Raw sockaddr_in structure (valid if IPv4)
@@ -356,7 +258,7 @@ public:
 	inline const void *rawIpData() const throw() { return ((_sa.saddr.sa_family == AF_INET) ? (void *)(&(_sa.sin.sin_addr.s_addr)) : (void *)_sa.sin6.sin6_addr.s6_addr); }
 	inline const void *rawIpData() const throw() { return ((_sa.saddr.sa_family == AF_INET) ? (void *)(&(_sa.sin.sin_addr.s_addr)) : (void *)_sa.sin6.sin6_addr.s6_addr); }
 
 
 	/**
 	/**
-	 * Compare only the IP portions of addresses, ignoring port
+	 * Compare only the IP portions of addresses, ignoring port/netmask
 	 *
 	 *
 	 * @param a Address to compare
 	 * @param a Address to compare
 	 * @return True if both addresses are of the same (valid) type and their IPs match
 	 * @return True if both addresses are of the same (valid) type and their IPs match
@@ -375,55 +277,38 @@ public:
 		return false;
 		return false;
 	}
 	}
 
 
-	bool operator==(const InetAddress &a) const throw();
-	inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); }
-	bool operator<(const InetAddress &a) const throw();
-	inline bool operator>(const InetAddress &a) const throw() { return (a < *this); }
-	inline bool operator<=(const InetAddress &a) const throw() { return !(a < *this); }
-	inline bool operator>=(const InetAddress &a) const throw() { return !(*this < a); }
-
 	/**
 	/**
-	 * @return True if address family is non-zero
+	 * Compare IP/netmask with another IP/netmask
+	 *
+	 * @param ipnet IP/netmask to compare with
+	 * @return True if [netmask] bits match
 	 */
 	 */
-	inline operator bool() const throw() { return ((_sa.saddr.sa_family == AF_INET)||(_sa.saddr.sa_family == AF_INET6)); }
+	bool sameNetworkAs(const InetAddress &ipnet) const
+		throw();
 
 
 	/**
 	/**
 	 * Set to null/zero
 	 * Set to null/zero
 	 */
 	 */
-	inline void zero()
-		throw()
-	{
-		_sa.saddr.sa_family = 0;
-	}
+	inline void zero() throw() { memset(&_sa,0,sizeof(_sa)); }
+
+	/**
+	 * @return True if address family is non-zero
+	 */
+	inline operator bool() const throw() { return ((_sa.saddr.sa_family == AF_INET)||(_sa.saddr.sa_family == AF_INET6)); }
+
+	bool operator==(const InetAddress &a) const throw();
+	inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); }
+	bool operator<(const InetAddress &a) const throw();
+	inline bool operator>(const InetAddress &a) const throw() { return (a < *this); }
+	inline bool operator<=(const InetAddress &a) const throw() { return !(a < *this); }
+	inline bool operator>=(const InetAddress &a) const throw() { return !(*this < a); }
 
 
 	/**
 	/**
 	 * @param mac MAC address seed
 	 * @param mac MAC address seed
 	 * @return IPv6 link-local address
 	 * @return IPv6 link-local address
 	 */
 	 */
-	static inline InetAddress makeIpv6LinkLocal(const MAC &mac)
-		throw()
-	{
-		InetAddress ip;
-		ip._sa.saddr.sa_family = AF_INET6;
-		ip._sa.sin6.sin6_addr.s6_addr[0] = 0xfe;
-		ip._sa.sin6.sin6_addr.s6_addr[1] = 0x80;
-		ip._sa.sin6.sin6_addr.s6_addr[2] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[3] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[4] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[5] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[6] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[7] = 0x00;
-		ip._sa.sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd;
-		ip._sa.sin6.sin6_addr.s6_addr[9] = mac[1];
-		ip._sa.sin6.sin6_addr.s6_addr[10] = mac[2];
-		ip._sa.sin6.sin6_addr.s6_addr[11] = 0xff;
-		ip._sa.sin6.sin6_addr.s6_addr[12] = 0xfe;
-		ip._sa.sin6.sin6_addr.s6_addr[13] = mac[3];
-		ip._sa.sin6.sin6_addr.s6_addr[14] = mac[4];
-		ip._sa.sin6.sin6_addr.s6_addr[15] = mac[5];
-		ip._sa.sin6.sin6_port = Utils::hton((uint16_t)64);
-		return ip;
-	}
+	static InetAddress makeIpv6LinkLocal(const MAC &mac)
+		throw();
 
 
 private:
 private:
 	union {
 	union {