testnet.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * ZeroTier One - Global Peer to Peer Ethernet
  3. * Copyright (C) 2011-2014 ZeroTier Networks LLC
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * ZeroTier may be used and distributed under the terms of the GPLv3, which
  21. * are available at: http://www.gnu.org/licenses/gpl-3.0.html
  22. *
  23. * If you would like to embed ZeroTier into a commercial application or
  24. * redistribute it in a modified binary form, please contact ZeroTier Networks
  25. * LLC. Start here: http://www.zerotier.com/
  26. */
  27. /* SEE: testnet/README.md */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <stdint.h>
  31. #include <string.h>
  32. #include <string>
  33. #include <map>
  34. #include <vector>
  35. #include <set>
  36. #include "node/Constants.hpp"
  37. #include "node/Node.hpp"
  38. #include "node/Utils.hpp"
  39. #include "node/Address.hpp"
  40. #include "node/Identity.hpp"
  41. #include "node/Thread.hpp"
  42. #include "node/CMWC4096.hpp"
  43. #include "node/Dictionary.hpp"
  44. #include "testnet/SimNet.hpp"
  45. #include "testnet/SimNetSocketManager.hpp"
  46. #include "testnet/TestEthernetTap.hpp"
  47. #include "testnet/TestEthernetTapFactory.hpp"
  48. #include "testnet/TestRoutingTable.hpp"
  49. #ifdef __WINDOWS__
  50. #include <windows.h>
  51. #else
  52. #include <unistd.h>
  53. #include <sys/stat.h>
  54. #endif
  55. using namespace ZeroTier;
  56. class SimNode
  57. {
  58. public:
  59. SimNode(SimNet &net,const std::string &hp,const char *rootTopology,bool issn,const InetAddress &addr) :
  60. home(hp),
  61. tapFactory(),
  62. routingTable(),
  63. socketManager(net.newEndpoint(addr)),
  64. node(home.c_str(),&tapFactory,&routingTable,socketManager,false,rootTopology),
  65. reasonForTermination(Node::NODE_RUNNING),
  66. supernode(issn)
  67. {
  68. thread = Thread::start(this);
  69. }
  70. ~SimNode()
  71. {
  72. node.terminate(Node::NODE_NORMAL_TERMINATION,"SimNode shutdown");
  73. Thread::join(thread);
  74. }
  75. void threadMain()
  76. throw()
  77. {
  78. reasonForTermination = node.run();
  79. }
  80. std::string home;
  81. TestEthernetTapFactory tapFactory;
  82. TestRoutingTable routingTable;
  83. SimNetSocketManager *socketManager;
  84. Node node;
  85. Node::ReasonForTermination reasonForTermination;
  86. bool supernode;
  87. Thread thread;
  88. };
  89. static std::string basePath;
  90. static SimNet net;
  91. static std::map< Address,SimNode * > nodes;
  92. static std::map< InetAddress,Address > usedIps;
  93. static CMWC4096 prng;
  94. static std::string rootTopology;
  95. // Converts an address into a fake IP not already claimed.
  96. // Be sure to call only once, as this claims the IP before returning it.
  97. static InetAddress inetAddressFromZeroTierAddress(const Address &addr)
  98. {
  99. uint32_t ip = (uint32_t)(addr.toInt() & 0xffffffff);
  100. for(;;) {
  101. if (((ip >> 24) & 0xff) >= 240) {
  102. ip &= 0x00ffffff;
  103. ip |= (((ip >> 24) & 0xff) % 240) << 24;
  104. }
  105. if (((ip >> 24) & 0xff) == 0)
  106. ip |= 0x01000000;
  107. if (((ip & 0xff) == 0)||((ip & 0xff) == 255))
  108. ip ^= 0x00000001;
  109. InetAddress inaddr(Utils::hton(ip),9993);
  110. if (usedIps.find(inaddr) == usedIps.end()) {
  111. usedIps[inaddr] = addr;
  112. return inaddr;
  113. }
  114. ++ip; // keep looking sequentially for an unclaimed IP
  115. }
  116. }
  117. static Identity makeNodeHome(bool super)
  118. {
  119. Identity id;
  120. id.generate();
  121. std::string path(basePath + ZT_PATH_SEPARATOR_S + (super ? "S" : "N") + id.address().toString());
  122. #ifdef __WINDOWS__
  123. CreateDirectoryA(path.c_str(),NULL);
  124. #else
  125. mkdir(path.c_str(),0700);
  126. #endif
  127. if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.secret").c_str(),id.toString(true)))
  128. return Identity();
  129. if (!Utils::writeFile((path + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),id.toString(false)))
  130. return Identity();
  131. return id;
  132. }
  133. // Instantiates supernodes by scanning for S########## subdirectories
  134. static std::vector<Address> initSupernodes()
  135. {
  136. Dictionary supernodes;
  137. std::vector< std::pair<Identity,InetAddress> > snids;
  138. std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
  139. for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
  140. if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'S')) {
  141. std::string idbuf;
  142. if (Utils::readFile((basePath + ZT_PATH_SEPARATOR_S + d->first + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),idbuf)) {
  143. Identity id(idbuf);
  144. if (id) {
  145. InetAddress inaddr(inetAddressFromZeroTierAddress(id.address()));
  146. snids.push_back(std::pair<Identity,InetAddress>(id,inaddr));
  147. Dictionary snd;
  148. snd["id"] = id.toString(false);
  149. snd["udp"] = inaddr.toString();
  150. snd["desc"] = id.address().toString();
  151. snd["dns"] = inaddr.toIpString();
  152. supernodes[id.address().toString()] = snd.toString();
  153. }
  154. }
  155. }
  156. }
  157. Dictionary rtd;
  158. rtd["supernodes"] = supernodes.toString();
  159. rtd["noupdate"] = "1";
  160. rootTopology = rtd.toString();
  161. std::vector<Address> newNodes;
  162. for(std::vector< std::pair<Identity,InetAddress> >::iterator i(snids.begin());i!=snids.end();++i) {
  163. SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + "S" + i->first.address().toString()),rootTopology.c_str(),true,i->second);
  164. nodes[i->first.address()] = n;
  165. newNodes.push_back(i->first.address());
  166. }
  167. return newNodes;
  168. }
  169. // Instantiates any not-already-instantiated regular nodes
  170. static std::vector<Address> scanForNewNodes()
  171. {
  172. std::vector<Address> newNodes;
  173. std::map<std::string,bool> dir(Utils::listDirectory(basePath.c_str()));
  174. for(std::map<std::string,bool>::iterator d(dir.begin());d!=dir.end();++d) {
  175. if ((d->first.length() == 11)&&(d->second)&&(d->first[0] == 'N')) {
  176. Address na(d->first.c_str() + 1);
  177. if (nodes.find(na) == nodes.end()) {
  178. InetAddress inaddr(inetAddressFromZeroTierAddress(na));
  179. SimNode *n = new SimNode(net,(basePath + ZT_PATH_SEPARATOR_S + d->first),rootTopology.c_str(),false,inaddr);
  180. nodes[na] = n;
  181. newNodes.push_back(na);
  182. }
  183. }
  184. }
  185. return newNodes;
  186. }
  187. static void doHelp(const std::vector<std::string> &cmd)
  188. {
  189. printf("---------- help"ZT_EOL_S);
  190. printf("---------- mksn <number of supernodes>"ZT_EOL_S);
  191. printf("---------- mkn <number of normal nodes>"ZT_EOL_S);
  192. printf("---------- list"ZT_EOL_S);
  193. printf("---------- join <address/*/**> <network ID>"ZT_EOL_S);
  194. printf("---------- leave <address/*/**> <network ID>"ZT_EOL_S);
  195. printf("---------- listnetworks <address/*/**>"ZT_EOL_S);
  196. printf("---------- listpeers <address/*/**>"ZT_EOL_S);
  197. printf("---------- unicast <address/*/**> <address/*/**> <network ID> <frame length, min: 16> [<timeout (sec)>]"ZT_EOL_S);
  198. printf("---------- multicast <address/*/**> <MAC/* for bcast> <network ID> <frame length, min: 16> [<timeout (sec)>]"ZT_EOL_S);
  199. printf("---------- quit"ZT_EOL_S);
  200. printf("---------- ( * means all regular nodes, ** means including supernodes )"ZT_EOL_S);
  201. printf("---------- ( . runs previous command again )"ZT_EOL_S);
  202. }
  203. static void doMKSN(const std::vector<std::string> &cmd)
  204. {
  205. if (cmd.size() < 2) {
  206. doHelp(cmd);
  207. return;
  208. }
  209. if (nodes.size() > 0) {
  210. printf("---------- mksn error: mksn can only be called once (network already exists)"ZT_EOL_S);
  211. return;
  212. }
  213. int count = Utils::strToInt(cmd[1].c_str());
  214. for(int i=0;i<count;++i) {
  215. Identity id(makeNodeHome(true));
  216. printf("%s identity created"ZT_EOL_S,id.address().toString().c_str());
  217. }
  218. std::vector<Address> nodes(initSupernodes());
  219. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  220. printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
  221. //printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
  222. }
  223. static void doMKN(const std::vector<std::string> &cmd)
  224. {
  225. if (cmd.size() < 2) {
  226. doHelp(cmd);
  227. return;
  228. }
  229. if (nodes.size() == 0) {
  230. printf("---------- mkn error: use mksn to create supernodes first."ZT_EOL_S);
  231. return;
  232. }
  233. int count = Utils::strToInt(cmd[1].c_str());
  234. for(int i=0;i<count;++i) {
  235. Identity id(makeNodeHome(false));
  236. printf("%s identity created"ZT_EOL_S,id.address().toString().c_str());
  237. }
  238. std::vector<Address> nodes(scanForNewNodes());
  239. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  240. printf("%s started (regular node)"ZT_EOL_S,a->toString().c_str());
  241. }
  242. static void doList(const std::vector<std::string> &cmd)
  243. {
  244. unsigned int peers = 0,supernodes = 0;
  245. ZT1_Node_Status status;
  246. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  247. n->second->node.status(&status);
  248. if (status.initialized) {
  249. printf("%s %c %s (%u peers, %u direct links)"ZT_EOL_S,
  250. n->first.toString().c_str(),
  251. n->second->supernode ? 'S' : 'N',
  252. (status.online ? "ONLINE" : "OFFLINE"),
  253. status.knownPeers,
  254. status.directlyConnectedPeers);
  255. if (n->second->supernode)
  256. ++supernodes;
  257. else ++peers;
  258. } else printf("%s ? INITIALIZING (0 peers, 0 direct links)"ZT_EOL_S,n->first.toString().c_str());
  259. }
  260. printf("---------- %u regular peers, %u supernodes"ZT_EOL_S,peers,supernodes);
  261. }
  262. static void doJoin(const std::vector<std::string> &cmd)
  263. {
  264. if (cmd.size() < 3) {
  265. doHelp(cmd);
  266. return;
  267. }
  268. std::vector<Address> addrs;
  269. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  270. bool includeSuper = (cmd[1] == "**");
  271. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  272. if ((includeSuper)||(!n->second->supernode))
  273. addrs.push_back(n->first);
  274. }
  275. } else addrs.push_back(Address(cmd[1]));
  276. uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str());
  277. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  278. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  279. if (n != nodes.end()) {
  280. n->second->node.join(nwid);
  281. printf("%s join %.16llx"ZT_EOL_S,n->first.toString().c_str(),nwid);
  282. }
  283. }
  284. }
  285. static void doLeave(const std::vector<std::string> &cmd)
  286. {
  287. if (cmd.size() < 3) {
  288. doHelp(cmd);
  289. return;
  290. }
  291. std::vector<Address> addrs;
  292. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  293. bool includeSuper = (cmd[1] == "**");
  294. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  295. if ((includeSuper)||(!n->second->supernode))
  296. addrs.push_back(n->first);
  297. }
  298. } else addrs.push_back(Address(cmd[1]));
  299. uint64_t nwid = Utils::hexStrToU64(cmd[2].c_str());
  300. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  301. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  302. if (n != nodes.end()) {
  303. n->second->node.leave(nwid);
  304. printf("%s leave %.16llx"ZT_EOL_S,n->first.toString().c_str(),nwid);
  305. }
  306. }
  307. }
  308. static void doListNetworks(const std::vector<std::string> &cmd)
  309. {
  310. if (cmd.size() < 2) {
  311. doHelp(cmd);
  312. return;
  313. }
  314. std::vector<Address> addrs;
  315. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  316. bool includeSuper = (cmd[1] == "**");
  317. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  318. if ((includeSuper)||(!n->second->supernode))
  319. addrs.push_back(n->first);
  320. }
  321. } else addrs.push_back(Address(cmd[1]));
  322. printf("---------- <nwid> <name> <mac> <status> <config age> <type> <dev> <ips>"ZT_EOL_S);
  323. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  324. std::string astr(a->toString());
  325. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  326. if (n != nodes.end()) {
  327. ZT1_Node_NetworkList *nl = n->second->node.listNetworks();
  328. if (nl) {
  329. for(unsigned int i=0;i<nl->numNetworks;++i) {
  330. printf("%s %s %s %s %s %ld %s %s ",
  331. astr.c_str(),
  332. nl->networks[i].nwidHex,
  333. nl->networks[i].name,
  334. nl->networks[i].macStr,
  335. nl->networks[i].statusStr,
  336. nl->networks[i].configAge,
  337. (nl->networks[i].isPrivate ? "private" : "public"),
  338. nl->networks[i].device);
  339. if (nl->networks[i].numIps > 0) {
  340. for(unsigned int j=0;j<nl->networks[i].numIps;++j) {
  341. if (j > 0)
  342. printf(",");
  343. printf("%s/%d",nl->networks[i].ips[j].ascii,(int)nl->networks[i].ips[j].port);
  344. }
  345. } else printf("-");
  346. printf(ZT_EOL_S);
  347. }
  348. n->second->node.freeQueryResult(nl);
  349. }
  350. }
  351. }
  352. }
  353. static void doListPeers(const std::vector<std::string> &cmd)
  354. {
  355. if (cmd.size() < 2) {
  356. doHelp(cmd);
  357. return;
  358. }
  359. std::vector<Address> addrs;
  360. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  361. bool includeSuper = (cmd[1] == "**");
  362. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  363. if ((includeSuper)||(!n->second->supernode))
  364. addrs.push_back(n->first);
  365. }
  366. } else addrs.push_back(Address(cmd[1]));
  367. printf("---------- <ztaddr> <paths> <latency> <version> <role>"ZT_EOL_S);
  368. for(std::vector<Address>::iterator a(addrs.begin());a!=addrs.end();++a) {
  369. std::string astr(a->toString());
  370. std::map< Address,SimNode * >::iterator n(nodes.find(*a));
  371. if (n != nodes.end()) {
  372. ZT1_Node_PeerList *pl = n->second->node.listPeers();
  373. if (pl) {
  374. for(unsigned int i=0;i<pl->numPeers;++i) {
  375. printf("%s %.10llx ",astr.c_str(),(unsigned long long)pl->peers[i].rawAddress);
  376. if (pl->peers[i].numPaths == 0)
  377. printf("-");
  378. else {
  379. for(unsigned int j=0;j<pl->peers[i].numPaths;++j) {
  380. if (j > 0)
  381. printf(",");
  382. switch(pl->peers[i].paths[j].type) {
  383. default:
  384. printf("unknown;");
  385. break;
  386. case ZT1_Node_PhysicalPath_TYPE_UDP:
  387. printf("udp;");
  388. break;
  389. case ZT1_Node_PhysicalPath_TYPE_TCP_OUT:
  390. printf("tcp_out;");
  391. break;
  392. case ZT1_Node_PhysicalPath_TYPE_TCP_IN:
  393. printf("tcp_in;");
  394. break;
  395. case ZT1_Node_PhysicalPath_TYPE_ETHERNET:
  396. printf("eth;");
  397. break;
  398. }
  399. printf("%s/%d;%ld;%ld;%ld;%s",
  400. pl->peers[i].paths[j].address.ascii,
  401. (int)pl->peers[i].paths[j].address.port,
  402. pl->peers[i].paths[j].lastSend,
  403. pl->peers[i].paths[j].lastReceive,
  404. pl->peers[i].paths[j].lastPing,
  405. (pl->peers[i].paths[j].fixed ? "fixed" : (pl->peers[i].paths[j].active ? "active" : "inactive")));
  406. }
  407. }
  408. const char *rolestr;
  409. switch(pl->peers[i].role) {
  410. case ZT1_Node_Peer_SUPERNODE: rolestr = "SUPERNODE"; break;
  411. case ZT1_Node_Peer_HUB: rolestr = "HUB"; break;
  412. case ZT1_Node_Peer_NODE: rolestr = "NODE"; break;
  413. default: rolestr = "?"; break;
  414. }
  415. printf(" %u %s %s"ZT_EOL_S,
  416. pl->peers[i].latency,
  417. ((pl->peers[i].remoteVersion[0]) ? pl->peers[i].remoteVersion : "-"),
  418. rolestr);
  419. }
  420. n->second->node.freeQueryResult(pl);
  421. }
  422. }
  423. }
  424. }
  425. static void doUnicast(const std::vector<std::string> &cmd)
  426. {
  427. union {
  428. uint64_t i[2];
  429. unsigned char data[2800];
  430. } pkt;
  431. if (cmd.size() < 5) {
  432. doHelp(cmd);
  433. return;
  434. }
  435. uint64_t nwid = Utils::hexStrToU64(cmd[3].c_str());
  436. unsigned int frameLen = Utils::strToUInt(cmd[4].c_str());
  437. uint64_t tout = 2000;
  438. if (cmd.size() >= 6)
  439. tout = Utils::strToU64(cmd[5].c_str()) * 1000ULL;
  440. if (frameLen < 16)
  441. frameLen = 16;
  442. if (frameLen > 2800)
  443. frameLen = 2800;
  444. std::vector<Address> senders;
  445. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  446. bool includeSuper = (cmd[1] == "**");
  447. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  448. if ((includeSuper)||(!n->second->supernode))
  449. senders.push_back(n->first);
  450. }
  451. } else senders.push_back(Address(cmd[1]));
  452. std::vector<Address> receivers;
  453. if ((cmd[2] == "*")||(cmd[2] == "**")) {
  454. bool includeSuper = (cmd[2] == "**");
  455. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  456. if ((includeSuper)||(!n->second->supernode))
  457. receivers.push_back(n->first);
  458. }
  459. } else receivers.push_back(Address(cmd[2]));
  460. for(unsigned int i=0;i<frameLen;++i)
  461. pkt.data[i] = (unsigned char)prng.next32();
  462. std::set< std::pair<Address,Address> > sentPairs;
  463. for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) {
  464. for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) {
  465. if (*s == *r)
  466. continue;
  467. SimNode *sender = nodes[*s];
  468. SimNode *receiver = nodes[*r];
  469. TestEthernetTap *stap = sender->tapFactory.getByNwid(nwid);
  470. TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid);
  471. if ((stap)&&(rtap)) {
  472. pkt.i[0] = s->toInt();
  473. pkt.i[1] = Utils::now();
  474. stap->injectPacketFromHost(stap->mac(),rtap->mac(),0xdead,pkt.data,frameLen);
  475. printf("%s -> %s etherType 0xdead network %.16llx length %u"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid,frameLen);
  476. sentPairs.insert(std::pair<Address,Address>(*s,*r));
  477. } else if (stap) {
  478. printf("%s -> !%s (receiver not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  479. } else if (rtap) {
  480. printf("%s -> !%s (sender not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  481. } else {
  482. printf("%s -> !%s (neither party is a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),r->toString().c_str(),nwid);
  483. }
  484. }
  485. }
  486. printf("---------- waiting up to %llu seconds..."ZT_EOL_S,tout / 1000ULL);
  487. std::set< std::pair<Address,Address> > receivedPairs;
  488. TestEthernetTap::TestFrame frame;
  489. uint64_t toutend = Utils::now() + tout;
  490. do {
  491. for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) {
  492. SimNode *receiver = nodes[*r];
  493. TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid);
  494. if ((rtap)&&(rtap->getNextReceivedFrame(frame,5))) {
  495. if ((frame.len == frameLen)&&(!memcmp(frame.data + 16,pkt.data + 16,frameLen - 16))) {
  496. uint64_t ints[2];
  497. memcpy(ints,frame.data,16);
  498. printf("%s <- %.10llx received test packet, length == %u, latency == %llums"ZT_EOL_S,r->toString().c_str(),ints[0],frame.len,frame.timestamp - ints[1]);
  499. receivedPairs.insert(std::pair<Address,Address>(Address(ints[0]),*r));
  500. } else {
  501. printf("%s !! got spurious packet, length == %u, etherType == 0x%.4x"ZT_EOL_S,r->toString().c_str(),frame.len,frame.etherType);
  502. }
  503. }
  504. }
  505. Thread::sleep(100);
  506. } while ((receivedPairs.size() < sentPairs.size())&&(Utils::now() < toutend));
  507. for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) {
  508. for(std::vector<Address>::iterator r(receivers.begin());r!=receivers.end();++r) {
  509. if (*s == *r)
  510. continue;
  511. if ((sentPairs.count(std::pair<Address,Address>(*s,*r)))&&(!receivedPairs.count(std::pair<Address,Address>(*s,*r)))) {
  512. printf("%s <- %s was never received (timed out)"ZT_EOL_S,r->toString().c_str(),s->toString().c_str());
  513. }
  514. }
  515. }
  516. printf("---------- sent %u, received %u"ZT_EOL_S,(unsigned int)sentPairs.size(),(unsigned int)receivedPairs.size());
  517. }
  518. static void doMulticast(const std::vector<std::string> &cmd)
  519. {
  520. union {
  521. uint64_t i[2];
  522. unsigned char data[2800];
  523. } pkt;
  524. if (cmd.size() < 5) {
  525. doHelp(cmd);
  526. return;
  527. }
  528. uint64_t nwid = Utils::hexStrToU64(cmd[3].c_str());
  529. unsigned int frameLen = Utils::strToUInt(cmd[4].c_str());
  530. uint64_t tout = 2000;
  531. if (cmd.size() >= 6)
  532. tout = Utils::strToU64(cmd[5].c_str()) * 1000ULL;
  533. if (frameLen < 16)
  534. frameLen = 16;
  535. if (frameLen > 2800)
  536. frameLen = 2800;
  537. std::vector<Address> senders;
  538. if ((cmd[1] == "*")||(cmd[1] == "**")) {
  539. bool includeSuper = (cmd[1] == "**");
  540. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  541. if ((includeSuper)||(!n->second->supernode))
  542. senders.push_back(n->first);
  543. }
  544. } else senders.push_back(Address(cmd[1]));
  545. MAC mcaddr;
  546. if (cmd[2] == "*")
  547. mcaddr = MAC(0xff,0xff,0xff,0xff,0xff,0xff);
  548. else mcaddr.fromString(cmd[2].c_str());
  549. if (!mcaddr.isMulticast()) {
  550. printf("---------- %s is not a multicast MAC address"ZT_EOL_S,mcaddr.toString().c_str());
  551. return;
  552. }
  553. for(unsigned int i=0;i<frameLen;++i)
  554. pkt.data[i] = (unsigned char)prng.next32();
  555. for(std::vector<Address>::iterator s(senders.begin());s!=senders.end();++s) {
  556. SimNode *sender = nodes[*s];
  557. TestEthernetTap *stap = sender->tapFactory.getByNwid(nwid);
  558. if (stap) {
  559. pkt.i[0] = s->toInt();
  560. pkt.i[1] = Utils::now();
  561. stap->injectPacketFromHost(stap->mac(),mcaddr,0xdead,pkt.data,frameLen);
  562. printf("%s -> %s etherType 0xdead network %.16llx length %u"ZT_EOL_S,s->toString().c_str(),mcaddr.toString().c_str(),nwid,frameLen);
  563. } else {
  564. printf("%s -> !%s (sender is not a member of %.16llx)"ZT_EOL_S,s->toString().c_str(),mcaddr.toString().c_str(),nwid);
  565. }
  566. }
  567. printf("---------- waiting %llu seconds..."ZT_EOL_S,tout / 1000ULL);
  568. unsigned int receiveCount = 0;
  569. TestEthernetTap::TestFrame frame;
  570. uint64_t toutend = Utils::now() + tout;
  571. do {
  572. for(std::map< Address,SimNode * >::iterator nn(nodes.begin());nn!=nodes.end();++nn) {
  573. SimNode *receiver = nn->second;
  574. TestEthernetTap *rtap = receiver->tapFactory.getByNwid(nwid);
  575. if ((rtap)&&(rtap->getNextReceivedFrame(frame,5))) {
  576. if ((frame.len == frameLen)&&(!memcmp(frame.data + 16,pkt.data + 16,frameLen - 16))) {
  577. uint64_t ints[2];
  578. memcpy(ints,frame.data,16);
  579. printf("%s <- %.10llx received test packet, length == %u, latency == %llums"ZT_EOL_S,nn->first.toString().c_str(),ints[0],frame.len,frame.timestamp - ints[1]);
  580. ++receiveCount;
  581. } else {
  582. printf("%s !! got spurious packet, length == %u, etherType == 0x%.4x"ZT_EOL_S,nn->first.toString().c_str(),frame.len,frame.etherType);
  583. }
  584. }
  585. }
  586. Thread::sleep(100);
  587. } while (Utils::now() < toutend);
  588. printf("---------- test multicast received by %u peers"ZT_EOL_S,receiveCount);
  589. }
  590. int main(int argc,char **argv)
  591. {
  592. char linebuf[1024];
  593. if (argc <= 1) {
  594. fprintf(stderr,"Usage: %s <base path for temporary node home directories>"ZT_EOL_S,argv[0]);
  595. return 1;
  596. }
  597. basePath = argv[1];
  598. #ifdef __WINDOWS__
  599. CreateDirectoryA(basePath.c_str(),NULL);
  600. #else
  601. mkdir(basePath.c_str(),0700);
  602. #endif
  603. printf("*** ZeroTier One Version %s -- Headless Network Simulator ***"ZT_EOL_S,Node::versionString());
  604. printf(ZT_EOL_S);
  605. {
  606. printf("---------- scanning '%s' for existing network..."ZT_EOL_S,basePath.c_str());
  607. std::vector<Address> snodes(initSupernodes());
  608. if (snodes.empty()) {
  609. printf("---------- no existing network found; use 'mksn' to create one."ZT_EOL_S);
  610. } else {
  611. for(std::vector<Address>::iterator a(snodes.begin());a!=snodes.end();++a)
  612. printf("%s started (supernode)"ZT_EOL_S,a->toString().c_str());
  613. //printf("---------- root topology is: %s"ZT_EOL_S,rootTopology.c_str());
  614. std::vector<Address> nodes(scanForNewNodes());
  615. for(std::vector<Address>::iterator a(nodes.begin());a!=nodes.end();++a)
  616. printf("%s started (normal peer)"ZT_EOL_S,a->toString().c_str());
  617. printf("---------- %u peers and %u supernodes loaded!"ZT_EOL_S,(unsigned int)nodes.size(),(unsigned int)snodes.size());
  618. }
  619. }
  620. printf(ZT_EOL_S);
  621. printf("Type 'help' for help."ZT_EOL_S);
  622. printf(ZT_EOL_S);
  623. std::vector<std::string> cmd,prevCmd;
  624. bool run = true;
  625. while (run) {
  626. printf(">> ");
  627. fflush(stdout);
  628. if (!fgets(linebuf,sizeof(linebuf),stdin))
  629. break;
  630. cmd = Utils::split(linebuf," \r\n\t","\\","\"");
  631. for(;;) {
  632. if (cmd.size() == 0)
  633. break;
  634. else if (cmd[0] == "quit")
  635. run = false;
  636. else if (cmd[0] == "help")
  637. doHelp(cmd);
  638. else if (cmd[0] == "mksn")
  639. doMKSN(cmd);
  640. else if (cmd[0] == "mkn")
  641. doMKN(cmd);
  642. else if (cmd[0] == "list")
  643. doList(cmd);
  644. else if (cmd[0] == "join")
  645. doJoin(cmd);
  646. else if (cmd[0] == "leave")
  647. doLeave(cmd);
  648. else if (cmd[0] == "listnetworks")
  649. doListNetworks(cmd);
  650. else if (cmd[0] == "listpeers")
  651. doListPeers(cmd);
  652. else if (cmd[0] == "unicast")
  653. doUnicast(cmd);
  654. else if (cmd[0] == "multicast")
  655. doMulticast(cmd);
  656. else if ((cmd[0] == ".")&&(prevCmd.size() > 0)) {
  657. cmd = prevCmd;
  658. continue;
  659. } else doHelp(cmd);
  660. break;
  661. }
  662. if ((cmd.size() > 0)&&(cmd[0] != "."))
  663. prevCmd = cmd;
  664. }
  665. for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) {
  666. printf("%s shutting down..."ZT_EOL_S,n->first.toString().c_str());
  667. delete n->second;
  668. }
  669. return 0;
  670. }