diff options
Diffstat (limited to 'node/NetworkConfig.hpp')
-rw-r--r-- | node/NetworkConfig.hpp | 377 |
1 files changed, 86 insertions, 291 deletions
diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index bf513df1..4bc2546b 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -35,21 +35,17 @@ #include "MulticastGroup.hpp" #include "Address.hpp" #include "CertificateOfMembership.hpp" - -#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF #include "Dictionary.hpp" -#include <string> -#endif /** * Flag: allow passive bridging (experimental) */ -#define ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING 0x0001 +#define ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING 0x0000000000000001ULL /** * Flag: enable broadcast */ -#define ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST 0x0002 +#define ZT_NETWORKCONFIG_FLAG_ENABLE_BROADCAST 0x0000000000000002ULL /** * Device is a network preferred relay @@ -68,18 +64,20 @@ namespace ZeroTier { -#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF +// Network config version +#define ZT_NETWORKCONFIG_VERSION 6 // Fields for meta-data sent with network config requests +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_VERSION "v" +#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_PROTOCOL_VERSION "pv" #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv" #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv" #define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv" -// These dictionary keys are short so they don't take up much room in -// netconf response packets. +// These dictionary keys are short so they don't take up much room. -// integer(hex)[,integer(hex),...] -#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et" +// network config version +#define ZT_NETWORKCONFIG_DICT_KEY_VERSION "v" // network ID #define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid" // integer(hex) @@ -88,34 +86,49 @@ namespace ZeroTier { #define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r" // address of member #define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id" +// flags(hex) +#define ZT_NETWORKCONFIG_DICT_KEY_FLAGS "f" // integer(hex) #define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml" -// 0/1 -#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p" +// network type (hex) +#define ZT_NETWORKCONFIG_DICT_KEY_TYPE "t" // text #define ZT_NETWORKCONFIG_DICT_KEY_NAME "n" -// text -#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" +// binary serialized certificate of membership +#define ZT_NETWORKCONFIG_DICT_KEY_COM "C" +// specialists (binary array of uint64_t) +#define ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS "S" +// routes (binary blob) +#define ZT_NETWORKCONFIG_DICT_KEY_ROUTES "RT" +// static IPs (binary blob) +#define ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS "I" +// pinned address physical route mappings (binary blob) +#define ZT_NETWORKCONFIG_DICT_KEY_PINNED "P" +// rules (binary blob) +#define ZT_NETWORKCONFIG_DICT_KEY_RULES "R" + +// Legacy fields -- these are obsoleted but are included when older clients query + +// boolean (now a flag) +#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING_OLD "pb" +// boolean (now a flag) +#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST_OLD "eb" // IP/bits[,IP/bits,...] // Note that IPs that end in all zeroes are routes with no assignment in them. -#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" +#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC_OLD "v4s" // IP/bits[,IP/bits,...] // Note that IPs that end in all zeroes are routes with no assignment in them. -#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" -// serialized CertificateOfMembership -#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com" +#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC_OLD "v6s" // 0/1 -#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb" -// 0/1 -#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb" +#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE_OLD "p" +// integer(hex)[,integer(hex),...] +#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES_OLD "et" +// string-serialized CertificateOfMembership +#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP_OLD "com" // node[,node,...] -#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab" +#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES_OLD "ab" // node;IP/port[,node;IP/port] -#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl" -// IP/metric[,IP/metric,...] -#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw" - -#endif // ZT_SUPPORT_OLD_STYLE_NETCONF +#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS_OLD "rl" /** * Network configuration received from network controller nodes @@ -215,6 +228,23 @@ public: } /** + * Write this network config to a dictionary for transport + * + * @param d Dictionary + * @param includeLegacy If true, include legacy fields for old node versions + * @return True if dictionary was successfully created, false if e.g. overflow + */ + bool toDictionary(Dictionary &d,bool includeLegacy) const; + + /** + * Read this network config from a dictionary + * + * @param d Dictionary + * @return True if dictionary was valid and network config successfully initialized + */ + bool fromDictionary(const Dictionary &d); + + /** * @return True if passive bridging is allowed (experimental) */ inline bool allowPassiveBridging() const throw() { return ((this->flags & ZT_NETWORKCONFIG_FLAG_ALLOW_PASSIVE_BRIDGING) != 0); } @@ -350,269 +380,6 @@ public: inline bool operator==(const NetworkConfig &nc) const { return (memcmp(this,&nc,sizeof(NetworkConfig)) == 0); } inline bool operator!=(const NetworkConfig &nc) const { return (!(*this == nc)); } - template<unsigned int C> - inline void serialize(Buffer<C> &b) const - { - b.append((uint16_t)1); // version - - b.append((uint64_t)networkId); - b.append((uint64_t)timestamp); - b.append((uint64_t)revision); - issuedTo.appendTo(b); - b.append((uint64_t)flags); - b.append((uint32_t)multicastLimit); - b.append((uint8_t)type); - - unsigned int nl = (unsigned int)strlen(name); - if (nl > 255) nl = 255; // sanity check - b.append((uint8_t)nl); - b.append((const void *)name,nl); - - b.append((uint16_t)specialistCount); - for(unsigned int i=0;i<specialistCount;++i) - b.append((uint64_t)specialists[i]); - - b.append((uint16_t)routeCount); - for(unsigned int i=0;i<routeCount;++i) { - reinterpret_cast<const InetAddress *>(&(routes[i].target))->serialize(b); - reinterpret_cast<const InetAddress *>(&(routes[i].via))->serialize(b); - b.append((uint16_t)routes[i].flags); - b.append((uint16_t)routes[i].metric); - } - - b.append((uint16_t)staticIpCount); - for(unsigned int i=0;i<staticIpCount;++i) - staticIps[i].serialize(b); - - b.append((uint16_t)pinnedCount); - for(unsigned int i=0;i<pinnedCount;++i) { - pinned[i].zt.appendTo(b); - pinned[i].phy.serialize(b); - } - - b.append((uint16_t)ruleCount); - for(unsigned int i=0;i<ruleCount;++i) { - b.append((uint8_t)rules[i].t); - switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f)) { - //case ZT_NETWORK_RULE_ACTION_DROP: - //case ZT_NETWORK_RULE_ACTION_ACCEPT: - default: - b.append((uint8_t)0); - break; - case ZT_NETWORK_RULE_ACTION_TEE: - case ZT_NETWORK_RULE_ACTION_REDIRECT: - case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: - case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: - b.append((uint8_t)5); - Address(rules[i].v.zt).appendTo(b); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_ID: - b.append((uint8_t)2); - b.append((uint16_t)rules[i].v.vlanId); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_PCP: - b.append((uint8_t)1); - b.append((uint8_t)rules[i].v.vlanPcp); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_DEI: - b.append((uint8_t)1); - b.append((uint8_t)rules[i].v.vlanDei); - break; - case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - b.append((uint8_t)2); - b.append((uint16_t)rules[i].v.etherType); - break; - case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: - case ZT_NETWORK_RULE_MATCH_MAC_DEST: - b.append((uint8_t)6); - b.append(rules[i].v.mac,6); - break; - case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - b.append((uint8_t)5); - b.append(&(rules[i].v.ipv4.ip),4); - b.append((uint8_t)rules[i].v.ipv4.mask); - break; - case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - b.append((uint8_t)17); - b.append(rules[i].v.ipv6.ip,16); - b.append((uint8_t)rules[i].v.ipv6.mask); - break; - case ZT_NETWORK_RULE_MATCH_IP_TOS: - b.append((uint8_t)1); - b.append((uint8_t)rules[i].v.ipTos); - break; - case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - b.append((uint8_t)1); - b.append((uint8_t)rules[i].v.ipProtocol); - break; - case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: - case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - b.append((uint8_t)4); - b.append((uint16_t)rules[i].v.port[0]); - b.append((uint16_t)rules[i].v.port[1]); - break; - case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - b.append((uint8_t)8); - b.append((uint64_t)rules[i].v.characteristics); - break; - case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - b.append((uint8_t)4); - b.append((uint16_t)rules[i].v.frameSize[0]); - b.append((uint16_t)rules[i].v.frameSize[1]); - break; - case ZT_NETWORK_RULE_MATCH_TCP_RELATIVE_SEQUENCE_NUMBER_RANGE: - b.append((uint8_t)8); - b.append((uint32_t)rules[i].v.tcpseq[0]); - b.append((uint32_t)rules[i].v.tcpseq[1]); - break; - } - } - - this->com.serialize(b); - - b.append((uint16_t)0); // extended bytes, currently 0 since unused - } - - template<unsigned int C> - inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0) - { - memset(this,0,sizeof(NetworkConfig)); - - unsigned int p = startAt; - - if (b.template at<uint16_t>(p) != 1) - throw std::invalid_argument("unrecognized version"); - p += 2; - - networkId = b.template at<uint64_t>(p); p += 8; - timestamp = b.template at<uint64_t>(p); p += 8; - revision = b.template at<uint64_t>(p); p += 8; - issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH; - flags = b.template at<uint64_t>(p); p += 8; - multicastLimit = (unsigned int)b.template at<uint32_t>(p); p += 4; - type = (ZT_VirtualNetworkType)b[p++]; - - unsigned int nl = (unsigned int)b[p++]; - memcpy(this->name,b.field(p,nl),std::min(nl,(unsigned int)ZT_MAX_NETWORK_SHORT_NAME_LENGTH)); - p += nl; - // _name will always be null terminated since field size is ZT_MAX_NETWORK_SHORT_NAME_LENGTH + 1 - - specialistCount = (unsigned int)b.template at<uint16_t>(p); p += 2; - if (specialistCount > ZT_MAX_NETWORK_SPECIALISTS) - throw std::invalid_argument("overflow (specialists)"); - for(unsigned int i=0;i<specialistCount;++i) { - specialists[i] = b.template at<uint64_t>(p); p += 8; - } - - routeCount = (unsigned int)b.template at<uint16_t>(p); p += 2; - if (routeCount > ZT_MAX_NETWORK_ROUTES) - throw std::invalid_argument("overflow (routes)"); - for(unsigned int i=0;i<routeCount;++i) { - p += reinterpret_cast<InetAddress *>(&(routes[i].target))->deserialize(b,p); - p += reinterpret_cast<InetAddress *>(&(routes[i].via))->deserialize(b,p); - routes[i].flags = b.template at<uint16_t>(p); p += 2; - routes[i].metric = b.template at<uint16_t>(p); p += 2; - } - - staticIpCount = (unsigned int)b.template at<uint16_t>(p); p += 2; - if (staticIpCount > ZT_MAX_ZT_ASSIGNED_ADDRESSES) - throw std::invalid_argument("overflow (static IPs)"); - for(unsigned int i=0;i<staticIpCount;++i) { - p += staticIps[i].deserialize(b,p); - } - - pinnedCount = (unsigned int)b.template at<uint16_t>(p); p += 2; - if (pinnedCount > ZT_MAX_NETWORK_PINNED) - throw std::invalid_argument("overflow (static addresses)"); - for(unsigned int i=0;i<pinnedCount;++i) { - pinned[i].zt.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH; - p += pinned[i].phy.deserialize(b,p); - } - - ruleCount = (unsigned int)b.template at<uint16_t>(p); p += 2; - if (ruleCount > ZT_MAX_NETWORK_RULES) - throw std::invalid_argument("overflow (rules)"); - for(unsigned int i=0;i<ruleCount;++i) { - rules[i].t = (uint8_t)b[p++]; - unsigned int rlen = (unsigned int)b[p++]; - switch((ZT_VirtualNetworkRuleType)(rules[i].t & 0x7f)) { - //case ZT_NETWORK_RULE_ACTION_DROP: - //case ZT_NETWORK_RULE_ACTION_ACCEPT: - default: - break; - case ZT_NETWORK_RULE_ACTION_TEE: - case ZT_NETWORK_RULE_ACTION_REDIRECT: - case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: - case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: { - Address tmp; - tmp.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - rules[i].v.zt = tmp.toInt(); - } break; - case ZT_NETWORK_RULE_MATCH_VLAN_ID: - rules[i].v.vlanId = b.template at<uint16_t>(p); - break; - case ZT_NETWORK_RULE_MATCH_VLAN_PCP: - rules[i].v.vlanPcp = (uint8_t)b[p]; - break; - case ZT_NETWORK_RULE_MATCH_VLAN_DEI: - rules[i].v.vlanDei = (uint8_t)b[p]; - break; - case ZT_NETWORK_RULE_MATCH_ETHERTYPE: - rules[i].v.etherType = b.template at<uint16_t>(p); - break; - case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: - case ZT_NETWORK_RULE_MATCH_MAC_DEST: - memcpy(rules[i].v.mac,b.field(p,6),6); - break; - case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: - case ZT_NETWORK_RULE_MATCH_IPV4_DEST: - memcpy(&(rules[i].v.ipv4.ip),b.field(p,4),4); - rules[i].v.ipv4.mask = (uint8_t)b[p+4]; - break; - case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: - case ZT_NETWORK_RULE_MATCH_IPV6_DEST: - memcpy(rules[i].v.ipv6.ip,b.field(p,16),16); - rules[i].v.ipv6.mask = (uint8_t)b[p+16]; - break; - case ZT_NETWORK_RULE_MATCH_IP_TOS: - rules[i].v.ipTos = (uint8_t)b[p]; - break; - case ZT_NETWORK_RULE_MATCH_IP_PROTOCOL: - rules[i].v.ipProtocol = (uint8_t)b[p]; - break; - case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: - case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: - rules[i].v.port[0] = b.template at<uint16_t>(p); - rules[i].v.port[1] = b.template at<uint16_t>(p+2); - break; - case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: - rules[i].v.characteristics = b.template at<uint64_t>(p); - break; - case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: - rules[i].v.frameSize[0] = b.template at<uint16_t>(p); - rules[i].v.frameSize[1] = b.template at<uint16_t>(p+2); - break; - case ZT_NETWORK_RULE_MATCH_TCP_RELATIVE_SEQUENCE_NUMBER_RANGE: - rules[i].v.tcpseq[0] = b.template at<uint32_t>(p); - rules[i].v.tcpseq[1] = b.template at<uint32_t>(p + 4); - break; - } - p += rlen; - } - - p += this->com.deserialize(b,p); - - p += b.template at<uint16_t>(p) + 2; - - return (p - startAt); - } - -#ifdef ZT_SUPPORT_OLD_STYLE_NETCONF - void fromDictionary(const char *ds,unsigned int dslen); -#endif - /* inline void dump() const { @@ -629,6 +396,8 @@ public: for(unsigned int i=0;i<routeCount;++i) { printf(" routes[i].target==%s\n",reinterpret_cast<const struct sockaddr_storage *>(&(routes[i].target))->toString().c_str()); printf(" routes[i].via==%s\n",reinterpret_cast<const struct sockaddr_storage *>(&(routes[i].via))->toIpString().c_str()); + printf(" routes[i].flags==%.4x\n",(unsigned int)routes[i].flags); + printf(" routes[i].metric==%u\n",(unsigned int)routes[i].metric); } printf("staticIpCount==%u\n",staticIpCount); for(unsigned int i=0;i<staticIpCount;++i) @@ -645,6 +414,32 @@ public: */ /** + * Add a specialist or mask flags if already present + * + * This masks the existing flags if the specialist is already here or adds + * it otherwise. + * + * @param a Address of specialist + * @param f Flags (OR of specialist role/type flags) + * @return True if successfully masked or added + */ + inline bool addSpecialist(const Address &a,const uint64_t f) + { + const uint64_t aint = a.toInt(); + for(unsigned int i=0;i<specialistCount;++i) { + if ((specialists[i] & 0xffffffffffULL) == aint) { + specialists[i] |= f; + return true; + } + } + if (specialistCount >= ZT_MAX_NETWORK_SPECIALISTS) { + specialists[specialistCount++] = f | aint; + return true; + } + return false; + } + + /** * Network ID that this configuration applies to */ uint64_t networkId; |