|
@@ -189,16 +189,16 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Do we already have this peer?
|
|
SharedPtr<Peer> peer(_r->topology->getPeer(id.address()));
|
|
SharedPtr<Peer> peer(_r->topology->getPeer(id.address()));
|
|
if (peer) {
|
|
if (peer) {
|
|
|
|
+ // Check to make sure this isn't a colliding identity (different key,
|
|
|
|
+ // but same address). The odds are spectacularly low but it could happen.
|
|
|
|
+ // Could also be a sign of someone doing something nasty.
|
|
if (peer->identity() != id) {
|
|
if (peer->identity() != id) {
|
|
- // Sorry, someone beat you to that address. What are the odds?
|
|
|
|
- // Well actually they're around two in 2^40. You should play
|
|
|
|
- // the lottery.
|
|
|
|
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
|
unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
|
if (_r->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
|
if (_r->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
|
TRACE("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
TRACE("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
-
|
|
|
|
Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
|
|
Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
|
|
outp.append((unsigned char)Packet::VERB_HELLO);
|
|
outp.append((unsigned char)Packet::VERB_HELLO);
|
|
outp.append(packetId());
|
|
outp.append(packetId());
|
|
@@ -209,7 +209,26 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r)
|
|
return true;
|
|
return true;
|
|
} // else continue and send OK since we already know thee...
|
|
} // else continue and send OK since we already know thee...
|
|
} else {
|
|
} else {
|
|
- // Learn a new peer
|
|
|
|
|
|
+ // If we don't have a peer record on file, check the identity cache (if
|
|
|
|
+ // we have one) to see if we have a cached identity. Then check that for
|
|
|
|
+ // collision before adding a new peer.
|
|
|
|
+ Identity alreadyHaveCachedId(_r->topology->getIdentity(id.address()));
|
|
|
|
+ if ((alreadyHaveCachedId)&&(id != alreadyHaveCachedId)) {
|
|
|
|
+ unsigned char key[ZT_PEER_SECRET_KEY_LENGTH];
|
|
|
|
+ if (_r->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
|
|
|
|
+ TRACE("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str());
|
|
|
|
+ Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
|
|
|
|
+ outp.append((unsigned char)Packet::VERB_HELLO);
|
|
|
|
+ outp.append(packetId());
|
|
|
|
+ outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION);
|
|
|
|
+ outp.armor(key,true);
|
|
|
|
+ _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Learn a new peer if it's new. This also adds it to the identity
|
|
|
|
+ // cache if that's enabled.
|
|
peer = _r->topology->addPeer(SharedPtr<Peer>(new Peer(_r->identity,id)));
|
|
peer = _r->topology->addPeer(SharedPtr<Peer>(new Peer(_r->identity,id)));
|
|
}
|
|
}
|
|
|
|
|