diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp index ebe3b4133..a833006fe 100644 --- a/node/NetworkConfig.hpp +++ b/node/NetworkConfig.hpp @@ -105,7 +105,7 @@ public: * @param etherType Ethernet frame type to check * @return True if allowed on this network */ - inline bool allowsEtherType(unsigned int etherType) + inline bool permitsEtherType(unsigned int etherType) throw() { if ((!etherType)||(etherType > 0xffff)) // sanity checks diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index 8d7a64dbc..afdf75d93 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -143,12 +143,18 @@ public: { InetAddress v4(p->ipv4ActivePath(_now)); InetAddress v6(p->ipv6ActivePath(_now)); - _P("200 listpeers %s %s %s %u %s", - p->address().toString().c_str(), - ((v4) ? v4.toString().c_str() : "-"), - ((v6) ? v6.toString().c_str() : "-"), - (((v4)||(v6)) ? p->latency() : 0), - p->remoteVersion().c_str()); + if ((v4)||(v6)) { + _P("200 listpeers %s %s %s %u %s", + p->address().toString().c_str(), + ((v4) ? v4.toString().c_str() : "-"), + ((v6) ? v6.toString().c_str() : "-"), + p->latency(), + p->remoteVersion().c_str()); + } else { + _P("200 listpeers %s - - - %s", + p->address().toString().c_str(), + p->remoteVersion().c_str()); + } } private: @@ -200,10 +206,11 @@ std::vector NodeConfig::execute(const char *command) tmp.append(i->toString()); } + SharedPtr nconf(nw->second->config2()); _P("200 listnetworks %.16llx %s %s %s %s", (unsigned long long)nw->first, Network::statusString(nw->second->status()), - (nw->second->isOpen() ? "open" : "private"), + ((nconf) ? (nconf->isOpen() ? "public" : "private") : "?"), nw->second->tap().deviceName().c_str(), ((tmp.length() > 0) ? tmp.c_str() : "-")); } diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 82f3b6afa..37b46a671 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -269,9 +269,8 @@ bool PacketDecoder::_doOK(const RuntimeEnvironment *_r,const SharedPtr &pe unsigned int dictlen = at(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN); std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen); if (dict.length()) { - Network::Config netconf(dict); + nw->setConfiguration(Dictionary(dict)); TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str()); - nw->setConfiguration(netconf); } } } break; @@ -363,7 +362,7 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr if (network) { if (network->isAllowed(source())) { unsigned int etherType = at(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); - if (network->permitsEtherType(etherType)) { + if (network->config()->permitsEtherType(etherType)) { network->tap().put(source().toMAC(),network->tap().mac(),etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD); } else if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) { TRACE("dropped FRAME from %s: ethernet type %u not allowed on network %.16llx",source().toString().c_str(),etherType,(unsigned long long)network->id()); @@ -500,78 +499,81 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared // inject the packet. This also gives us an opportunity to check things // like multicast bandwidth constraints. if (network) { - maxDepth = std::min((unsigned int)ZT_MULTICAST_GLOBAL_MAX_DEPTH,network->multicastDepth()); - if (!maxDepth) - maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH; + SharedPtr nconf(network->config2()); + if (nconf) { + maxDepth = std::min((unsigned int)ZT_MULTICAST_GLOBAL_MAX_DEPTH,nconf->multicastDepth()); + if (!maxDepth) + maxDepth = ZT_MULTICAST_GLOBAL_MAX_DEPTH; - if (!network->isAllowed(origin)) { - TRACE("didn't inject MULTICAST_FRAME from %s(%s) into %.16llx: sender %s not allowed or we don't have a certificate",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),origin.toString().c_str()); + if (!network->isAllowed(origin)) { + TRACE("didn't inject MULTICAST_FRAME from %s(%s) into %.16llx: sender %s not allowed or we don't have a certificate",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),origin.toString().c_str()); - // Tell them we need a certificate - Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); - outp.append((unsigned char)Packet::VERB_FRAME); - outp.append(packetId()); - outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); - outp.append(nwid); - outp.armor(peer->key(),true); - _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); + // Tell them we need a certificate + Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR); + outp.append((unsigned char)Packet::VERB_FRAME); + outp.append(packetId()); + outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); + outp.append(nwid); + outp.armor(peer->key(),true); + _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); - // We do not terminate here, since if the member just has an out of - // date cert or hasn't sent us a cert yet we still want to propagate - // the message so multicast keeps working downstream. - } else if ((!network->permitsBridging(origin))&&(!origin.wouldHaveMac(sourceMac))) { - // This *does* terminate propagation, since it's technically a - // security violation of the network's bridging policy. But if we - // were to keep propagating it wouldn't hurt anything, just waste - // bandwidth as everyone else would reject it too. + // We do not terminate here, since if the member just has an out of + // date cert or hasn't sent us a cert yet we still want to propagate + // the message so multicast keeps working downstream. + } else if ((!nconf->permitsBridging(origin))&&(!origin.wouldHaveMac(sourceMac))) { + // This *does* terminate propagation, since it's technically a + // security violation of the network's bridging policy. But if we + // were to keep propagating it wouldn't hurt anything, just waste + // bandwidth as everyone else would reject it too. #ifdef ZT_TRACE_MULTICAST - Utils::snprintf(mct,sizeof(mct), - "%.16llx %.2u %.3u%s %c %s dropped: bridging not allowed", - guid, - prefix, - depth, - mctdepth, - (_r->topology->amSupernode() ? 'S' : '-'), - _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + Utils::snprintf(mct,sizeof(mct), + "%.16llx %.2u %.3u%s %c %s dropped: bridging not allowed", + guid, + prefix, + depth, + mctdepth, + (_r->topology->amSupernode() ? 'S' : '-'), + _r->identity.address().toString().c_str()); + _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); #endif - TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: source mac %s doesn't belong to %s, and bridging is not supported on network",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),sourceMac.toString().c_str(),origin.toString().c_str()); - return true; - } else if (!network->permitsEtherType(etherType)) { - // Ditto for this-- halt propagation if this is for an ethertype - // this network doesn't allow. Same principle as bridging test. + TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: source mac %s doesn't belong to %s, and bridging is not supported on network",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),sourceMac.toString().c_str(),origin.toString().c_str()); + return true; + } else if (!nconf->permitsEtherType(etherType)) { + // Ditto for this-- halt propagation if this is for an ethertype + // this network doesn't allow. Same principle as bridging test. #ifdef ZT_TRACE_MULTICAST - Utils::snprintf(mct,sizeof(mct), - "%.16llx %.2u %.3u%s %c %s dropped: ethertype not allowed", - guid, - prefix, - depth, - mctdepth, - (_r->topology->amSupernode() ? 'S' : '-'), - _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + Utils::snprintf(mct,sizeof(mct), + "%.16llx %.2u %.3u%s %c %s dropped: ethertype not allowed", + guid, + prefix, + depth, + mctdepth, + (_r->topology->amSupernode() ? 'S' : '-'), + _r->identity.address().toString().c_str()); + _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); #endif - TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: ethertype %u is not allowed",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),etherType); - return true; - } else if (!network->updateAndCheckMulticastBalance(origin,dest,frameLen)) { - // Rate limits can only be checked by members of this network, but - // there should be enough of them that over-limit multicasts get - // their propagation aborted. + TRACE("dropped MULTICAST_FRAME from %s(%s) into %.16llx: ethertype %u is not allowed",source().toString().c_str(),nwid,_remoteAddress.toString().c_str(),etherType); + return true; + } else if (!network->updateAndCheckMulticastBalance(origin,dest,frameLen)) { + // Rate limits can only be checked by members of this network, but + // there should be enough of them that over-limit multicasts get + // their propagation aborted. #ifdef ZT_TRACE_MULTICAST - Utils::snprintf(mct,sizeof(mct), - "%.16llx %.2u %.3u%s %c %s dropped: rate limits exceeded", - guid, - prefix, - depth, - mctdepth, - (_r->topology->amSupernode() ? 'S' : '-'), - _r->identity.address().toString().c_str()); - _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); + Utils::snprintf(mct,sizeof(mct), + "%.16llx %.2u %.3u%s %c %s dropped: rate limits exceeded", + guid, + prefix, + depth, + mctdepth, + (_r->topology->amSupernode() ? 'S' : '-'), + _r->identity.address().toString().c_str()); + _r->demarc->send(Demarc::ANY_PORT,ZT_DEFAULTS.multicastTraceWatcher,mct,strlen(mct),-1); #endif - TRACE("dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str()); - return true; - } else { - network->tap().put(sourceMac,dest.mac(),etherType,frame,frameLen); + TRACE("dropped MULTICAST_FRAME from %s(%s): rate limits exceeded for sender %s",source().toString().c_str(),_remoteAddress.toString().c_str(),origin.toString().c_str()); + return true; + } else { + network->tap().put(sourceMac,dest.mac(),etherType,frame,frameLen); + } } } } diff --git a/node/Switch.cpp b/node/Switch.cpp index 371840766..14f6c5066 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -82,6 +82,10 @@ void Switch::onRemotePacket(Demarc::Port localPort,const InetAddress &fromAddr,c void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,const MAC &to,unsigned int etherType,const Buffer<4096> &data) { + SharedPtr nconf(network->config2()); + if (!nconf) + return; + if (to == network->tap().mac()) { LOG("%s: frame received from self, ignoring (bridge loop? OS bug?)",network->tap().deviceName().c_str()); return; @@ -92,7 +96,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c return; } - if (!network->permitsEtherType(etherType)) { + if (!nconf->permitsEtherType(etherType)) { LOG("ignored tap: %s -> %s: ethertype %s not allowed on network %.16llx",from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),(unsigned long long)network->id()); return; } @@ -115,11 +119,11 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c const SharedPtr supernode(_r->topology->getBestSupernode()); uint64_t now = Utils::now(); - for(unsigned int prefix=0,np=((unsigned int)2 << (network->multicastPrefixBits() - 1));prefixmulticastPrefixBits() - 1));prefixmc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),network->multicastPrefixBits(),prefix)); + _r->mc->getNextHops(network->id(),mg,Multicaster::AddToPropagationQueue(&fifoPtr,fifoEnd,bloom,bloomNonce,_r->identity.address(),nconf->multicastPrefixBits(),prefix)); while (fifoPtr != fifoEnd) *(fifoPtr++) = (unsigned char)0; @@ -143,7 +147,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append((unsigned char)0); outp.append(network->id()); outp.append(bloomNonce); - outp.append((unsigned char)network->multicastPrefixBits()); + outp.append((unsigned char)nconf->multicastPrefixBits()); outp.append((unsigned char)prefix); _r->identity.address().appendTo(outp); outp.append((unsigned char)((mcid >> 16) & 0xff));