From d8dae365f6629175b6cfac4ed178305d8ba0e536 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 11 Sep 2019 15:34:55 -0700 Subject: [PATCH] Cleanup, optimization, multicast stuff, and it now compiles again. --- node/AtomicCounter.hpp | 4 +- node/C25519.cpp | 113 +++++++++++++------------------ node/C25519.hpp | 4 +- node/Capability.hpp | 8 +-- node/CertificateOfMembership.hpp | 19 +++--- node/CertificateOfOwnership.hpp | 10 +-- node/Credential.cpp | 2 +- node/Dictionary.hpp | 20 +++--- node/IncomingPacket.cpp | 49 ++++---------- node/IncomingPacket.hpp | 8 +-- node/Switch.cpp | 32 +++------ node/Utils.cpp | 6 +- node/Utils.hpp | 88 ++++++++++-------------- 13 files changed, 144 insertions(+), 219 deletions(-) diff --git a/node/AtomicCounter.hpp b/node/AtomicCounter.hpp index 08438ace3..4e6b95315 100644 --- a/node/AtomicCounter.hpp +++ b/node/AtomicCounter.hpp @@ -58,8 +58,8 @@ public: } private: - inline AtomicCounter(const AtomicCounter &) {} - inline const AtomicCounter &operator=(const AtomicCounter &) { return *this; } + ZT_ALWAYS_INLINE AtomicCounter(const AtomicCounter &) {} + ZT_ALWAYS_INLINE const AtomicCounter &operator=(const AtomicCounter &) { return *this; } #ifdef __GNUC__ int _v; diff --git a/node/C25519.cpp b/node/C25519.cpp index 8c6f5bcb2..f14875b7a 100644 --- a/node/C25519.cpp +++ b/node/C25519.cpp @@ -41,7 +41,7 @@ typedef uint8_t u8; typedef int32_t s32; typedef int64_t limb; -static inline void fsum(limb *output, const limb *in) { +static ZT_ALWAYS_INLINE void fsum(limb *output, const limb *in) { unsigned i; for (i = 0; i < 10; i += 2) { output[0+i] = output[0+i] + in[0+i]; @@ -49,21 +49,21 @@ static inline void fsum(limb *output, const limb *in) { } } -static inline void fdifference(limb *output, const limb *in) { +static ZT_ALWAYS_INLINE void fdifference(limb *output, const limb *in) { unsigned i; for (i = 0; i < 10; ++i) { output[i] = in[i] - output[i]; } } -static inline void fscalar_product(limb *output, const limb *in, const limb scalar) { +static ZT_ALWAYS_INLINE void fscalar_product(limb *output, const limb *in, const limb scalar) { unsigned i; for (i = 0; i < 10; ++i) { output[i] = in[i] * scalar; } } -static inline void fproduct(limb *output, const limb *in2, const limb *in) { +static ZT_ALWAYS_INLINE void fproduct(limb *output, const limb *in2, const limb *in) { output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]); output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) + ((limb) ((s32) in2[1])) * ((s32) in[0]); @@ -166,7 +166,7 @@ static inline void fproduct(limb *output, const limb *in2, const limb *in) { output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]); } -static inline void freduce_degree(limb *output) { +static ZT_ALWAYS_INLINE void freduce_degree(limb *output) { output[8] += output[18] << 4; output[8] += output[18] << 1; output[8] += output[18]; @@ -200,7 +200,7 @@ static inline void freduce_degree(limb *output) { #error "This code only works on a two's complement system" #endif -static inline limb div_by_2_26(const limb v) +static ZT_ALWAYS_INLINE limb div_by_2_26(const limb v) { /* High word of v; no shift needed. */ const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); @@ -212,7 +212,7 @@ static inline limb div_by_2_26(const limb v) return (v + roundoff) >> 26; } -static inline limb div_by_2_25(const limb v) +static ZT_ALWAYS_INLINE limb div_by_2_25(const limb v) { /* High word of v; no shift needed*/ const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32); @@ -224,7 +224,7 @@ static inline limb div_by_2_25(const limb v) return (v + roundoff) >> 25; } -static inline void freduce_coefficients(limb *output) { +static ZT_ALWAYS_INLINE void freduce_coefficients(limb *output) { unsigned i; output[10] = 0; @@ -277,7 +277,7 @@ static inline void fmul(limb *output, const limb *in, const limb *in2) { memcpy(output, t, sizeof(limb) * 10); } -static inline void fsquare_inner(limb *output, const limb *in) { +static ZT_ALWAYS_INLINE void fsquare_inner(limb *output, const limb *in) { output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]); output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]); output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) + @@ -335,7 +335,7 @@ static inline void fsquare_inner(limb *output, const limb *in) { output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]); } -static void fsquare(limb *output, const limb *in) { +static inline void fsquare(limb *output, const limb *in) { limb t[19]; fsquare_inner(t, in); /* |t[i]| < 14*2^54 because the largest product of two limbs will be < @@ -347,7 +347,7 @@ static void fsquare(limb *output, const limb *in) { memcpy(output, t, sizeof(limb) * 10); } -static inline void fexpand(limb *output, const u8 *input) { +static ZT_ALWAYS_INLINE void fexpand(limb *output, const u8 *input) { #define F(n,start,shift,mask) \ output[n] = ((((limb) input[start + 0]) | \ ((limb) input[start + 1]) << 8 | \ @@ -370,7 +370,7 @@ static inline void fexpand(limb *output, const u8 *input) { #error "This code only works when >> does sign-extension on negative numbers" #endif -static inline s32 s32_eq(s32 a, s32 b) { +static ZT_ALWAYS_INLINE s32 s32_eq(s32 a, s32 b) { a = ~(a ^ b); a &= a << 16; a &= a << 8; @@ -380,7 +380,7 @@ static inline s32 s32_eq(s32 a, s32 b) { return a >> 31; } -static inline s32 s32_gte(s32 a, s32 b) { +static ZT_ALWAYS_INLINE s32 s32_gte(s32 a, s32 b) { a -= b; /* a >= 0 iff a >= b. */ return ~(a >> 31); @@ -560,7 +560,7 @@ static inline void fmonty(limb *x2, limb *z2, /* output 2Q */ /* |z2|i| < 2^26 */ } -static inline void swap_conditional(limb a[19], limb b[19], limb iswap) { +static ZT_ALWAYS_INLINE void swap_conditional(limb a[19], limb b[19], limb iswap) { unsigned i; const s32 swap = (s32) -iswap; @@ -683,7 +683,7 @@ static inline void crecip(limb *out, const limb *z) { /* 2^255 - 21 */ fmul(out,t1,z11); } -static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoint) { +static inline void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoint) { limb bp[10], x[10], z[11], zmone[10]; uint8_t e[32]; int i; @@ -701,10 +701,7 @@ static void crypto_scalarmult(u8 *mypublic, const u8 *secret, const u8 *basepoin } static const unsigned char base[32] = {9}; -static inline void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) -{ - crypto_scalarmult(q,n,base); -} +static ZT_ALWAYS_INLINE void crypto_scalarmult_base(unsigned char *q,const unsigned char *n) { crypto_scalarmult(q,n,base); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -762,7 +759,7 @@ typedef struct static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); -static inline crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static ZT_ALWAYS_INLINE crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */ x -= 1; /* 4294967295: yes; 0..65534: no */ @@ -770,7 +767,7 @@ static inline crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inp return x; } -static inline crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static ZT_ALWAYS_INLINE crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ @@ -779,17 +776,10 @@ static inline crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs return x; } -static inline crypto_uint32 times19(crypto_uint32 a) -{ - return (a << 4) + (a << 1) + a; -} +static ZT_ALWAYS_INLINE crypto_uint32 times19(crypto_uint32 a) { return (a << 4) + (a << 1) + a; } +static ZT_ALWAYS_INLINE crypto_uint32 times38(crypto_uint32 a) { return (a << 5) + (a << 2) + (a << 1); } -static inline crypto_uint32 times38(crypto_uint32 a) -{ - return (a << 5) + (a << 2) + (a << 1); -} - -static inline void reduce_add_sub(fe25519 *r) +static ZT_ALWAYS_INLINE void reduce_add_sub(fe25519 *r) { int i,rep; for(rep=0;rep<4;rep++) @@ -807,7 +797,7 @@ static inline void reduce_add_sub(fe25519 *r) } } -static inline void reduce_mul(fe25519 *r) +static ZT_ALWAYS_INLINE void reduce_mul(fe25519 *r) { int i,rep; for(rep=0;rep<2;rep++) @@ -825,8 +815,7 @@ static inline void reduce_mul(fe25519 *r) } } -/* reduction modulo 2^255-19 */ -static inline void fe25519_freeze(fe25519 *r) +static ZT_ALWAYS_INLINE void fe25519_freeze(fe25519 *r) { int i; crypto_uint32 mm = equal(r->v[31],127); @@ -842,15 +831,14 @@ static inline void fe25519_freeze(fe25519 *r) r->v[0] -= mm&237; } -static inline void fe25519_unpack(fe25519 *r, const unsigned char x[32]) +static ZT_ALWAYS_INLINE void fe25519_unpack(fe25519 *r, const unsigned char x[32]) { int i; for(i=0;i<32;i++) r->v[i] = x[i]; r->v[31] &= 127; } -/* Assumes input x being reduced below 2^255 */ -static inline void fe25519_pack(unsigned char r[32], const fe25519 *x) +static ZT_ALWAYS_INLINE void fe25519_pack(unsigned char r[32], const fe25519 *x) { int i; fe25519 y = *x; @@ -871,7 +859,7 @@ static inline int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) return 1; } -static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) +static ZT_ALWAYS_INLINE void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { int i; crypto_uint32 mask = b; @@ -879,27 +867,27 @@ static inline void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } -static inline unsigned char fe25519_getparity(const fe25519 *x) +static ZT_ALWAYS_INLINE unsigned char fe25519_getparity(const fe25519 *x) { fe25519 t = *x; fe25519_freeze(&t); return t.v[0] & 1; } -static inline void fe25519_setone(fe25519 *r) +static ZT_ALWAYS_INLINE void fe25519_setone(fe25519 *r) { int i; r->v[0] = 1; for(i=1;i<32;i++) r->v[i]=0; } -static inline void fe25519_setzero(fe25519 *r) +static ZT_ALWAYS_INLINE void fe25519_setzero(fe25519 *r) { int i; for(i=0;i<32;i++) r->v[i]=0; } -static inline void fe25519_neg(fe25519 *r, const fe25519 *x) +static ZT_ALWAYS_INLINE void fe25519_neg(fe25519 *r, const fe25519 *x) { fe25519 t; int i; @@ -908,14 +896,14 @@ static inline void fe25519_neg(fe25519 *r, const fe25519 *x) fe25519_sub(r, r, &t); } -static inline void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) +static ZT_ALWAYS_INLINE void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; reduce_add_sub(r); } -static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) +static ZT_ALWAYS_INLINE void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; crypto_uint32 t[32]; @@ -926,7 +914,7 @@ static inline void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) reduce_add_sub(r); } -static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) +static ZT_ALWAYS_INLINE void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i,j; crypto_uint32 t[63]; @@ -943,10 +931,7 @@ static inline void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) reduce_mul(r); } -static inline void fe25519_square(fe25519 *r, const fe25519 *x) -{ - fe25519_mul(r, x, x); -} +static ZT_ALWAYS_INLINE void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); } static inline void fe25519_invert(fe25519 *r, const fe25519 *x) { @@ -1072,7 +1057,7 @@ static inline void fe25519_pow2523(fe25519 *r, const fe25519 *x) static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; -static inline crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +static ZT_ALWAYS_INLINE crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ @@ -1080,8 +1065,7 @@ static inline crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs return x; } -/* Reduce coefficients of r before calling reduce_add_sub */ -static inline void reduce_add_sub(sc25519 *r) +static ZT_ALWAYS_INLINE void reduce_add_sub(sc25519 *r) { crypto_uint32 pb = 0; crypto_uint32 b; @@ -1101,7 +1085,6 @@ static inline void reduce_add_sub(sc25519 *r) r->v[i] ^= mask & (r->v[i] ^ t[i]); } -/* Reduce coefficients of x before calling barrett_reduce */ static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) { /* See HAC, Alg. 14.42 */ @@ -1140,10 +1123,6 @@ static inline void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) pb = b; } - /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 - * If so: Handle it here! - */ - reduce_add_sub(r); reduce_add_sub(r); } @@ -1165,7 +1144,7 @@ static inline void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) barrett_reduce(r, t); } -static inline void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) +static ZT_ALWAYS_INLINE void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) { int i; for(i=0;i<32;i++) r[i] = x->v[i]; @@ -1202,7 +1181,7 @@ static inline void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) barrett_reduce(r, t); } -static inline void sc25519_window3(signed char r[85], const sc25519 *s) +static ZT_ALWAYS_INLINE void sc25519_window3(signed char r[85], const sc25519 *s) { char carry; int i; @@ -1239,7 +1218,7 @@ static inline void sc25519_window3(signed char r[85], const sc25519 *s) r[84] += carry; } -static inline void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) +static ZT_ALWAYS_INLINE void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) { int i; for(i=0;i<31;i++) @@ -2128,21 +2107,21 @@ static const ge25519_aff ge25519_base_multiples_affine[425] = { {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} }; -static inline void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) +static ZT_ALWAYS_INLINE void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } -static inline void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) +static ZT_ALWAYS_INLINE void p1p1_to_p2_2(ge25519_p3 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } -static inline void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) +static ZT_ALWAYS_INLINE void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { p1p1_to_p2_2(r, p); fe25519_mul(&r->t, &p->x, &p->y); @@ -2211,13 +2190,13 @@ static inline void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) } /* Constant-time version of: if(b) r = p */ -static inline void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) +static ZT_ALWAYS_INLINE void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { fe25519_cmov(&r->x, &p->x, b); fe25519_cmov(&r->y, &p->y, b); } -static inline unsigned char equal(signed char b,signed char c) +static ZT_ALWAYS_INLINE unsigned char equal(signed char b,signed char c) { unsigned char ub = b; unsigned char uc = c; @@ -2228,7 +2207,7 @@ static inline unsigned char equal(signed char b,signed char c) return (unsigned char)y; } -static inline unsigned char negative(signed char b) +static ZT_ALWAYS_INLINE unsigned char negative(signed char b) { unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ @@ -2377,7 +2356,7 @@ static inline void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) } } -static inline void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) +static ZT_ALWAYS_INLINE void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) { unsigned long long i; diff --git a/node/C25519.hpp b/node/C25519.hpp index b73e0ec11..94b62c321 100644 --- a/node/C25519.hpp +++ b/node/C25519.hpp @@ -32,7 +32,7 @@ public: /** * Generate a C25519 elliptic curve key pair */ - static inline void generate(uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN]) + static ZT_ALWAYS_INLINE void generate(uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN]) { Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN); _calcPubDH(pub,priv); @@ -53,7 +53,7 @@ public: * @tparam F Type of 'cond' */ template - static inline void generateSatisfying(F cond,uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN]) + static ZT_ALWAYS_INLINE void generateSatisfying(F cond,uint8_t pub[ZT_C25519_PUBLIC_KEY_LEN],uint8_t priv[ZT_C25519_PRIVATE_KEY_LEN]) { Utils::getSecureRandom(priv,ZT_C25519_PRIVATE_KEY_LEN); _calcPubED(pub,priv); // do Ed25519 key -- bytes 32-63 of pub and priv diff --git a/node/Capability.hpp b/node/Capability.hpp index 91a3d2118..902869e8d 100644 --- a/node/Capability.hpp +++ b/node/Capability.hpp @@ -61,7 +61,7 @@ class Capability : public Credential public: static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_CAPABILITY; } - inline Capability() : + ZT_ALWAYS_INLINE Capability() : _nwid(0), _ts(0), _id(0), @@ -80,7 +80,7 @@ public: * @param rules Network flow rules for this capability * @param ruleCount Number of flow rules */ - inline Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) : + ZT_ALWAYS_INLINE Capability(uint32_t id,uint64_t nwid,int64_t ts,unsigned int mccl,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) : _nwid(nwid), _ts(ts), _id(id), @@ -119,7 +119,7 @@ public: /** * @return Last 'to' address in chain of custody */ - inline Address issuedTo() const + ZT_ALWAYS_INLINE Address issuedTo() const { Address i2; for(unsigned int i=0;i static inline void serializeRules(Buffer &b,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp index 744e6b865..ba21afd46 100644 --- a/node/CertificateOfMembership.hpp +++ b/node/CertificateOfMembership.hpp @@ -69,7 +69,7 @@ class CertificateOfMembership : public Credential friend class Credential; public: - static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; } + static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COM; } /** * Reserved qualifier IDs @@ -101,7 +101,7 @@ public: /** * Create an empty certificate of membership */ - inline CertificateOfMembership() : + ZT_ALWAYS_INLINE CertificateOfMembership() : _qualifierCount(0), _signatureLength(0) {} @@ -113,7 +113,7 @@ public: * @param nwid Network ID * @param issuedTo Certificate recipient */ - inline CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo) + ZT_ALWAYS_INLINE CertificateOfMembership(uint64_t timestamp,uint64_t timestampMaxDelta,uint64_t nwid,const Address &issuedTo) { _qualifiers[0].id = COM_RESERVED_ID_TIMESTAMP; _qualifiers[0].value = timestamp; @@ -135,10 +135,7 @@ public: * @param startAt Position to start in buffer */ template - inline CertificateOfMembership(const Buffer &b,unsigned int startAt = 0) - { - deserialize(b,startAt); - } + ZT_ALWAYS_INLINE CertificateOfMembership(const Buffer &b,unsigned int startAt = 0) { deserialize(b,startAt); } /** * @return True if there's something here @@ -214,7 +211,7 @@ public: } } - inline void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); } + ZT_ALWAYS_INLINE void setQualifier(ReservedId id,uint64_t value,uint64_t maxDelta) { setQualifier((uint64_t)id,value,maxDelta); } /** * Compare two certificates for parameter agreement @@ -297,17 +294,17 @@ public: * @param RR Runtime environment for looking up peers * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } + ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } /** * @return True if signed */ - inline bool isSigned() const { return (_signedBy); } + ZT_ALWAYS_INLINE bool isSigned() const { return (_signedBy); } /** * @return Address that signed this certificate or null address if none */ - inline const Address &signedBy() const { return _signedBy; } + ZT_ALWAYS_INLINE const Address &signedBy() const { return _signedBy; } template inline void serialize(Buffer &b) const diff --git a/node/CertificateOfOwnership.hpp b/node/CertificateOfOwnership.hpp index 264c47151..a77ebaae2 100644 --- a/node/CertificateOfOwnership.hpp +++ b/node/CertificateOfOwnership.hpp @@ -46,7 +46,7 @@ class CertificateOfOwnership : public Credential friend class Credential; public: - static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; } + static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_COO; } enum Thing { @@ -56,12 +56,12 @@ public: THING_IPV6_ADDRESS = 3 }; - inline CertificateOfOwnership() + ZT_ALWAYS_INLINE CertificateOfOwnership() { memset(reinterpret_cast(this),0,sizeof(CertificateOfOwnership)); } - inline CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) + ZT_ALWAYS_INLINE CertificateOfOwnership(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id) { memset(reinterpret_cast(this),0,sizeof(CertificateOfOwnership)); _networkId = nwid; @@ -82,7 +82,7 @@ public: ZT_ALWAYS_INLINE Thing thingType(const unsigned int i) const { return (Thing)_thingTypes[i]; } ZT_ALWAYS_INLINE const uint8_t *thingValue(const unsigned int i) const { return _thingValues[i]; } - inline bool owns(const InetAddress &ip) const + ZT_ALWAYS_INLINE bool owns(const InetAddress &ip) const { if (ip.ss_family == AF_INET) return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast(&ip)->sin_addr.s_addr),4); @@ -91,7 +91,7 @@ public: return false; } - inline bool owns(const MAC &mac) const + ZT_ALWAYS_INLINE bool owns(const MAC &mac) const { uint8_t tmp[6]; mac.copyTo(tmp,6); diff --git a/node/Credential.cpp b/node/Credential.cpp index 5e5ebe9bf..d53b62f00 100644 --- a/node/Credential.cpp +++ b/node/Credential.cpp @@ -26,7 +26,7 @@ namespace ZeroTier { template -static inline Credential::VerifyResult _credVerify(const RuntimeEnvironment *const RR,void *tPtr,CRED credential) +static ZT_ALWAYS_INLINE Credential::VerifyResult _credVerify(const RuntimeEnvironment *const RR,void *tPtr,CRED credential) { const Address signedBy(credential.signer()); const uint64_t networkId = credential.networkId(); diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp index 9fbc27d05..1614ccb74 100644 --- a/node/Dictionary.hpp +++ b/node/Dictionary.hpp @@ -217,7 +217,7 @@ public: * @tparam BC Buffer capacity (usually inferred) */ template - inline bool get(const char *key,Buffer &dest) const + ZT_ALWAYS_INLINE bool get(const char *key,Buffer &dest) const { const int r = this->get(key,const_cast(reinterpret_cast(dest.data())),BC); if (r >= 0) { @@ -236,7 +236,7 @@ public: * @param dfl Default value if not found in dictionary * @return Boolean value of key or 'dfl' if not found */ - bool getB(const char *key,bool dfl = false) const + ZT_ALWAYS_INLINE bool getB(const char *key,bool dfl = false) const { char tmp[4]; if (this->get(key,tmp,sizeof(tmp)) >= 0) @@ -251,7 +251,7 @@ public: * @param dfl Default value or 0 if unspecified * @return Decoded hex UInt value or 'dfl' if not found */ - inline uint64_t getUI(const char *key,uint64_t dfl = 0) const + ZT_ALWAYS_INLINE uint64_t getUI(const char *key,uint64_t dfl = 0) const { char tmp[128]; if (this->get(key,tmp,sizeof(tmp)) >= 1) @@ -266,7 +266,7 @@ public: * @param dfl Default value or 0 if unspecified * @return Decoded hex UInt value or 'dfl' if not found */ - inline int64_t getI(const char *key,int64_t dfl = 0) const + ZT_ALWAYS_INLINE int64_t getI(const char *key,int64_t dfl = 0) const { char tmp[128]; if (this->get(key,tmp,sizeof(tmp)) >= 1) @@ -366,7 +366,7 @@ public: /** * Add a boolean as a '1' or a '0' */ - inline bool add(const char *key,bool value) + ZT_ALWAYS_INLINE bool add(const char *key,bool value) { return this->add(key,(value) ? "1" : "0",1); } @@ -374,7 +374,7 @@ public: /** * Add a 64-bit integer (unsigned) as a hex value */ - inline bool add(const char *key,uint64_t value) + ZT_ALWAYS_INLINE bool add(const char *key,uint64_t value) { char tmp[32]; return this->add(key,Utils::hex(value,tmp),-1); @@ -383,7 +383,7 @@ public: /** * Add a 64-bit integer (unsigned) as a hex value */ - inline bool add(const char *key,int64_t value) + ZT_ALWAYS_INLINE bool add(const char *key,int64_t value) { char tmp[32]; if (value >= 0) { @@ -397,7 +397,7 @@ public: /** * Add a 64-bit integer (unsigned) as a hex value */ - inline bool add(const char *key,const Address &a) + ZT_ALWAYS_INLINE bool add(const char *key,const Address &a) { char tmp[32]; return this->add(key,Utils::hex(a.toInt(),tmp),-1); @@ -409,7 +409,7 @@ public: * @tparam BC Buffer capacity (usually inferred) */ template - inline bool add(const char *key,const Buffer &value) + ZT_ALWAYS_INLINE bool add(const char *key,const Buffer &value) { return this->add(key,(const char *)value.data(),(int)value.size()); } @@ -418,7 +418,7 @@ public: * @param key Key to check * @return True if key is present */ - inline bool contains(const char *key) const + ZT_ALWAYS_INLINE bool contains(const char *key) const { char tmp[2]; return (this->get(key,tmp,2) >= 0); diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index f55a2ade1..cf411ec69 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -45,7 +45,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr) // Check for trusted paths or unencrypted HELLOs (HELLO is the only packet sent in the clear) const unsigned int c = cipher(); bool trusted = false; - if (c == ZT_PROTO_CIPHER_SUITE__NO_CRYPTO_TRUSTED_PATH) { + if (c == ZT_PROTO_CIPHER_SUITE__NONE) { // If this is marked as a packet via a trusted path, check source address and path ID. // Obviously if no trusted paths are configured this always returns false and such // packets are dropped on the floor. @@ -174,15 +174,11 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar network->setAccessDenied(); } break; - case Packet::ERROR_UNWANTED_MULTICAST: { + case Packet::ERROR_MULTICAST_STFU: { // Members of networks can use this error to indicate that they no longer // want to receive multicasts on a given channel. - networkId = at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD); - const SharedPtr network(RR->node->network(networkId)); - if ((network)&&(network->gate(tPtr,peer))) { - const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14)); - RR->mc->remove(network->id(),mg,peer->address()); - } + const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 8,6),6),at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD + 14)); + RR->mc->remove(at(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD),mg,peer->address()); } break; default: break; @@ -431,6 +427,8 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP } break; case Packet::VERB_MULTICAST_GATHER: { + // TODO + /* networkId = at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); const SharedPtr network(RR->node->network(networkId)); if (network) { @@ -439,32 +437,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,void *tPtr,const SharedP if (((ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6) + (count * 5)) <= size()) RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); } - } break; - - case Packet::VERB_MULTICAST_FRAME: { - const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS]; - networkId = at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); - const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI)); - - const SharedPtr network(RR->node->network(networkId)); - if (network) { - unsigned int offset = 0; - - if ((flags & 0x01) != 0) { // deprecated but still used by older peers - CertificateOfMembership com; - offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS); - if (com) - network->addCredential(tPtr,com); - } - - if ((flags & 0x02) != 0) { - // OK(MULTICAST_FRAME) includes implicit gather results - offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS; - unsigned int totalKnown = at(offset); offset += 4; - unsigned int count = at(offset); offset += 2; - RR->mc->addMultiple(tPtr,RR->node->now(),networkId,mg,field(offset,count * 5),count,totalKnown); - } - } + */ } break; default: break; @@ -660,6 +633,8 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,c // Packet contains a series of 18-byte network,MAC,ADI tuples for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;(ptr+18)<=size();ptr+=18) { + // TODO + /* const uint64_t nwid = at(ptr); if (nwid != lastNwid) { lastNwid = nwid; @@ -671,6 +646,7 @@ bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,c } if (authorized) RR->mc->add(tPtr,now,nwid,MulticastGroup(MAC(field(ptr + 8,6),6),at(ptr + 14)),peer->address()); + */ } peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,0); @@ -831,6 +807,8 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr const int64_t now = RR->node->now(); if (gatherLimit) { + // TODO + /* Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_MULTICAST_GATHER); outp.append(packetId()); @@ -842,6 +820,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),now); } + */ } peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,nwid); @@ -956,6 +935,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, } if (gatherLimit) { // DEPRECATED but still supported + /* Packet outp(source(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_MULTICAST_FRAME); outp.append(packetId()); @@ -967,6 +947,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr, outp.armor(peer->key(),true); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); } + */ } peer->received(tPtr,_path,hops(),packetId(),payloadLength(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,nwid); diff --git a/node/IncomingPacket.hpp b/node/IncomingPacket.hpp index 763de0c44..bca4c13cf 100644 --- a/node/IncomingPacket.hpp +++ b/node/IncomingPacket.hpp @@ -49,7 +49,7 @@ class Network; class IncomingPacket : public Packet { public: - inline IncomingPacket() : + ZT_ALWAYS_INLINE IncomingPacket() : Packet(), _receiveTime(0) { @@ -64,7 +64,7 @@ public: * @param now Current time * @throws std::out_of_range Range error processing packet */ - inline IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,int64_t now) : + ZT_ALWAYS_INLINE IncomingPacket(const void *data,unsigned int len,const SharedPtr &path,int64_t now) : Packet(data,len), _receiveTime(now), _path(path) @@ -80,7 +80,7 @@ public: * @param now Current time * @throws std::out_of_range Range error processing packet */ - inline void init(const void *data,unsigned int len,const SharedPtr &path,int64_t now) + ZT_ALWAYS_INLINE void init(const void *data,unsigned int len,const SharedPtr &path,int64_t now) { copyFrom(data,len); _receiveTime = now; @@ -105,7 +105,7 @@ public: /** * @return Time of packet receipt / start of decode */ - inline uint64_t receiveTime() const { return _receiveTime; } + ZT_ALWAYS_INLINE uint64_t receiveTime() const { return _receiveTime; } private: // These are called internally to handle packet contents once it has diff --git a/node/Switch.cpp b/node/Switch.cpp index 05d068740..c34fc8e0b 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -49,28 +49,7 @@ void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddre const SharedPtr path(RR->topology->getPath(localSocket,fromAddr)); path->received(now); - if (len == 13) { - /* LEGACY: before VERB_PUSH_DIRECT_PATHS, peers used broadcast - * announcements on the LAN to solve the 'same network problem.' We - * no longer send these, but we'll listen for them for a while to - * locate peers with versions <1.0.4. */ - - const Address beaconAddr(reinterpret_cast(data) + 8,5); - if (beaconAddr == RR->identity.address()) - return; - if (!RR->node->shouldUsePathForZeroTierTraffic(tPtr,beaconAddr,localSocket,fromAddr)) - return; - const SharedPtr peer(RR->topology->get(beaconAddr)); - if (peer) { // we'll only respond to beacons from known peers - if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses - _lastBeaconResponse = now; - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP); - outp.armor(peer->key(),true); - path->send(RR,tPtr,outp.data(),outp.size(),now); - } - } - - } else if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) { // SECURITY: min length check is important since we do some C-style stuff below! + if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) { // SECURITY: min length check is important since we do some C-style stuff below! if (reinterpret_cast(data)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) { // Handle fragment ---------------------------------------------------- @@ -372,6 +351,8 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const return; } + // TODO + /* RR->mc->send( tPtr, RR->node->now(), @@ -382,6 +363,7 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const etherType, data, len); + */ } else if (to == network->mac()) { // Destination is this node, so just reinject it RR->node->putFrame(tPtr,network->id(),network->userPtr(),from,to,etherType,vlanId,data,len); @@ -434,7 +416,11 @@ void Switch::onLocalEthernet(void *tPtr,const SharedPtr &network,const /* Create an array of up to ZT_MAX_BRIDGE_SPAM recipients for this bridged frame. */ bridges[0] = network->findBridgeTo(to); - std::vector
activeBridges(network->config().activeBridges()); + std::vector
activeBridges; + for(unsigned int i=0;iconfig().specialistCount;++i) { + if ((network->config().specialists[i] & ZT_NETWORKCONFIG_SPECIALIST_TYPE_ACTIVE_BRIDGE) != 0) + activeBridges.push_back(network->config().specialists[i]); + } if ((bridges[0])&&(bridges[0] != RR->identity.address())&&(network->config().permitsBridging(bridges[0]))) { /* We have a known bridge route for this MAC, send it there. */ ++numBridges; diff --git a/node/Utils.cpp b/node/Utils.cpp index 03fde4493..04d8ba272 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -193,13 +193,13 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) } uint8_t h[48]; - for(unsigned int k=0;k<4;++k) { + for(unsigned int k=0;k<4;++k) { // treat random state like a 256-bit counter; endian-ness is irrelevant since we just want random if (++randomState[k] != 0) break; } - HMACSHA384((const uint8_t *)randomState,randomBuf,sizeof(randomBuf),h); + HMACSHA384((const uint8_t *)randomState,randomBuf,sizeof(randomBuf),h); // compute HMAC on random buffer using state as secret key AES c(h); - c.ctr(h + 32,randomBuf,sizeof(randomBuf),randomBuf); + c.ctr(h + 32,randomBuf,sizeof(randomBuf),randomBuf); // encrypt random buffer with AES-CTR using HMAC result as key } ((uint8_t *)buf)[i] = randomBuf[randomPtr++]; diff --git a/node/Utils.hpp b/node/Utils.hpp index 04fe1ae4c..8556e9f7f 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -68,29 +68,35 @@ public: */ static char *decimal(unsigned long n,char s[24]); - static inline char *hex(uint64_t i,char s[17]) + /** + * Convert an unsigned integer into hex + * + * @param i Any unsigned integer + * @param s Buffer to receive hex, must be at least (2*sizeof(i))+1 in size or overflow will occur. + * @return Pointer to s containing hex string with trailing zero byte + */ + template + static ZT_ALWAYS_INLINE char *hex(I i,char *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; + char *const r = s; + for(unsigned int i=0,b=(sizeof(i)*8);i> b) & 0xf]; + b -= 4; + *(s++) = HEXCHARS[(i >> b) & 0xf]; + } + *s = (char)0; + return r; } - static inline char *hex10(uint64_t i,char s[11]) + /** + * Convert the least significant 40 bits of a uint64_t to hex + * + * @param i Unsigned 64-bit int + * @param s Buffer of size [11] to receive 10 hex characters + * @return Pointer to buffer + */ + static ZT_ALWAYS_INLINE char *hex10(uint64_t i,char s[11]) { s[0] = HEXCHARS[(i >> 36) & 0xf]; s[1] = HEXCHARS[(i >> 32) & 0xf]; @@ -106,39 +112,15 @@ public: return s; } - static inline char *hex(uint32_t i,char s[9]) - { - s[0] = HEXCHARS[(i >> 28) & 0xf]; - s[1] = HEXCHARS[(i >> 24) & 0xf]; - s[2] = HEXCHARS[(i >> 20) & 0xf]; - s[3] = HEXCHARS[(i >> 16) & 0xf]; - s[4] = HEXCHARS[(i >> 12) & 0xf]; - s[5] = HEXCHARS[(i >> 8) & 0xf]; - s[6] = HEXCHARS[(i >> 4) & 0xf]; - s[7] = HEXCHARS[i & 0xf]; - s[8] = (char)0; - return s; - } - - static inline char *hex(uint16_t i,char s[5]) - { - 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 s[3]) - { - 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) + /** + * Convert a byte array into hex + * + * @param d Bytes + * @param l Length of bytes + * @param s String buffer, must be at least (l*2)+1 in size or overflow will occur + * @return Pointer to filled string buffer + */ + static ZT_ALWAYS_INLINE char *hex(const void *d,unsigned int l,char *s) { char *const save = s; for(unsigned int i=0;i