From 80d8b7d0ae56f1dce8b5b25ab7930df436755daf Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Fri, 2 Aug 2013 17:17:34 -0400 Subject: [PATCH] Netconf wired up, ready to test. --- netconf-service/netconf.cpp | 16 ++++++++++++ node/Node.cpp | 46 ++++++++++++++++++++++++++++++++ node/Packet.hpp | 13 ++++++++++ node/PacketDecoder.cpp | 52 +++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/netconf-service/netconf.cpp b/netconf-service/netconf.cpp index 01f331205..af6ed4e67 100644 --- a/netconf-service/netconf.cpp +++ b/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; diff --git a/node/Node.cpp b/node/Node.cpp index e67dd5261..8079e8016 100644 --- a/node/Node.cpp +++ b/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 = _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() : diff --git a/node/Packet.hpp b/node/Packet.hpp index 1d63929bd..0e7ccea3f 100644 --- a/node/Packet.hpp +++ b/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) diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 0353625c2..518ed9e74 100644 --- a/node/PacketDecoder.cpp +++ b/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) { + // TODO: not implemented yet, will be needed for private networks. + + return true; } bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const SharedPtr &peer) { + char tmp[128]; + try { + uint64_t nwid = at(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID); +#ifndef __WINDOWS__ + if (_r->netconfService) { + unsigned int dictLen = at(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) { + try { + uint64_t nwid = at(ZT_PROTO_VERB_NETWORK_CONFIG_REFRESH_IDX_NETWORK_ID); + SharedPtr 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