Browse Source

Netconf wired up, ready to test.

Adam Ierymenko 12 years ago
parent
commit
80d8b7d0ae
4 changed files with 127 additions and 0 deletions
  1. 16 0
      netconf-service/netconf.cpp
  2. 46 0
      node/Node.cpp
  3. 13 0
      node/Packet.hpp
  4. 52 0
      node/PacketDecoder.cpp

+ 16 - 0
netconf-service/netconf.cpp

@@ -219,6 +219,22 @@ int main(int argc,char **argv)
 					StoreQueryResult rs = q.store();
 					if (rs.num_rows() > 0)
 						isOpen = ((int)rs[0]["isOpen"] > 0);
+					else {
+						Dictionary response;
+						response["peer"] = peerIdentity.address().toString();
+						response["nwid"] = request.get("nwid");
+						response["type"] = "netconf-response";
+						response["requestId"] = request.get("requestId");
+						response["error"] = "NOT_FOUND";
+						std::string respm = response.toString();
+						uint32_t respml = (uint32_t)htonl((uint32_t)respm.length());
+
+						stdoutWriteLock.lock();
+						write(STDOUT_FILENO,&respml,4);
+						write(STDOUT_FILENO,respm.data(),respm.length());
+						stdoutWriteLock.unlock();
+						continue;
+					}
 				}
 
 				Dictionary netconf;

+ 46 - 0
node/Node.cpp

@@ -50,6 +50,7 @@
 #include "Node.hpp"
 #include "Topology.hpp"
 #include "Demarc.hpp"
+#include "Packet.hpp"
 #include "Switch.hpp"
 #include "Utils.hpp"
 #include "EthernetTap.hpp"
@@ -192,9 +193,54 @@ struct _NodeImpl
 	}
 };
 
+#ifndef __WINDOWS__
 static void _netconfServiceMessageHandler(void *renv,Service &svc,const Dictionary &msg)
 {
+	if (!renv)
+		return; // sanity check
+	const RuntimeEnvironment *_r = (const RuntimeEnvironment *)renv;
+
+	try {
+		const std::string &type = msg.get("type");
+		if (type == "netconf-response") {
+			uint64_t inRePacketId = strtoull(msg.get("requestId").c_str(),(char **)0,16);
+			SharedPtr<Network> network = _r->nc->network(strtoull(msg.get("nwid").c_str(),(char **)0,16));
+			Address peerAddress(msg.get("peer").c_str());
+
+			if ((network)&&(peerAddress)) {
+				if (msg.contains("error")) {
+					Packet::ErrorCode errCode = Packet::ERROR_INVALID_REQUEST;
+					const std::string &err = msg.get("error");
+					if (err == "NOT_FOUND")
+						errCode = Packet::ERROR_NOT_FOUND;
+
+					Packet outp(peerAddress,_r->identity.address(),Packet::VERB_ERROR);
+					outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+					outp.append(inRePacketId);
+					outp.append((unsigned char)errCode);
+					outp.append(network->id());
+					_r->sw->send(outp,true);
+				} else if (msg.contains("netconf")) {
+					const std::string &netconf = msg.get("netconf");
+					if (netconf.length() < 2048) { // sanity check
+						Packet outp(peerAddress,_r->identity.address(),Packet::VERB_OK);
+						outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+						outp.append(inRePacketId);
+						outp.append(network->id());
+						outp.append((uint16_t)netconf.length());
+						outp.append(netconf.data(),netconf.length());
+						_r->sw->send(outp,true);
+					}
+				}
+			}
+		}
+	} catch (std::exception &exc) {
+		LOG("unexpected exception parsing response from netconf service: %s",exc.what());
+	} catch ( ... ) {
+		LOG("unexpected exception parsing response from netconf service: unknown exception");
+	}
 }
+#endif // !__WINDOWS__
 
 Node::Node(const char *hp)
 	throw() :

+ 13 - 0
node/Packet.hpp

@@ -132,27 +132,34 @@
 #define ZT_PROTO_VERB_MULTICAST_FRAME_BLOOM_FILTER_SIZE_BYTES 64
 
 // Field incides for parsing verbs
+
 #define ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION + 1)
 #define ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION (ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION + 1)
 #define ZT_PROTO_VERB_HELLO_IDX_REVISION (ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION + 1)
 #define ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP (ZT_PROTO_VERB_HELLO_IDX_REVISION + 2)
 #define ZT_PROTO_VERB_HELLO_IDX_IDENTITY (ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP + 8)
+
 #define ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID (ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB + 1)
 #define ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE (ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID + 8)
 #define ZT_PROTO_VERB_ERROR_IDX_PAYLOAD (ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE + 1)
+
 #define ZT_PROTO_VERB_OK_IDX_IN_RE_VERB (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID (ZT_PROTO_VERB_OK_IDX_IN_RE_VERB + 1)
 #define ZT_PROTO_VERB_OK_IDX_PAYLOAD (ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID + 8)
+
 #define ZT_PROTO_VERB_WHOIS_IDX_ZTADDRESS (ZT_PACKET_IDX_PAYLOAD)
+
 #define ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT (ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS + 5)
 #define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN (ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT + 2)
 #define ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS (ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN + 1)
+
 #define ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
 #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_MULTICAST_FRAME_IDX_FLAGS (ZT_PACKET_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS + 1)
 #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SUBMITTER_ADDRESS (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID + 8)
@@ -166,6 +173,12 @@
 #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD_LENGTH + 2)
 #define ZT_PROTO_VERB_MULTICAST_FRAME_IDX_PAYLOAD (ZT_PROTO_VERB_MULTICAST_FRAME_IDX_SIGNATURE_LENGTH + 2)
 
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID + 8)
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT (ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN + 2)
+
+#define ZT_PROTO_VERB_NETWORK_CONFIG_REFRESH_IDX_NETWORK_ID (ZT_PACKET_IDX_PAYLOAD)
+
 // Field indices for parsing OK and ERROR payloads of replies
 #define ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP (ZT_PROTO_VERB_OK_IDX_PAYLOAD)
 #define ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY (ZT_PROTO_VERB_OK_IDX_PAYLOAD)

+ 52 - 0
node/PacketDecoder.cpp

@@ -25,6 +25,7 @@
  * LLC. Start here: http://www.zerotier.com/
  */
 
+#include "Constants.hpp"
 #include "RuntimeEnvironment.hpp"
 #include "Topology.hpp"
 #include "PacketDecoder.hpp"
@@ -32,6 +33,7 @@
 #include "Peer.hpp"
 #include "NodeConfig.hpp"
 #include "Filter.hpp"
+#include "Service.hpp"
 
 namespace ZeroTier {
 
@@ -546,14 +548,64 @@ bool PacketDecoder::_doMULTICAST_FRAME(const RuntimeEnvironment *_r,const Shared
 
 bool PacketDecoder::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
 {
+	// TODO: not implemented yet, will be needed for private networks.
+
+	return true;
 }
 
 bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
 {
+	char tmp[128];
+	try {
+		uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID);
+#ifndef __WINDOWS__
+		if (_r->netconfService) {
+			unsigned int dictLen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN);
+			std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,dictLen),dictLen);
+
+			Dictionary request;
+			request["type"] = "netconf-request";
+			request["peerId"] = peer->identity().toString(false);
+			sprintf(tmp,"%llx",(unsigned long long)nwid);
+			request["nwid"] = tmp;
+			sprintf(tmp,"%llx",(unsigned long long)packetId());
+			request["requestId"] = tmp;
+			_r->netconfService->send(request);
+		} else {
+#endif // !__WINDOWS__
+			Packet outp(source(),_r->identity.address(),Packet::VERB_ERROR);
+			outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
+			outp.append(packetId());
+			outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
+			outp.append(nwid);
+			outp.encrypt(peer->cryptKey());
+			outp.hmacSet(peer->macKey());
+			_r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1);
+			TRACE("sent ERROR(NETWORK_CONFIG_REQUEST,UNSUPPORTED_OPERATION) to %s(%s)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
+#ifndef __WINDOWS__
+		}
+#endif // !__WINDOWS__
+	} catch (std::exception &exc) {
+		TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what());
+	} catch ( ... ) {
+		TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: (unknown)",source().toString().c_str(),_remoteAddress.toString().c_str());
+	}
+	return true;
 }
 
 bool PacketDecoder::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *_r,const SharedPtr<Peer> &peer)
 {
+	try {
+		uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REFRESH_IDX_NETWORK_ID);
+		SharedPtr<Network> nw(_r->nc->network(nwid));
+		if ((nw)&&(source() == nw->controller())) // only respond to requests from controller
+			nw->requestConfiguration();
+	} catch (std::exception &exc) {
+		TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what());
+	} catch ( ... ) {
+		TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: (unknown)",source().toString().c_str(),_remoteAddress.toString().c_str());
+	}
+	return true;
 }
 
 } // namespace ZeroTier