This commit is contained in:
Adam Ierymenko 2017-07-06 16:11:11 -07:00
parent 53728b79b4
commit d2415dee00
32 changed files with 620 additions and 678 deletions

View file

@ -141,20 +141,9 @@ public:
/**
* @return Hexadecimal string
*/
inline std::string toString() const
inline char *toString(char buf[11]) const
{
char buf[16];
Utils::ztsnprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a);
return std::string(buf);
};
/**
* @param buf Buffer to fill
* @param len Length of buffer
*/
inline void toString(char *buf,unsigned int len) const
{
Utils::ztsnprintf(buf,len,"%.10llx",(unsigned long long)_a);
return Utils::hex10(_a,buf);
}
/**

View file

@ -57,6 +57,7 @@ void CertificateOfMembership::setQualifier(uint64_t id,uint64_t value,uint64_t m
std::string CertificateOfMembership::toString() const
{
char tmp[ZT_NETWORK_COM_MAX_QUALIFIERS * 32];
std::string s;
s.append("1:"); // COM_UINT64_ED25519
@ -69,7 +70,7 @@ std::string CertificateOfMembership::toString() const
buf[ptr++] = Utils::hton(_qualifiers[i].value);
buf[ptr++] = Utils::hton(_qualifiers[i].maxDelta);
}
s.append(Utils::hex(buf,ptr * sizeof(uint64_t)));
s.append(Utils::hex(buf,ptr * sizeof(uint64_t),tmp));
delete [] buf;
} catch ( ... ) {
delete [] buf;
@ -78,11 +79,11 @@ std::string CertificateOfMembership::toString() const
s.push_back(':');
s.append(_signedBy.toString());
s.append(_signedBy.toString(tmp));
if (_signedBy) {
s.push_back(':');
s.append(Utils::hex(_signature.data,(unsigned int)_signature.size()));
s.append(Utils::hex(_signature.data,(unsigned int)_signature.size(),tmp));
}
return s;

View file

@ -391,8 +391,7 @@ public:
inline bool add(const char *key,uint64_t value)
{
char tmp[32];
Utils::ztsnprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value);
return this->add(key,tmp,-1);
return this->add(key,Utils::hex(value,tmp),-1);
}
/**
@ -401,8 +400,7 @@ public:
inline bool add(const char *key,const Address &a)
{
char tmp[32];
Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt());
return this->add(key,tmp,-1);
return this->add(key,Utils::hex(a.toInt(),tmp),-1);
}
/**

View file

@ -136,19 +136,23 @@ bool Identity::locallyValidate() const
(digest[63] == addrb[4]));
}
std::string Identity::toString(bool includePrivate) const
char *Identity::toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const
{
std::string r;
r.append(_address.toString());
r.append(":0:"); // 0 == ZT_OBJECT_TYPE_IDENTITY
r.append(Utils::hex(_publicKey.data,(unsigned int)_publicKey.size()));
char *p = buf;
Utils::hex10(_address.toInt(),p);
p += 10;
*(p++) = ':';
*(p++) = '0';
*(p++) = ':';
Utils::hex(_publicKey.data,ZT_C25519_PUBLIC_KEY_LEN,p);
p += ZT_C25519_PUBLIC_KEY_LEN * 2;
if ((_privateKey)&&(includePrivate)) {
r.push_back(':');
r.append(Utils::hex(_privateKey->data,(unsigned int)_privateKey->size()));
*(p++) = ':';
Utils::hex(_privateKey->data,ZT_C25519_PRIVATE_KEY_LEN,p);
p += ZT_C25519_PRIVATE_KEY_LEN * 2;
}
return r;
*(p++) = (char)0;
return buf;
}
bool Identity::fromString(const char *str)
@ -157,7 +161,7 @@ bool Identity::fromString(const char *str)
return false;
char *saveptr = (char *)0;
char tmp[1024];
char tmp[ZT_IDENTITY_STRING_BUFFER_LENGTH];
if (!Utils::scopy(tmp,sizeof(tmp),str))
return false;

View file

@ -29,7 +29,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "Constants.hpp"
#include "Array.hpp"
@ -39,6 +38,8 @@
#include "Buffer.hpp"
#include "SHA512.hpp"
#define ZT_IDENTITY_STRING_BUFFER_LENGTH 384
namespace ZeroTier {
/**
@ -66,16 +67,7 @@ public:
{
}
Identity(const char *str)
throw(std::invalid_argument) :
_privateKey((C25519::Private *)0)
{
if (!fromString(str))
throw std::invalid_argument(std::string("invalid string-serialized identity: ") + str);
}
Identity(const std::string &str)
throw(std::invalid_argument) :
Identity(const char *str) :
_privateKey((C25519::Private *)0)
{
if (!fromString(str))
@ -277,9 +269,10 @@ public:
* Serialize to a more human-friendly string
*
* @param includePrivate If true, include private key (if it exists)
* @param buf Buffer to store string
* @return ASCII string representation of identity
*/
std::string toString(bool includePrivate) const;
char *toString(bool includePrivate,char buf[ZT_IDENTITY_STRING_BUFFER_LENGTH]) const;
/**
* Deserialize a human-friendly string
@ -291,7 +284,6 @@ public:
* @return True if deserialization appears successful
*/
bool fromString(const char *str);
inline bool fromString(const std::string &str) { return fromString(str.c_str()); }
/**
* @return C25519 public key

View file

@ -5,7 +5,7 @@
* 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 3 of the License, or
* (at your option) any later version.
* (at your oion) 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
@ -40,7 +40,6 @@ const InetAddress InetAddress::LO4((const void *)("\x7f\x00\x00\x01"),4,0);
const InetAddress InetAddress::LO6((const void *)("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"),16,0);
InetAddress::IpScope InetAddress::ipScope() const
throw()
{
switch(ss_family) {
@ -111,27 +110,7 @@ InetAddress::IpScope InetAddress::ipScope() const
return IP_SCOPE_NONE;
}
void InetAddress::set(const std::string &ip,unsigned int port)
throw()
{
memset(this,0,sizeof(InetAddress));
if (ip.find(':') != std::string::npos) {
struct sockaddr_in6 *sin6 = reinterpret_cast<struct sockaddr_in6 *>(this);
ss_family = AF_INET6;
sin6->sin6_port = Utils::hton((uint16_t)port);
if (inet_pton(AF_INET6,ip.c_str(),(void *)&(sin6->sin6_addr.s6_addr)) <= 0)
memset(this,0,sizeof(InetAddress));
} else if (ip.find('.') != std::string::npos) {
struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(this);
ss_family = AF_INET;
sin->sin_port = Utils::hton((uint16_t)port);
if (inet_pton(AF_INET,ip.c_str(),(void *)&(sin->sin_addr.s_addr)) <= 0)
memset(this,0,sizeof(InetAddress));
}
}
void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
throw()
{
memset(this,0,sizeof(InetAddress));
if (ipLen == 4) {
@ -147,90 +126,98 @@ void InetAddress::set(const void *ipBytes,unsigned int ipLen,unsigned int port)
}
}
std::string InetAddress::toString() const
char *InetAddress::toString(char buf[64]) const
{
char buf[128];
switch(ss_family) {
case AF_INET:
Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d",
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[3],
(int)Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port))
);
return std::string(buf);
case AF_INET6:
Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d",
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[3]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[4]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[5]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[6]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[7]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[8]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[9]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[10]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[11]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[12]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[13]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[14]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[15]),
(int)Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port))
);
return std::string(buf);
char *p = toIpString(buf);
if (*p) {
while (*p) ++p;
*(p++) = '/';
Utils::decimal(port(),p);
}
return std::string();
return buf;
}
std::string InetAddress::toIpString() const
char *InetAddress::toIpString(char buf[64]) const
{
char buf[128];
switch(ss_family) {
case AF_INET:
Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d",
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[3]
);
return std::string(buf);
case AF_INET6:
Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[3]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[4]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[5]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[6]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[7]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[8]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[9]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[10]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[11]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[12]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[13]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[14]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[15])
);
return std::string(buf);
case AF_INET: {
const uint8_t *a = reinterpret_cast<const uint8_t *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr));
char *p = buf;
for(int i=0;;++i) {
Utils::decimal((unsigned long)a[i],p);
if (i != 3) {
while (*p) ++p;
*(p++) = '.';
} else break;
}
} break;
case AF_INET6: {
uint16_t a[8];
memcpy(a,reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
char *p = buf;
for(int i=0;i<8;++i) {
Utils::hex(Utils::ntoh(a[i]),p);
p[4] = (i == 7) ? (char)0 : ':';
p += 5;
}
} break;
default:
buf[0] = (char)0;
break;
}
return std::string();
return buf;
}
void InetAddress::fromString(const std::string &ipSlashPort)
bool InetAddress::fromString(const char *ipSlashPort)
{
const std::size_t slashAt = ipSlashPort.find('/');
if (slashAt == std::string::npos) {
set(ipSlashPort,0);
char buf[64];
memset(this,0,sizeof(InetAddress));
if (!*ipSlashPort)
return true;
if (!Utils::scopy(buf,sizeof(buf),ipSlashPort))
return false;
char *portAt = buf;
while ((*portAt)&&(*portAt != '/'))
++portAt;
unsigned int port = 0;
if (*portAt) {
*(portAt++) = (char)0;
port = Utils::strToUInt(portAt) & 0xffff;
}
if (strchr(buf,':')) {
uint16_t a[8];
unsigned int b = 0;
char *saveptr = (char *)0;
for(char *s=Utils::stok(buf,":",&saveptr);((s)&&(b<8));s=Utils::stok((char *)0,":",&saveptr))
a[b++] = Utils::hton((uint16_t)(Utils::hexStrToUInt(s) & 0xffff));
struct sockaddr_in6 *const in6 = reinterpret_cast<struct sockaddr_in6 *>(this);
in6->sin6_family = AF_INET6;
memcpy(in6->sin6_addr.s6_addr,a,16);
in6->sin6_port = Utils::hton((uint16_t)port);
return true;
} else if (strchr(buf,'.')) {
uint8_t a[4];
unsigned int b = 0;
char *saveptr = (char *)0;
for(char *s=Utils::stok(buf,".",&saveptr);((s)&&(b<4));s=Utils::stok((char *)0,".",&saveptr))
a[b++] = (uint8_t)(Utils::strToUInt(s) & 0xff);
struct sockaddr_in *const in = reinterpret_cast<struct sockaddr_in *>(this);
in->sin_family = AF_INET;
memcpy(&(in->sin_addr.s_addr),a,4);
in->sin_port = Utils::hton((uint16_t)port);
return true;
} else {
long p = strtol(ipSlashPort.substr(slashAt+1).c_str(),(char **)0,10);
if ((p > 0)&&(p <= 0xffff))
set(ipSlashPort.substr(0,slashAt),(unsigned int)p);
else set(ipSlashPort.substr(0,slashAt),0);
return false;
}
}
@ -244,14 +231,13 @@ InetAddress InetAddress::netmask() const
case AF_INET6: {
uint64_t nm[2];
const unsigned int bits = netmaskBits();
if(bits) {
nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
}
else {
nm[0] = 0;
nm[1] = 0;
}
if(bits) {
nm[0] = Utils::hton((uint64_t)((bits >= 64) ? 0xffffffffffffffffULL : (0xffffffffffffffffULL << (64 - bits))));
nm[1] = Utils::hton((uint64_t)((bits <= 64) ? 0ULL : (0xffffffffffffffffULL << (128 - bits))));
} else {
nm[0] = 0;
nm[1] = 0;
}
memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,nm,16);
} break;
}
@ -338,7 +324,6 @@ bool InetAddress::containsAddress(const InetAddress &addr) const
}
bool InetAddress::isNetwork() const
throw()
{
switch(ss_family) {
case AF_INET: {
@ -371,7 +356,6 @@ bool InetAddress::isNetwork() const
}
bool InetAddress::operator==(const InetAddress &a) const
throw()
{
if (ss_family == a.ss_family) {
switch(ss_family) {
@ -395,7 +379,6 @@ bool InetAddress::operator==(const InetAddress &a) const
}
bool InetAddress::operator<(const InetAddress &a) const
throw()
{
if (ss_family < a.ss_family)
return true;

View file

@ -31,8 +31,6 @@
#include <string.h>
#include <stdint.h>
#include <string>
#include "Constants.hpp"
#include "../include/ZeroTierOne.h"
#include "Utils.hpp"
@ -85,25 +83,22 @@ struct InetAddress : public sockaddr_storage
IP_SCOPE_PRIVATE = 7 // 10.x.x.x, 192.168.x.x, etc.
};
InetAddress() throw() { memset(this,0,sizeof(InetAddress)); }
InetAddress(const InetAddress &a) throw() { memcpy(this,&a,sizeof(InetAddress)); }
InetAddress(const InetAddress *a) throw() { memcpy(this,a,sizeof(InetAddress)); }
InetAddress(const struct sockaddr_storage &ss) throw() { *this = ss; }
InetAddress(const struct sockaddr_storage *ss) throw() { *this = ss; }
InetAddress(const struct sockaddr &sa) throw() { *this = sa; }
InetAddress(const struct sockaddr *sa) throw() { *this = sa; }
InetAddress(const struct sockaddr_in &sa) throw() { *this = sa; }
InetAddress(const struct sockaddr_in *sa) throw() { *this = sa; }
InetAddress(const struct sockaddr_in6 &sa) throw() { *this = sa; }
InetAddress(const struct sockaddr_in6 *sa) throw() { *this = 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() { memset(this,0,sizeof(InetAddress)); }
InetAddress(const InetAddress &a) { memcpy(this,&a,sizeof(InetAddress)); }
InetAddress(const InetAddress *a) { memcpy(this,a,sizeof(InetAddress)); }
InetAddress(const struct sockaddr_storage &ss) { *this = ss; }
InetAddress(const struct sockaddr_storage *ss) { *this = ss; }
InetAddress(const struct sockaddr &sa) { *this = sa; }
InetAddress(const struct sockaddr *sa) { *this = sa; }
InetAddress(const struct sockaddr_in &sa) { *this = sa; }
InetAddress(const struct sockaddr_in *sa) { *this = sa; }
InetAddress(const struct sockaddr_in6 &sa) { *this = sa; }
InetAddress(const struct sockaddr_in6 *sa) { *this = sa; }
InetAddress(const void *ipBytes,unsigned int ipLen,unsigned int port) { this->set(ipBytes,ipLen,port); }
InetAddress(const uint32_t ipv4,unsigned int port) { this->set(&ipv4,4,port); }
InetAddress(const char *ipSlashPort) { this->fromString(ipSlashPort); }
inline InetAddress &operator=(const InetAddress &a)
throw()
{
if (&a != this)
memcpy(this,&a,sizeof(InetAddress));
@ -111,7 +106,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const InetAddress *a)
throw()
{
if (a != this)
memcpy(this,a,sizeof(InetAddress));
@ -119,7 +113,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_storage &ss)
throw()
{
if (reinterpret_cast<const InetAddress *>(&ss) != this)
memcpy(this,&ss,sizeof(InetAddress));
@ -127,7 +120,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_storage *ss)
throw()
{
if (reinterpret_cast<const InetAddress *>(ss) != this)
memcpy(this,ss,sizeof(InetAddress));
@ -135,7 +127,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_in &sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -145,7 +136,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_in *sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -155,7 +145,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_in6 &sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -165,7 +154,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr_in6 *sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -175,7 +163,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr &sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(&sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -192,7 +179,6 @@ struct InetAddress : public sockaddr_storage
}
inline InetAddress &operator=(const struct sockaddr *sa)
throw()
{
if (reinterpret_cast<const InetAddress *>(sa) != this) {
memset(this,0,sizeof(InetAddress));
@ -211,17 +197,7 @@ struct InetAddress : public sockaddr_storage
/**
* @return IP scope classification (e.g. loopback, link-local, private, global)
*/
IpScope ipScope() const
throw();
/**
* Set from a string-format IP and a port
*
* @param ip IP address in V4 or V6 ASCII notation
* @param port Port or 0 for none
*/
void set(const std::string &ip,unsigned int port)
throw();
IpScope ipScope() const;
/**
* Set from a raw IP and port number
@ -230,8 +206,7 @@ struct InetAddress : public sockaddr_storage
* @param ipLen Length of IP address: 4 or 16
* @param port Port number or 0 for none
*/
void set(const void *ipBytes,unsigned int ipLen,unsigned int port)
throw();
void set(const void *ipBytes,unsigned int ipLen,unsigned int port);
/**
* Set the port component
@ -272,23 +247,23 @@ struct InetAddress : public sockaddr_storage
/**
* @return ASCII IP/port format representation
*/
std::string toString() const;
char *toString(char buf[64]) const;
/**
* @return IP portion only, in ASCII string format
*/
std::string toIpString() const;
char *toIpString(char buf[64]) const;
/**
* @param ipSlashPort ASCII IP/port format notation
* @param ipSlashPort IP/port (port is optional, will be 0 if not included)
* @return True if address appeared to be valid
*/
void fromString(const std::string &ipSlashPort);
bool fromString(const char *ipSlashPort);
/**
* @return Port or 0 if no port component defined
*/
inline unsigned int port() const
throw()
{
switch(ss_family) {
case AF_INET: return Utils::ntoh((uint16_t)(reinterpret_cast<const struct sockaddr_in *>(this)->sin_port));
@ -306,7 +281,7 @@ struct InetAddress : public sockaddr_storage
*
* @return Netmask bits
*/
inline unsigned int netmaskBits() const throw() { return port(); }
inline unsigned int netmaskBits() const { return port(); }
/**
* @return True if netmask bits is valid for the address type
@ -329,7 +304,7 @@ struct InetAddress : public sockaddr_storage
*
* @return Gateway metric
*/
inline unsigned int metric() const throw() { return port(); }
inline unsigned int metric() const { return port(); }
/**
* Construct a full netmask as an InetAddress
@ -376,12 +351,12 @@ struct InetAddress : public sockaddr_storage
/**
* @return True if this is an IPv4 address
*/
inline bool isV4() const throw() { return (ss_family == AF_INET); }
inline bool isV4() const { return (ss_family == AF_INET); }
/**
* @return True if this is an IPv6 address
*/
inline bool isV6() const throw() { return (ss_family == AF_INET6); }
inline bool isV6() const { return (ss_family == AF_INET6); }
/**
* @return pointer to raw address bytes or NULL if not available
@ -454,7 +429,7 @@ struct InetAddress : public sockaddr_storage
/**
* Set to null/zero
*/
inline void zero() throw() { memset(this,0,sizeof(InetAddress)); }
inline void zero() { memset(this,0,sizeof(InetAddress)); }
/**
* Check whether this is a network/route rather than an IP assignment
@ -464,8 +439,7 @@ struct InetAddress : public sockaddr_storage
*
* @return True if everything after netmask bits is zero
*/
bool isNetwork() const
throw();
bool isNetwork() const;
/**
* @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP
@ -494,7 +468,7 @@ struct InetAddress : public sockaddr_storage
/**
* @return True if address family is non-zero
*/
inline operator bool() const throw() { return (ss_family != 0); }
inline operator bool() const { return (ss_family != 0); }
template<unsigned int C>
inline void serialize(Buffer<C> &b) const
@ -552,12 +526,12 @@ struct InetAddress : public sockaddr_storage
return (p - startAt);
}
bool operator==(const InetAddress &a) const throw();
bool operator<(const InetAddress &a) const throw();
inline bool operator!=(const InetAddress &a) const throw() { return !(*this == a); }
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); }
bool operator==(const InetAddress &a) const;
bool operator<(const InetAddress &a) const;
inline bool operator!=(const InetAddress &a) const { return !(*this == a); }
inline bool operator>(const InetAddress &a) const { return (a < *this); }
inline bool operator<=(const InetAddress &a) const { return !(a < *this); }
inline bool operator>=(const InetAddress &a) const { return !(*this < a); }
/**
* @param mac MAC address seed

View file

@ -44,30 +44,24 @@ namespace ZeroTier {
class MAC
{
public:
MAC() throw() : _m(0ULL) {}
MAC(const MAC &m) throw() : _m(m._m) {}
MAC() : _m(0ULL) {}
MAC(const MAC &m) : _m(m._m) {}
MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) throw() :
MAC(const unsigned char a,const unsigned char b,const unsigned char c,const unsigned char d,const unsigned char e,const unsigned char f) :
_m( ((((uint64_t)a) & 0xffULL) << 40) |
((((uint64_t)b) & 0xffULL) << 32) |
((((uint64_t)c) & 0xffULL) << 24) |
((((uint64_t)d) & 0xffULL) << 16) |
((((uint64_t)e) & 0xffULL) << 8) |
(((uint64_t)f) & 0xffULL) ) {}
MAC(const char *s) throw() { fromString(s); }
MAC(const std::string &s) throw() { fromString(s.c_str()); }
MAC(const void *bits,unsigned int len) throw() { setTo(bits,len); }
MAC(const Address &ztaddr,uint64_t nwid) throw() { fromAddress(ztaddr,nwid); }
MAC(const uint64_t m) throw() : _m(m & 0xffffffffffffULL) {}
MAC(const void *bits,unsigned int len) { setTo(bits,len); }
MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); }
MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {}
/**
* @return MAC in 64-bit integer
*/
inline uint64_t toInt() const throw() { return _m; }
inline uint64_t toInt() const { return _m; }
/**
* Set MAC to zero
@ -77,14 +71,13 @@ public:
/**
* @return True if MAC is non-zero
*/
inline operator bool() const throw() { return (_m != 0ULL); }
inline operator bool() const { return (_m != 0ULL); }
/**
* @param bits Raw MAC in big-endian byte order
* @param len Length, must be >= 6 or result is zero
*/
inline void setTo(const void *bits,unsigned int len)
throw()
{
if (len < 6) {
_m = 0ULL;
@ -104,7 +97,6 @@ public:
* @param len Length of buffer, must be >= 6 or nothing is copied
*/
inline void copyTo(void *buf,unsigned int len) const
throw()
{
if (len < 6)
return;
@ -124,7 +116,6 @@ public:
*/
template<unsigned int C>
inline void appendTo(Buffer<C> &b) const
throw(std::out_of_range)
{
unsigned char *p = (unsigned char *)b.appendField(6);
*(p++) = (unsigned char)((_m >> 40) & 0xff);
@ -138,48 +129,17 @@ public:
/**
* @return True if this is broadcast (all 0xff)
*/
inline bool isBroadcast() const throw() { return (_m == 0xffffffffffffULL); }
inline bool isBroadcast() const { return (_m == 0xffffffffffffULL); }
/**
* @return True if this is a multicast MAC
*/
inline bool isMulticast() const throw() { return ((_m & 0x010000000000ULL) != 0ULL); }
inline bool isMulticast() const { return ((_m & 0x010000000000ULL) != 0ULL); }
/**
* @param True if this is a locally-administered MAC
*/
inline bool isLocallyAdministered() const throw() { return ((_m & 0x020000000000ULL) != 0ULL); }
/**
* @param s Hex MAC, with or without : delimiters
*/
inline void fromString(const char *s)
{
char tmp[8];
for(int i=0;i<6;++i)
tmp[i] = (char)0;
Utils::unhex(s,tmp,6);
setTo(tmp,6);
}
/**
* @return MAC address in standard :-delimited hex format
*/
inline std::string toString() const
{
char tmp[24];
toString(tmp,sizeof(tmp));
return std::string(tmp);
}
/**
* @param buf Buffer to contain human-readable MAC
* @param len Length of buffer
*/
inline void toString(char *buf,unsigned int len) const
{
Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]);
}
inline bool isLocallyAdministered() const { return ((_m & 0x020000000000ULL) != 0ULL); }
/**
* Set this MAC to a MAC derived from an address and a network ID
@ -188,7 +148,6 @@ public:
* @param nwid 64-bit network ID
*/
inline void fromAddress(const Address &ztaddr,uint64_t nwid)
throw()
{
uint64_t m = ((uint64_t)firstOctetForNetwork(nwid)) << 40;
m |= ztaddr.toInt(); // a is 40 bits
@ -208,7 +167,6 @@ public:
* @param nwid Network ID
*/
inline Address toAddress(uint64_t nwid) const
throw()
{
uint64_t a = _m & 0xffffffffffULL; // least significant 40 bits of MAC are formed from address
a ^= ((nwid >> 8) & 0xff) << 32; // ... XORed with bits 8-48 of the nwid in little-endian byte order, so unmask it
@ -224,7 +182,6 @@ public:
* @return First octet of MAC for this network
*/
static inline unsigned char firstOctetForNetwork(uint64_t nwid)
throw()
{
unsigned char a = ((unsigned char)(nwid & 0xfe) | 0x02); // locally administered, not multicast, from LSB of network ID
return ((a == 0x52) ? 0x32 : a); // blacklist 0x52 since it's used by KVM, libvirt, and other popular virtualization engines... seems de-facto standard on Linux
@ -239,29 +196,27 @@ public:
/**
* @return 6, which is the number of bytes in a MAC, for container compliance
*/
inline unsigned int size() const throw() { return 6; }
inline unsigned int size() const { return 6; }
inline unsigned long hashCode() const throw() { return (unsigned long)_m; }
inline unsigned long hashCode() const { return (unsigned long)_m; }
inline MAC &operator=(const MAC &m)
throw()
{
_m = m._m;
return *this;
}
inline MAC &operator=(const uint64_t m)
throw()
{
_m = m;
return *this;
}
inline bool operator==(const MAC &m) const throw() { return (_m == m._m); }
inline bool operator!=(const MAC &m) const throw() { return (_m != m._m); }
inline bool operator<(const MAC &m) const throw() { return (_m < m._m); }
inline bool operator<=(const MAC &m) const throw() { return (_m <= m._m); }
inline bool operator>(const MAC &m) const throw() { return (_m > m._m); }
inline bool operator>=(const MAC &m) const throw() { return (_m >= m._m); }
inline bool operator==(const MAC &m) const { return (_m == m._m); }
inline bool operator!=(const MAC &m) const { return (_m != m._m); }
inline bool operator<(const MAC &m) const { return (_m < m._m); }
inline bool operator<=(const MAC &m) const { return (_m <= m._m); }
inline bool operator>(const MAC &m) const { return (_m > m._m); }
inline bool operator>=(const MAC &m) const { return (_m >= m._m); }
private:
uint64_t _m;

View file

@ -29,8 +29,6 @@
#include <stdint.h>
#include <string>
#include "MAC.hpp"
#include "InetAddress.hpp"
@ -94,16 +92,6 @@ public:
return MulticastGroup();
}
/**
* @return Human readable string representing this group (MAC/ADI in hex)
*/
inline std::string toString() const
{
char buf[64];
Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi);
return std::string(buf);
}
/**
* @return Multicast address
*/

View file

@ -51,7 +51,7 @@ namespace ZeroTier {
namespace {
#ifdef ZT_RULES_ENGINE_DEBUGGING
#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); }
#define FILTER_TRACE(f,...) { snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); }
static const char *_rtn(const ZT_VirtualNetworkRuleType rt)
{
switch(rt) {
@ -1257,7 +1257,17 @@ void Network::requestConfiguration(void *tPtr)
nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
nconf->name[0] = 'a';
nconf->name[1] = 'd';
nconf->name[2] = 'h';
nconf->name[3] = 'o';
nconf->name[4] = 'c';
nconf->name[5] = '-';
Utils::hex((uint16_t)startPortRange,nconf->name + 6);
nconf->name[10] = '-';
Utils::hex((uint16_t)endPortRange,nconf->name + 11);
nconf->name[15] = (char)0;
this->setConfiguration(tPtr,*nconf,false);
delete nconf;

View file

@ -64,7 +64,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (this->staticIps[i].ss_family == AF_INET) {
if (v4s.length() > 0)
v4s.push_back(',');
v4s.append(this->staticIps[i].toString());
char buf[64];
v4s.append(this->staticIps[i].toString(buf));
}
}
if (v4s.length() > 0) {
@ -75,7 +76,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (this->staticIps[i].ss_family == AF_INET6) {
if (v6s.length() > 0)
v6s.push_back(',');
v6s.append(this->staticIps[i].toString());
char buf[64];
v6s.append(this->staticIps[i].toString(buf));
}
}
if (v6s.length() > 0) {
@ -94,8 +96,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (ets.length() > 0)
ets.push_back(',');
char tmp2[16];
Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et);
ets.append(tmp2);
ets.append(Utils::hex((uint16_t)et,tmp2));
}
et = 0;
}
@ -114,7 +115,8 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if ((this->specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) {
if (ab.length() > 0)
ab.push_back(',');
ab.append(Address(this->specialists[i]).toString().c_str());
char tmp2[16];
ab.append(Address(this->specialists[i]).toString(tmp2));
}
}
if (ab.length() > 0) {

View file

@ -82,8 +82,8 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
if (n > 0) {
tmp[n] = (char)0;
if (RR->identity.fromString(tmp)) {
RR->publicIdentityStr = RR->identity.toString(false);
RR->secretIdentityStr = RR->identity.toString(true);
RR->identity.toString(false,RR->publicIdentityStr);
RR->identity.toString(true,RR->secretIdentityStr);
} else {
n = -1;
}
@ -92,10 +92,10 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
if (n <= 0) {
RR->identity.generate();
RR->publicIdentityStr = RR->identity.toString(false);
RR->secretIdentityStr = RR->identity.toString(true);
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr.data(),(unsigned int)RR->secretIdentityStr.length());
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length());
RR->identity.toString(false,RR->publicIdentityStr);
RR->identity.toString(true,RR->secretIdentityStr);
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr));
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
} else {
n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1);
if (n > 0) {
@ -104,7 +104,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
n = -1;
}
if (n <= 0)
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length());
stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
}
try {
@ -386,8 +386,8 @@ uint64_t Node::address() const
void Node::status(ZT_NodeStatus *status) const
{
status->address = RR->identity.address().toInt();
status->publicIdentity = RR->publicIdentityStr.c_str();
status->secretIdentity = RR->secretIdentityStr.c_str();
status->publicIdentity = RR->publicIdentityStr;
status->secretIdentity = RR->secretIdentityStr;
status->online = _online ? 1 : 0;
}
@ -544,39 +544,6 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
}
#ifdef ZT_TRACE
void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
{
static Mutex traceLock;
va_list ap;
char tmp1[1024],tmp2[1024],tmp3[256];
Mutex::Lock _l(traceLock);
time_t now = (time_t)(_now / 1000ULL);
#ifdef __WINDOWS__
ctime_s(tmp3,sizeof(tmp3),&now);
char *nowstr = tmp3;
#else
char *nowstr = ctime_r(&now,tmp3);
#endif
unsigned long nowstrlen = (unsigned long)strlen(nowstr);
if (nowstr[nowstrlen-1] == '\n')
nowstr[--nowstrlen] = (char)0;
if (nowstr[nowstrlen-1] == '\r')
nowstr[--nowstrlen] = (char)0;
va_start(ap,fmt);
vsnprintf(tmp2,sizeof(tmp2),fmt,ap);
va_end(ap);
tmp2[sizeof(tmp2)-1] = (char)0;
Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
postEvent((void *)0,ZT_EVENT_TRACE,tmp1);
}
#endif // ZT_TRACE
uint64_t Node::prng()
{
// https://en.wikipedia.org/wiki/Xorshift#xorshift.2B

View file

@ -195,10 +195,6 @@ public:
inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); }
inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
#ifdef ZT_TRACE
void postTrace(const char *module,unsigned int line,const char *fmt,...);
#endif
bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress);
inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast<struct sockaddr_storage *>(&addr)) != 0) : false ); }

View file

@ -27,7 +27,7 @@
#ifndef ZT_RUNTIMEENVIRONMENT_HPP
#define ZT_RUNTIMEENVIRONMENT_HPP
#include <string>
#include <string.h>
#include "Constants.hpp"
#include "Utils.hpp"
@ -60,11 +60,13 @@ public:
,sa((SelfAwareness *)0)
{
Utils::getSecureRandom(&instanceId,sizeof(instanceId));
memset(publicIdentityStr,0,sizeof(publicIdentityStr));
memset(secretIdentityStr,0,sizeof(secretIdentityStr));
}
~RuntimeEnvironment()
{
Utils::burn(reinterpret_cast<void *>(const_cast<char *>(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length());
Utils::burn(secretIdentityStr,sizeof(secretIdentityStr));
}
/**
@ -77,8 +79,8 @@ public:
// This node's identity
Identity identity;
std::string publicIdentityStr;
std::string secretIdentityStr;
char publicIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
char secretIdentityStr[ZT_IDENTITY_STRING_BUFFER_LENGTH];
// This is set externally to an instance of this base class
NetworkController *localNetworkController;

View file

@ -91,12 +91,8 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
{
#ifdef ZT_TRACE
if ((!peer)||(peer->address() == RR->identity.address())) {
if (!peer)
fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add NULL peer" ZT_EOL_S);
else fprintf(stderr,"FATAL BUG: addPeer() caught attempt to add peer for self" ZT_EOL_S);
abort();
}
if ((!peer)||(peer->address() == RR->identity.address()))
return SharedPtr<Peer>();
#endif
SharedPtr<Peer> np;

View file

@ -55,6 +55,27 @@ namespace ZeroTier {
const char Utils::HEXCHARS[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
static unsigned long _Utils_itoa(unsigned long n,char *s)
{
if (n == 0)
return 0;
unsigned long pos = _Utils_itoa(n / 10,s);
if (pos >= 22) // sanity check, should be impossible
pos = 22;
s[pos] = '0' + (char)(n % 10);
return pos + 1;
}
char *Utils::decimal(unsigned long n,char s[24])
{
if (n == 0) {
s[0] = '0';
s[1] = (char)0;
return s;
}
s[_Utils_itoa(n,s)] = (char)0;
return s;
}
// Crazy hack to force memory to be securely zeroed in spite of the best efforts of optimizing compilers.
static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
{
@ -64,82 +85,6 @@ static void _Utils_doBurn(volatile uint8_t *ptr,unsigned int len)
static void (*volatile _Utils_doBurn_ptr)(volatile uint8_t *,unsigned int) = _Utils_doBurn;
void Utils::burn(void *ptr,unsigned int len) { (_Utils_doBurn_ptr)((volatile uint8_t *)ptr,len); }
std::string Utils::hex(const void *data,unsigned int len)
{
std::string r;
r.reserve(len * 2);
for(unsigned int i=0;i<len;++i) {
r.push_back(HEXCHARS[(((const unsigned char *)data)[i] & 0xf0) >> 4]);
r.push_back(HEXCHARS[((const unsigned char *)data)[i] & 0x0f]);
}
return r;
}
std::string Utils::unhex(const char *hex,unsigned int maxlen)
{
int n = 1;
unsigned char c,b = 0;
const char *eof = hex + maxlen;
std::string r;
if (!maxlen)
return r;
while ((c = (unsigned char)*(hex++))) {
if ((c >= 48)&&(c <= 57)) { // 0..9
if ((n ^= 1))
r.push_back((char)(b | (c - 48)));
else b = (c - 48) << 4;
} else if ((c >= 65)&&(c <= 70)) { // A..F
if ((n ^= 1))
r.push_back((char)(b | (c - (65 - 10))));
else b = (c - (65 - 10)) << 4;
} else if ((c >= 97)&&(c <= 102)) { // a..f
if ((n ^= 1))
r.push_back((char)(b | (c - (97 - 10))));
else b = (c - (97 - 10)) << 4;
}
if (hex == eof)
break;
}
return r;
}
unsigned int Utils::unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len)
{
int n = 1;
unsigned char c,b = 0;
unsigned int l = 0;
const char *eof = hex + maxlen;
if (!maxlen)
return 0;
while ((c = (unsigned char)*(hex++))) {
if ((c >= 48)&&(c <= 57)) { // 0..9
if ((n ^= 1)) {
if (l >= len) break;
((unsigned char *)buf)[l++] = (b | (c - 48));
} else b = (c - 48) << 4;
} else if ((c >= 65)&&(c <= 70)) { // A..F
if ((n ^= 1)) {
if (l >= len) break;
((unsigned char *)buf)[l++] = (b | (c - (65 - 10)));
} else b = (c - (65 - 10)) << 4;
} else if ((c >= 97)&&(c <= 102)) { // a..f
if ((n ^= 1)) {
if (l >= len) break;
((unsigned char *)buf)[l++] = (b | (c - (97 - 10)));
} else b = (c - (97 - 10)) << 4;
}
if (hex == eof)
break;
}
return l;
}
void Utils::getSecureRandom(void *buf,unsigned int bytes)
{
static Mutex globalLock;
@ -244,21 +189,4 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src)
return true;
}
unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
int n = (int)vsnprintf(buf,len,fmt,ap);
va_end(ap);
if ((n >= (int)len)||(n < 0)) {
if (len)
buf[len - 1] = (char)0;
throw std::length_error("buf[] overflow");
}
return (unsigned int)n;
}
} // namespace ZeroTier

View file

@ -70,42 +70,144 @@ public:
static void burn(void *ptr,unsigned int len);
/**
* Convert binary data to hexadecimal
*
* @param data Data to convert to hex
* @param len Length of data
* @return Hexadecimal string
* @param n Number to convert
* @param s Buffer, at least 24 bytes in size
* @return String containing 'n' in base 10 form
*/
static std::string hex(const void *data,unsigned int len);
static inline std::string hex(const std::string &data) { return hex(data.data(),(unsigned int)data.length()); }
static char *decimal(unsigned long n,char s[24]);
/**
* Convert hexadecimal to binary data
*
* This ignores all non-hex characters, just stepping over them and
* continuing. Upper and lower case are supported for letters a-f.
*
* @param hex Hexadecimal ASCII code (non-hex chars are ignored, stops at zero or maxlen)
* @param maxlen Maximum length of hex string buffer
* @return Binary data
*/
static std::string unhex(const char *hex,unsigned int maxlen);
static inline std::string unhex(const std::string &hex) { return unhex(hex.c_str(),(unsigned int)hex.length()); }
static inline char *hex(uint64_t i,char *const s)
{
s[0] = HEXCHARS[(i >> 60) & 0xf];
s[1] = HEXCHARS[(i >> 56) & 0xf];
s[2] = HEXCHARS[(i >> 52) & 0xf];
s[3] = HEXCHARS[(i >> 48) & 0xf];
s[4] = HEXCHARS[(i >> 44) & 0xf];
s[5] = HEXCHARS[(i >> 40) & 0xf];
s[6] = HEXCHARS[(i >> 36) & 0xf];
s[7] = HEXCHARS[(i >> 32) & 0xf];
s[8] = HEXCHARS[(i >> 28) & 0xf];
s[9] = HEXCHARS[(i >> 24) & 0xf];
s[10] = HEXCHARS[(i >> 20) & 0xf];
s[11] = HEXCHARS[(i >> 16) & 0xf];
s[12] = HEXCHARS[(i >> 12) & 0xf];
s[13] = HEXCHARS[(i >> 8) & 0xf];
s[14] = HEXCHARS[(i >> 4) & 0xf];
s[15] = HEXCHARS[i & 0xf];
s[16] = (char)0;
return s;
}
/**
* Convert hexadecimal to binary data
*
* This ignores all non-hex characters, just stepping over them and
* continuing. Upper and lower case are supported for letters a-f.
*
* @param hex Hexadecimal ASCII
* @param maxlen Maximum length of hex string buffer
* @param buf Buffer to fill
* @param len Length of buffer
* @return Number of characters actually written
*/
static unsigned int unhex(const char *hex,unsigned int maxlen,void *buf,unsigned int len);
static inline unsigned int unhex(const std::string &hex,void *buf,unsigned int len) { return unhex(hex.c_str(),(unsigned int)hex.length(),buf,len); }
static inline char *hex10(uint64_t i,char *const s)
{
s[0] = HEXCHARS[(i >> 36) & 0xf];
s[1] = HEXCHARS[(i >> 32) & 0xf];
s[2] = HEXCHARS[(i >> 28) & 0xf];
s[3] = HEXCHARS[(i >> 24) & 0xf];
s[4] = HEXCHARS[(i >> 20) & 0xf];
s[5] = HEXCHARS[(i >> 16) & 0xf];
s[6] = HEXCHARS[(i >> 12) & 0xf];
s[7] = HEXCHARS[(i >> 8) & 0xf];
s[8] = HEXCHARS[(i >> 4) & 0xf];
s[9] = HEXCHARS[i & 0xf];
s[10] = (char)0;
return s;
}
static inline char *hex(uint16_t i,char *const s)
{
s[0] = HEXCHARS[(i >> 12) & 0xf];
s[1] = HEXCHARS[(i >> 8) & 0xf];
s[2] = HEXCHARS[(i >> 4) & 0xf];
s[3] = HEXCHARS[i & 0xf];
s[4] = (char)0;
return s;
}
static inline char *hex(uint8_t i,char *const s)
{
s[0] = HEXCHARS[(i >> 4) & 0xf];
s[1] = HEXCHARS[i & 0xf];
s[2] = (char)0;
return s;
}
static inline char *hex(const void *d,unsigned int l,char *s)
{
char *save = s;
for(unsigned int i=0;i<l;++i) {
unsigned int b = reinterpret_cast<const uint8_t *>(d)[i];
*(s++) = HEXCHARS[(b >> 4) & 0xf];
*(s++) = HEXCHARS[b & 0xf];
}
*s = (char)0;
return save;
}
static inline unsigned int unhex(const char *h,void *buf,unsigned int buflen)
{
unsigned int l = 0;
while (l < buflen) {
uint8_t hc = (uint8_t)*(h++);
if (!hc) break;
uint8_t c = 0;
if ((hc >= 48)&&(hc <= 57))
c = hc - 48;
else if ((hc >= 97)&&(hc <= 102))
c = hc - 87;
else if ((hc >= 65)&&(hc <= 70))
c = hc - 55;
hc = (uint8_t)*(h++);
if (!hc) break;
c <<= 4;
if ((hc >= 48)&&(hc <= 57))
c |= hc - 48;
else if ((hc >= 97)&&(hc <= 102))
c |= hc - 87;
else if ((hc >= 65)&&(hc <= 70))
c |= hc - 55;
reinterpret_cast<uint8_t *>(buf)[l++] = c;
}
return l;
}
static inline unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen)
{
unsigned int l = 0;
const char *hend = h + hlen;
while (l < buflen) {
if (h == hend) break;
uint8_t hc = (uint8_t)*(h++);
if (!hc) break;
uint8_t c = 0;
if ((hc >= 48)&&(hc <= 57))
c = hc - 48;
else if ((hc >= 97)&&(hc <= 102))
c = hc - 87;
else if ((hc >= 65)&&(hc <= 70))
c = hc - 55;
if (h == hend) break;
hc = (uint8_t)*(h++);
if (!hc) break;
c <<= 4;
if ((hc >= 48)&&(hc <= 57))
c |= hc - 48;
else if ((hc >= 97)&&(hc <= 102))
c |= hc - 87;
else if ((hc >= 65)&&(hc <= 70))
c |= hc - 55;
reinterpret_cast<uint8_t *>(buf)[l++] = c;
}
return l;
}
/**
* Generate secure random bytes
@ -232,20 +334,6 @@ public:
*/
static bool scopy(char *dest,unsigned int len,const char *src);
/**
* Variant of snprintf that is portable and throws an exception
*
* This just wraps the local implementation whatever it's called, while
* performing a few other checks and adding exceptions for overflow.
*
* @param buf Buffer to write to
* @param len Length of buffer in bytes
* @param fmt Format string
* @param ... Format arguments
* @throws std::length_error buf[] too short (buf[] will still be left null-terminated)
*/
static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...);
/**
* Count the number of bits set in an integer
*