mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-08 19:48:42 +00:00
Packet decoder work for EXT_FRAME for bridging - GitHub issue #68
This commit is contained in:
parent
d44e1349d8
commit
c30f9832b0
@ -371,21 +371,6 @@ public:
|
|||||||
t->put(from,to,etherType,data,len);
|
t->put(from,to,etherType,data,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject a frame into tap with local MAC as destination MAC (if it's created)
|
|
||||||
*
|
|
||||||
* @param from Origin MAC
|
|
||||||
* @param etherType Ethernet frame type
|
|
||||||
* @param data Frame data
|
|
||||||
* @param len Frame length
|
|
||||||
*/
|
|
||||||
inline void tapPut(const MAC &from,unsigned int etherType,const void *data,unsigned int len)
|
|
||||||
{
|
|
||||||
EthernetTap *t = _tap;
|
|
||||||
if (t)
|
|
||||||
t->put(from,t->mac(),etherType,data,len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Tap device name or empty string if still initializing
|
* @return Tap device name or empty string if still initializing
|
||||||
*/
|
*/
|
||||||
@ -401,6 +386,7 @@ public:
|
|||||||
* @return Ethernet MAC address for this network's local interface
|
* @return Ethernet MAC address for this network's local interface
|
||||||
*/
|
*/
|
||||||
inline const MAC &mac() const
|
inline const MAC &mac() const
|
||||||
|
throw()
|
||||||
{
|
{
|
||||||
return _mac;
|
return _mac;
|
||||||
}
|
}
|
||||||
@ -416,6 +402,20 @@ public:
|
|||||||
return std::set<InetAddress>();
|
return std::set<InetAddress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for config()->permitsBridging(), returns false if no config
|
||||||
|
*
|
||||||
|
* @param peer Peer address to check
|
||||||
|
* @return True if peer can bridge other Ethernet nodes into this network or network is in permissive bridging mode
|
||||||
|
*/
|
||||||
|
inline bool permitsBridging(const Address &peer) const
|
||||||
|
{
|
||||||
|
Mutex::Lock _l(_lock);
|
||||||
|
if (_config)
|
||||||
|
return _config->permitsBridging(peer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mac MAC address
|
* @param mac MAC address
|
||||||
* @return ZeroTier address of bridge to this MAC or null address if not found
|
* @return ZeroTier address of bridge to this MAC or null address if not found
|
||||||
|
@ -176,6 +176,16 @@
|
|||||||
#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
|
#define ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + 8)
|
||||||
#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
|
#define ZT_PROTO_VERB_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
|
||||||
|
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_LEN_NETWORK_ID 8
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_IDX_TO (ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID + ZT_PROTO_VERB_EXT_FRAME_LEN_NETWORK_ID)
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_LEN_TO 6
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_IDX_FROM (ZT_PROTO_VERB_EXT_FRAME_IDX_TO + ZT_PROTO_VERB_EXT_FRAME_LEN_TO)
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_LEN_FROM 6
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE (ZT_PROTO_VERB_EXT_FRAME_IDX_FROM + ZT_PROTO_VERB_EXT_FRAME_LEN_FROM)
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_LEN_ETHERTYPE 2
|
||||||
|
#define ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE + 2)
|
||||||
|
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH (ZT_PACKET_IDX_PAYLOAD)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH (ZT_PACKET_IDX_PAYLOAD)
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH 2
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH 2
|
||||||
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH)
|
#define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_FIFO (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PROPAGATION_DEPTH + ZT_PROTO_VERB_MULTICAST_FRAME_LEN_PROPAGATION_DEPTH)
|
||||||
|
@ -405,47 +405,44 @@ bool PacketDecoder::_doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr<P
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
|
bool PacketDecoder::_incomingFrame(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
|
||||||
{
|
{
|
||||||
try {
|
if (network->isAllowed(peer->address())) {
|
||||||
SharedPtr<Network> network(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)));
|
|
||||||
if (network) {
|
|
||||||
if (network->isAllowed(source())) {
|
|
||||||
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
|
|
||||||
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) {
|
|
||||||
if (network->config()->permitsEtherType(etherType)) {
|
if (network->config()->permitsEtherType(etherType)) {
|
||||||
network->tapPut(
|
network->tapPut(from,to,etherType,data,len);
|
||||||
MAC(source(),network->id()),
|
|
||||||
etherType,
|
|
||||||
data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,
|
|
||||||
size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
|
|
||||||
} else {
|
|
||||||
TRACE("dropped FRAME from %s: ethernet type %u not allowed on network %.16llx",source().toString().c_str(),etherType,(unsigned long long)network->id());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else return true; // ignore empty frames
|
|
||||||
|
|
||||||
// Source moves "closer" to us in multicast propagation priority when
|
/* Source moves "closer" to us in multicast propagation priority when
|
||||||
// we receive unicast frames from it. This is called "implicit social
|
* we receive unicast frames from it. This is called "implicit social
|
||||||
// ordering" in other docs.
|
* ordering" in other docs. */
|
||||||
_r->mc->bringCloser(network->id(),source());
|
_r->mc->bringCloser(network->id(),peer->address());
|
||||||
peer->receive(_r,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now());
|
peer->receive(_r,_fromSock,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP,Utils::now());
|
||||||
} else {
|
} else {
|
||||||
TRACE("dropped FRAME from %s(%s): sender not a member of closed network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
|
TRACE("dropped %s from %s@%s: ethernet type %u not allowed on network %.16llx",Packet::verbString(verb()),from.toString().c_str(),peer->address().toString().c_str(),etherType,(unsigned long long)network->id());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TRACE("dropped %s from %s(%s): peer not a member of closed network %.16llx",Packet::verbString(verb()),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),network->id());
|
||||||
|
|
||||||
Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
|
Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
|
||||||
outp.append((unsigned char)Packet::VERB_FRAME);
|
outp.append((unsigned char)verb());
|
||||||
outp.append(packetId());
|
outp.append(packetId());
|
||||||
outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
||||||
outp.append(network->id());
|
outp.append(network->id());
|
||||||
outp.armor(peer->key(),true);
|
outp.armor(peer->key(),true);
|
||||||
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
_fromSock->send(_remoteAddress,outp.data(),outp.size());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
SharedPtr<Network> network(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)));
|
||||||
|
if (network) {
|
||||||
|
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE);
|
||||||
|
if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD)
|
||||||
|
_incomingFrame(_r,peer,network,MAC(peer->address(),network->id()),network->mac(),etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
|
||||||
} else {
|
} else {
|
||||||
TRACE("dropped FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
|
TRACE("dropped FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
TRACE("dropped FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
|
TRACE("dropped FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
|
||||||
@ -457,6 +454,47 @@ bool PacketDecoder::_doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer>
|
|||||||
|
|
||||||
bool PacketDecoder::_doEXT_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
|
bool PacketDecoder::_doEXT_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
|
SharedPtr<Network> network(_r->nc->network(at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID)));
|
||||||
|
if (network) {
|
||||||
|
const MAC to(field(ZT_PROTO_VERB_EXT_FRAME_IDX_TO,ZT_PROTO_VERB_EXT_FRAME_LEN_TO),ZT_PROTO_VERB_EXT_FRAME_LEN_TO);
|
||||||
|
const MAC from(field(ZT_PROTO_VERB_EXT_FRAME_IDX_FROM,ZT_PROTO_VERB_EXT_FRAME_LEN_FROM),ZT_PROTO_VERB_EXT_FRAME_LEN_FROM);
|
||||||
|
unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE);
|
||||||
|
if (size() > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD) {
|
||||||
|
if ((!from)||(from.isMulticast())||(!to)) {
|
||||||
|
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: invalid source or destination MAC",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from != MAC(peer->address(),network->id())) {
|
||||||
|
if (network->permitsBridging(peer->address())) {
|
||||||
|
network->learnBridgeRoute(from,peer->address());
|
||||||
|
} else {
|
||||||
|
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: sender not allowed to bridge into %.16llx",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to != network->mac()) {
|
||||||
|
/* For security reasons we should block incoming bridge packets if
|
||||||
|
* we are not a bridge. Bridging is a two way street, and unwanted
|
||||||
|
* bridging might open doors to strange things on untrusted nets. */
|
||||||
|
if (!network->permitsBridging(_r->identity.address())) {
|
||||||
|
TRACE("dropped EXT_FRAME from %s@%s(%s) to %s: I cannot bridge to %.16llx or bridging disabled on network",from.toString().c_str(),peer->address().toString().c_str(),_remoteAddress.toString().c_str(),to.toString().c_str(),network->id());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_incomingFrame(_r,peer,network,from,to,etherType,data() + ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD);
|
||||||
|
} else return true; // ignore empty frames
|
||||||
|
} else {
|
||||||
|
TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID));
|
||||||
|
}
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
TRACE("dropped EXT_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what());
|
||||||
|
} catch ( ... ) {
|
||||||
|
TRACE("dropped EXT_FRAME from %s(%s): unexpected exception: (unknown)",source().toString().c_str(),_remoteAddress.toString().c_str());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class RuntimeEnvironment;
|
class RuntimeEnvironment;
|
||||||
|
class Network;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of packet that handles the decoding of it
|
* Subclass of packet that handles the decoding of it
|
||||||
@ -116,6 +117,7 @@ private:
|
|||||||
bool _doOK(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doOK(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
bool _doWHOIS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doWHOIS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
bool _doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doRENDEZVOUS(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
|
bool _incomingFrame(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer,const SharedPtr<Network> &network,const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len);
|
||||||
bool _doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doFRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
bool _doEXT_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doEXT_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
bool _doMULTICAST_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
bool _doMULTICAST_FRAME(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer);
|
||||||
|
@ -112,7 +112,7 @@ void Peer::receive(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verb == Packet::VERB_FRAME)
|
if ((verb == Packet::VERB_FRAME)||(verb == Packet::VERB_EXT_FRAME))
|
||||||
_lastUnicastFrame = now;
|
_lastUnicastFrame = now;
|
||||||
else if (verb == Packet::VERB_MULTICAST_FRAME)
|
else if (verb == Packet::VERB_MULTICAST_FRAME)
|
||||||
_lastMulticastFrame = now;
|
_lastMulticastFrame = now;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user