EthernetTap.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254
  1. /*
  2. * ZeroTier One - Global Peer to Peer Ethernet
  3. * Copyright (C) 2012-2013 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. #include <string>
  28. #include <map>
  29. #include <set>
  30. #include <algorithm>
  31. #include "Constants.hpp"
  32. #include "EthernetTap.hpp"
  33. #include "Logger.hpp"
  34. #include "RuntimeEnvironment.hpp"
  35. #include "Utils.hpp"
  36. #include "Mutex.hpp"
  37. // ff:ff:ff:ff:ff:ff with no ADI
  38. static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC(0xff),0);
  39. //
  40. // TAP implementation for *nix OSes, with some specialization for different flavors
  41. //
  42. #ifdef __UNIX_LIKE__ /////////////////////////////////////////////////////////
  43. #include <stdint.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <unistd.h>
  48. #include <signal.h>
  49. #include <fcntl.h>
  50. #include <errno.h>
  51. #include <sys/types.h>
  52. #include <sys/stat.h>
  53. #include <sys/ioctl.h>
  54. #include <sys/wait.h>
  55. #include <sys/select.h>
  56. #include <netinet/in.h>
  57. #include <net/if_arp.h>
  58. #include <arpa/inet.h>
  59. // Command identifiers used with command finder static (on various *nixes)
  60. #define ZT_UNIX_IP_COMMAND 1
  61. #define ZT_UNIX_IFCONFIG_COMMAND 2
  62. #define ZT_MAC_KEXTLOAD_COMMAND 3
  63. #define ZT_MAC_IPCONFIG_COMMAND 4
  64. // Finds external commands on startup
  65. class _CommandFinder
  66. {
  67. public:
  68. _CommandFinder()
  69. {
  70. _findCmd(ZT_UNIX_IFCONFIG_COMMAND,"ifconfig");
  71. #ifdef __LINUX__
  72. _findCmd(ZT_UNIX_IP_COMMAND,"ip");
  73. #endif
  74. #ifdef __APPLE__
  75. _findCmd(ZT_MAC_KEXTLOAD_COMMAND,"kextload");
  76. _findCmd(ZT_MAC_IPCONFIG_COMMAND,"ipconfig");
  77. #endif
  78. }
  79. // returns NULL if command was not found
  80. inline const char *operator[](int id) const
  81. throw()
  82. {
  83. std::map<int,std::string>::const_iterator c(_paths.find(id));
  84. if (c == _paths.end())
  85. return (const char *)0;
  86. return c->second.c_str();
  87. }
  88. private:
  89. inline void _findCmd(int id,const char *name)
  90. {
  91. char tmp[4096];
  92. sprintf(tmp,"/sbin/%s",name);
  93. if (ZeroTier::Utils::fileExists(tmp)) {
  94. _paths[id] = tmp;
  95. return;
  96. }
  97. sprintf(tmp,"/usr/sbin/%s",name);
  98. if (ZeroTier::Utils::fileExists(tmp)) {
  99. _paths[id] = tmp;
  100. return;
  101. }
  102. sprintf(tmp,"/bin/%s",name);
  103. if (ZeroTier::Utils::fileExists(tmp)) {
  104. _paths[id] = tmp;
  105. return;
  106. }
  107. sprintf(tmp,"/usr/bin/%s",name);
  108. if (ZeroTier::Utils::fileExists(tmp)) {
  109. _paths[id] = tmp;
  110. return;
  111. }
  112. }
  113. std::map<int,std::string> _paths;
  114. };
  115. static const _CommandFinder UNIX_COMMANDS;
  116. #ifdef __LINUX__
  117. #include <linux/if.h>
  118. #include <linux/if_tun.h>
  119. #include <linux/if_addr.h>
  120. #include <linux/if_ether.h>
  121. #endif // __LINUX__
  122. #ifdef __APPLE__
  123. #include <sys/uio.h>
  124. #include <sys/param.h>
  125. #include <sys/sysctl.h>
  126. #include <net/route.h>
  127. #include <net/if_dl.h>
  128. #include <ifaddrs.h>
  129. #endif // __APPLE__
  130. namespace ZeroTier {
  131. // Only permit one tap to be opened concurrently across the entire process
  132. static Mutex __tapCreateLock;
  133. #ifdef __LINUX__
  134. EthernetTap::EthernetTap(
  135. const RuntimeEnvironment *renv,
  136. const char *tag,
  137. const MAC &mac,
  138. unsigned int mtu,
  139. void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
  140. void *arg)
  141. throw(std::runtime_error) :
  142. _mac(mac),
  143. _mtu(mtu),
  144. _r(renv),
  145. _handler(handler),
  146. _arg(arg),
  147. _fd(0)
  148. {
  149. char procpath[128];
  150. Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
  151. if (mtu > 4096)
  152. throw std::runtime_error("max tap MTU is 4096");
  153. _fd = ::open("/dev/net/tun",O_RDWR);
  154. if (_fd <= 0)
  155. throw std::runtime_error(std::string("could not open TUN/TAP device: ") + strerror(errno));
  156. struct ifreq ifr;
  157. memset(&ifr,0,sizeof(ifr));
  158. { // pick an unused device name
  159. int devno = 0;
  160. struct stat sbuf;
  161. do {
  162. sprintf(ifr.ifr_name,"zt%d",devno++);
  163. sprintf(procpath,"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
  164. } while (stat(procpath,&sbuf) == 0);
  165. }
  166. ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  167. if (ioctl(_fd,TUNSETIFF,(void *)&ifr) < 0) {
  168. ::close(_fd);
  169. throw std::runtime_error("unable to configure TUN/TAP device for TAP operation");
  170. }
  171. strcpy(_dev,ifr.ifr_name);
  172. ioctl(_fd,TUNSETPERSIST,0); // valgrind may generate a false alarm here
  173. // Open an arbitrary socket to talk to netlink
  174. int sock = socket(AF_INET,SOCK_DGRAM,0);
  175. if (sock <= 0) {
  176. ::close(_fd);
  177. throw std::runtime_error("unable to open netlink socket");
  178. }
  179. // Set MAC address
  180. ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER;
  181. memcpy(ifr.ifr_ifru.ifru_hwaddr.sa_data,mac.data,6);
  182. if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) {
  183. ::close(_fd);
  184. ::close(sock);
  185. throw std::runtime_error("unable to configure TAP hardware (MAC) address");
  186. return;
  187. }
  188. // Set MTU
  189. ifr.ifr_ifru.ifru_mtu = (int)mtu;
  190. if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) {
  191. ::close(_fd);
  192. ::close(sock);
  193. throw std::runtime_error("unable to configure TAP MTU");
  194. }
  195. if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) {
  196. ::close(_fd);
  197. throw std::runtime_error("unable to set flags on file descriptor for TAP device");
  198. }
  199. /* Bring interface up */
  200. if (ioctl(sock,SIOCGIFFLAGS,(void *)&ifr) < 0) {
  201. ::close(_fd);
  202. ::close(sock);
  203. throw std::runtime_error("unable to get TAP interface flags");
  204. }
  205. ifr.ifr_flags |= IFF_UP;
  206. if (ioctl(sock,SIOCSIFFLAGS,(void *)&ifr) < 0) {
  207. ::close(_fd);
  208. ::close(sock);
  209. throw std::runtime_error("unable to set TAP interface flags");
  210. }
  211. ::close(sock);
  212. ::pipe(_shutdownSignalPipe);
  213. TRACE("tap %s created",_dev);
  214. _thread = Thread::start(this);
  215. }
  216. #endif // __LINUX__
  217. #ifdef __APPLE__
  218. EthernetTap::EthernetTap(
  219. const RuntimeEnvironment *renv,
  220. const char *tag,
  221. const MAC &mac,
  222. unsigned int mtu,
  223. void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
  224. void *arg)
  225. throw(std::runtime_error) :
  226. _mac(mac),
  227. _mtu(mtu),
  228. _r(renv),
  229. _handler(handler),
  230. _arg(arg),
  231. _dhcp(false),
  232. _dhcp6(false),
  233. _fd(0)
  234. {
  235. char devpath[64],ethaddr[64],mtustr[16];
  236. struct stat tmp;
  237. Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
  238. if (mtu > 4096)
  239. throw std::runtime_error("max tap MTU is 4096");
  240. // Check for existence of ZT tap devices, try to load module if not there
  241. const char *kextload = UNIX_COMMANDS[ZT_MAC_KEXTLOAD_COMMAND];
  242. if ((stat("/dev/zt0",&tmp))&&(kextload)) {
  243. long kextpid;
  244. char tmp[4096];
  245. strcpy(tmp,_r->homePath.c_str());
  246. if ((kextpid = (long)vfork()) == 0) {
  247. chdir(tmp);
  248. execl(kextload,kextload,"-q","-repository",tmp,"tap.kext",(const char *)0);
  249. _exit(-1);
  250. } else {
  251. int exitcode = -1;
  252. waitpid(kextpid,&exitcode,0);
  253. usleep(500);
  254. }
  255. }
  256. if (stat("/dev/zt0",&tmp))
  257. throw std::runtime_error("/dev/zt# tap devices do not exist and unable to load kernel extension");
  258. // Open the first available device (ones in use will fail with resource busy)
  259. for(int i=0;i<256;++i) {
  260. sprintf(devpath,"/dev/zt%d",i);
  261. if (stat(devpath,&tmp))
  262. throw std::runtime_error("no more TAP devices available");
  263. _fd = ::open(devpath,O_RDWR);
  264. if (_fd > 0) {
  265. sprintf(_dev,"zt%d",i);
  266. break;
  267. }
  268. }
  269. if (_fd <= 0)
  270. throw std::runtime_error("unable to open TAP device or no more devices available");
  271. if (fcntl(_fd,F_SETFL,fcntl(_fd,F_GETFL) & ~O_NONBLOCK) == -1) {
  272. ::close(_fd);
  273. throw std::runtime_error("unable to set flags on file descriptor for TAP device");
  274. }
  275. const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
  276. if (!ifconfig) {
  277. ::close(_fd);
  278. throw std::runtime_error("unable to find 'ifconfig' command on system");
  279. }
  280. // Configure MAC address and MTU, bring interface up
  281. sprintf(ethaddr,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
  282. sprintf(mtustr,"%u",mtu);
  283. long cpid;
  284. if ((cpid = (long)vfork()) == 0) {
  285. execl(ifconfig,ifconfig,_dev,"lladdr",ethaddr,"mtu",mtustr,"up",(const char *)0);
  286. _exit(-1);
  287. } else {
  288. int exitcode = -1;
  289. waitpid(cpid,&exitcode,0);
  290. if (exitcode) {
  291. ::close(_fd);
  292. throw std::runtime_error("ifconfig failure setting link-layer address and activating tap interface");
  293. }
  294. }
  295. whack(); // turns on IPv6 on OSX
  296. ::pipe(_shutdownSignalPipe);
  297. _thread = Thread::start(this);
  298. }
  299. #endif // __APPLE__
  300. EthernetTap::~EthernetTap()
  301. {
  302. ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
  303. Thread::join(_thread);
  304. ::close(_fd);
  305. }
  306. #ifdef __APPLE__
  307. void EthernetTap::whack()
  308. {
  309. const char *ipconfig = UNIX_COMMANDS[ZT_MAC_IPCONFIG_COMMAND];
  310. if (ipconfig) {
  311. long cpid = (long)vfork();
  312. if (cpid == 0) {
  313. execl(ipconfig,ipconfig,"set",_dev,"AUTOMATIC-V6",(const char *)0);
  314. _exit(-1);
  315. } else {
  316. int exitcode = -1;
  317. waitpid(cpid,&exitcode,0);
  318. }
  319. }
  320. }
  321. #else
  322. void EthernetTap::whack() {}
  323. #endif // __APPLE__ / !__APPLE__
  324. bool EthernetTap::setDhcpEnabled(bool dhcp)
  325. {
  326. // TODO
  327. return _dhcp;
  328. }
  329. bool EthernetTap::setDhcp6Enabled(bool dhcp)
  330. {
  331. return _dhcp6;
  332. }
  333. void EthernetTap::setDisplayName(const char *dn)
  334. {
  335. }
  336. #ifdef __LINUX__
  337. static bool ___removeIp(const char *_dev,const InetAddress &ip)
  338. {
  339. const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
  340. if (!ipcmd)
  341. return false;
  342. long cpid = (long)vfork();
  343. if (cpid == 0) {
  344. execl(ipcmd,ipcmd,"addr","del",ip.toString().c_str(),"dev",_dev,(const char *)0);
  345. _exit(-1);
  346. } else {
  347. int exitcode = -1;
  348. waitpid(cpid,&exitcode,0);
  349. return (exitcode == 0);
  350. }
  351. }
  352. bool EthernetTap::addIP(const InetAddress &ip)
  353. {
  354. const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
  355. if (!ipcmd) {
  356. LOG("ERROR: could not configure IP address for %s: unable to find 'ip' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev);
  357. return false;
  358. }
  359. Mutex::Lock _l(_ips_m);
  360. if (!ip)
  361. return false;
  362. if (_ips.count(ip) > 0)
  363. return true;
  364. // Remove and reconfigure if address is the same but netmask is different
  365. for(std::set<InetAddress>::iterator i(_ips.begin());i!=_ips.end();++i) {
  366. if (i->ipsEqual(ip)) {
  367. if (___removeIp(_dev,*i)) {
  368. _ips.erase(i);
  369. break;
  370. } else {
  371. LOG("WARNING: failed to remove old IP/netmask %s to replace with %s",i->toString().c_str(),ip.toString().c_str());
  372. }
  373. }
  374. }
  375. long cpid;
  376. if ((cpid = (long)vfork()) == 0) {
  377. execl(ipcmd,ipcmd,"addr","add",ip.toString().c_str(),"dev",_dev,(const char *)0);
  378. _exit(-1);
  379. } else {
  380. int exitcode = -1;
  381. waitpid(cpid,&exitcode,0);
  382. if (exitcode == 0) {
  383. _ips.insert(ip);
  384. return true;
  385. } else return false;
  386. }
  387. return false;
  388. }
  389. #endif // __LINUX__
  390. #ifdef __APPLE__
  391. static bool ___removeIp(const char *_dev,const InetAddress &ip)
  392. {
  393. const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
  394. if (!ifconfig)
  395. return false;
  396. long cpid;
  397. if ((cpid = (long)vfork()) == 0) {
  398. execl(ifconfig,ifconfig,_dev,"inet",ip.toIpString().c_str(),"-alias",(const char *)0);
  399. _exit(-1);
  400. } else {
  401. int exitcode = -1;
  402. waitpid(cpid,&exitcode,0);
  403. return (exitcode == 0);
  404. }
  405. return false; // never reached, make compiler shut up about return value
  406. }
  407. bool EthernetTap::addIP(const InetAddress &ip)
  408. {
  409. const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
  410. if (!ifconfig) {
  411. LOG("ERROR: could not configure IP address for %s: unable to find 'ifconfig' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev);
  412. return false;
  413. }
  414. Mutex::Lock _l(_ips_m);
  415. if (!ip)
  416. return false;
  417. if (_ips.count(ip) > 0)
  418. return true; // IP/netmask already assigned
  419. // Remove and reconfigure if address is the same but netmask is different
  420. for(std::set<InetAddress>::iterator i(_ips.begin());i!=_ips.end();++i) {
  421. if ((i->ipsEqual(ip))&&(i->netmaskBits() != ip.netmaskBits())) {
  422. if (___removeIp(_dev,*i)) {
  423. _ips.erase(i);
  424. break;
  425. } else {
  426. LOG("WARNING: failed to remove old IP/netmask %s to replace with %s",i->toString().c_str(),ip.toString().c_str());
  427. }
  428. }
  429. }
  430. long cpid;
  431. if ((cpid = (long)vfork()) == 0) {
  432. execl(ifconfig,ifconfig,_dev,ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0);
  433. _exit(-1);
  434. } else {
  435. int exitcode = -1;
  436. waitpid(cpid,&exitcode,0);
  437. if (exitcode == 0) {
  438. _ips.insert(ip);
  439. return true;
  440. }
  441. }
  442. return false;
  443. }
  444. #endif // __APPLE__
  445. bool EthernetTap::removeIP(const InetAddress &ip)
  446. {
  447. Mutex::Lock _l(_ips_m);
  448. if (_ips.count(ip) > 0) {
  449. if (___removeIp(_dev,ip)) {
  450. _ips.erase(ip);
  451. return true;
  452. }
  453. }
  454. return false;
  455. }
  456. std::set<InetAddress> EthernetTap::allIps() const
  457. {
  458. // TODO
  459. return ips();
  460. }
  461. void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
  462. {
  463. char putBuf[4096 + 14];
  464. if ((_fd > 0)&&(len <= _mtu)) {
  465. for(int i=0;i<6;++i)
  466. putBuf[i] = to.data[i];
  467. for(int i=0;i<6;++i)
  468. putBuf[i+6] = from.data[i];
  469. *((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType);
  470. memcpy(putBuf + 14,data,len);
  471. len += 14;
  472. int n = ::write(_fd,putBuf,len);
  473. if (n <= 0) {
  474. LOG("error writing packet to Ethernet tap device: %s",strerror(errno));
  475. } else if (n != (int)len) {
  476. // Saw this gremlin once, so log it if we see it again... OSX tap
  477. // or something seems to have goofy issues with certain MTUs.
  478. LOG("ERROR: write underrun: %s tap write() wrote %d of %u bytes of frame",_dev,n,len);
  479. }
  480. }
  481. }
  482. std::string EthernetTap::deviceName() const
  483. {
  484. return std::string(_dev);
  485. }
  486. #ifdef __LINUX__
  487. bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
  488. {
  489. char *ptr,*ptr2;
  490. unsigned char mac[6];
  491. std::set<MulticastGroup> newGroups;
  492. int fd = ::open("/proc/net/dev_mcast",O_RDONLY);
  493. if (fd > 0) {
  494. char buf[131072];
  495. int n = (int)::read(fd,buf,sizeof(buf));
  496. if ((n > 0)&&(n < (int)sizeof(buf))) {
  497. buf[n] = (char)0;
  498. for(char *l=strtok_r(buf,"\r\n",&ptr);(l);l=strtok_r((char *)0,"\r\n",&ptr)) {
  499. int fno = 0;
  500. char *devname = (char *)0;
  501. char *mcastmac = (char *)0;
  502. for(char *f=strtok_r(l," \t",&ptr2);(f);f=strtok_r((char *)0," \t",&ptr2)) {
  503. if (fno == 1)
  504. devname = f;
  505. else if (fno == 4)
  506. mcastmac = f;
  507. ++fno;
  508. }
  509. if ((devname)&&(!strcmp(devname,_dev))&&(mcastmac)&&(Utils::unhex(mcastmac,mac,6) == 6))
  510. newGroups.insert(MulticastGroup(MAC(mac),0));
  511. }
  512. }
  513. ::close(fd);
  514. }
  515. {
  516. Mutex::Lock _l(_ips_m);
  517. for(std::set<InetAddress>::const_iterator i(_ips.begin());i!=_ips.end();++i)
  518. newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
  519. }
  520. bool changed = false;
  521. newGroups.insert(_blindWildcardMulticastGroup); // always join this
  522. for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
  523. if (!groups.count(*mg)) {
  524. groups.insert(*mg);
  525. changed = true;
  526. }
  527. }
  528. for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
  529. if (!newGroups.count(*mg)) {
  530. groups.erase(mg++);
  531. changed = true;
  532. } else ++mg;
  533. }
  534. return changed;
  535. }
  536. #endif // __LINUX__
  537. #ifdef __APPLE__
  538. bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
  539. {
  540. std::set<MulticastGroup> newGroups;
  541. struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
  542. if (!getifmaddrs(&ifmap)) {
  543. struct ifmaddrs *p = ifmap;
  544. while (p) {
  545. if (p->ifma_addr->sa_family == AF_LINK) {
  546. struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name;
  547. struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr;
  548. if ((la->sdl_alen == 6)&&(in->sdl_nlen <= sizeof(_dev))&&(!memcmp(_dev,in->sdl_data,in->sdl_nlen)))
  549. newGroups.insert(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen),0));
  550. }
  551. p = p->ifma_next;
  552. }
  553. freeifmaddrs(ifmap);
  554. }
  555. {
  556. Mutex::Lock _l(_ips_m);
  557. for(std::set<InetAddress>::const_iterator i(_ips.begin());i!=_ips.end();++i)
  558. newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
  559. }
  560. bool changed = false;
  561. newGroups.insert(_blindWildcardMulticastGroup); // always join this
  562. for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
  563. if (!groups.count(*mg)) {
  564. groups.insert(*mg);
  565. changed = true;
  566. }
  567. }
  568. for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
  569. if (!newGroups.count(*mg)) {
  570. groups.erase(mg++);
  571. changed = true;
  572. } else ++mg;
  573. }
  574. return changed;
  575. }
  576. #endif // __APPLE__
  577. void EthernetTap::threadMain()
  578. throw()
  579. {
  580. fd_set readfds,nullfds;
  581. MAC to,from;
  582. char getBuf[4096 + 14];
  583. Buffer<4096> data;
  584. // Wait for a moment after startup -- wait for Network to finish
  585. // constructing itself.
  586. Thread::sleep(500);
  587. FD_ZERO(&readfds);
  588. FD_ZERO(&nullfds);
  589. int nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
  590. for(;;) {
  591. FD_SET(_shutdownSignalPipe[0],&readfds);
  592. FD_SET(_fd,&readfds);
  593. select(nfds,&readfds,&nullfds,&nullfds,(struct timeval *)0);
  594. if (FD_ISSET(_shutdownSignalPipe[0],&readfds)) // writes to shutdown pipe terminate thread
  595. break;
  596. if (FD_ISSET(_fd,&readfds)) {
  597. int n = (int)::read(_fd,getBuf,_mtu + 14);
  598. if (n > 14) {
  599. for(int i=0;i<6;++i)
  600. to.data[i] = (unsigned char)getBuf[i];
  601. for(int i=0;i<6;++i)
  602. from.data[i] = (unsigned char)getBuf[i + 6];
  603. data.copyFrom(getBuf + 14,(unsigned int)n - 14);
  604. _handler(_arg,from,to,ntohs(((const uint16_t *)getBuf)[6]),data);
  605. } else if (n < 0) {
  606. if ((errno != EINTR)&&(errno != ETIMEDOUT)) {
  607. TRACE("unexpected error reading from tap: %s",strerror(errno));
  608. break;
  609. }
  610. }
  611. }
  612. }
  613. }
  614. } // namespace ZeroTier
  615. #endif // __UNIX_LIKE__ //////////////////////////////////////////////////////
  616. //////////////////////////////////////////////////////////////////////////////
  617. #ifdef __WINDOWS__ ///////////////////////////////////////////////////////////
  618. #include <stdio.h>
  619. #include <stdlib.h>
  620. #include <stdint.h>
  621. #include <string.h>
  622. #include <WinSock2.h>
  623. #include <Windows.h>
  624. #include <iphlpapi.h>
  625. #include <ws2ipdef.h>
  626. #include <WS2tcpip.h>
  627. #include <tchar.h>
  628. #include <winreg.h>
  629. #include <wchar.h>
  630. #include <nldef.h>
  631. #include <netioapi.h>
  632. #include "..\vsprojects\TapDriver\tap-windows.h"
  633. namespace ZeroTier {
  634. // Helper function to get an adapter's LUID and index from its GUID. The LUID is
  635. // constant but the index can change, so go ahead and just look them both up by
  636. // the GUID which is constant. (The GUID is the instance ID in the registry.)
  637. static inline std::pair<NET_LUID,NET_IFINDEX> _findAdapterByGuid(const GUID &guid)
  638. throw(std::runtime_error)
  639. {
  640. MIB_IF_TABLE2 *ift = (MIB_IF_TABLE2 *)0;
  641. if (GetIfTable2Ex(MibIfTableRaw,&ift) != NO_ERROR)
  642. throw std::runtime_error("GetIfTable2Ex() failed");
  643. for(ULONG i=0;i<ift->NumEntries;++i) {
  644. if (ift->Table[i].InterfaceGuid == guid) {
  645. std::pair<NET_LUID,NET_IFINDEX> tmp(ift->Table[i].InterfaceLuid,ift->Table[i].InterfaceIndex);
  646. FreeMibTable(ift);
  647. return tmp;
  648. }
  649. }
  650. FreeMibTable(&ift);
  651. throw std::runtime_error("interface not found");
  652. }
  653. static Mutex _systemTapInitLock;
  654. EthernetTap::EthernetTap(
  655. const RuntimeEnvironment *renv,
  656. const char *tag,
  657. const MAC &mac,
  658. unsigned int mtu,
  659. void (*handler)(void *,const MAC &,const MAC &,unsigned int,const Buffer<4096> &),
  660. void *arg)
  661. throw(std::runtime_error) :
  662. _mac(mac),
  663. _mtu(mtu),
  664. _r(renv),
  665. _handler(handler),
  666. _arg(arg),
  667. _dhcp(false),
  668. _dhcp6(false),
  669. _tap(INVALID_HANDLE_VALUE),
  670. _injectSemaphore(INVALID_HANDLE_VALUE),
  671. _run(true)
  672. {
  673. char subkeyName[4096];
  674. char subkeyClass[4096];
  675. char data[4096];
  676. if (mtu > ZT_IF_MTU)
  677. throw std::runtime_error("MTU too large for Windows tap");
  678. #ifdef _WIN64
  679. const char *devcon = "\\devcon64.exe";
  680. #else
  681. BOOL f64 = FALSE;
  682. const char *devcon = ((IsWow64Process(GetCurrentProcess(),&f64) == TRUE) ? "\\devcon64.exe" : "\\devcon32.exe");
  683. #endif
  684. Mutex::Lock _l(_systemTapInitLock); // only init one tap at a time, process-wide
  685. HKEY nwAdapters;
  686. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS)
  687. throw std::runtime_error("unable to open registry key for network adapter enumeration");
  688. std::set<std::string> existingDeviceInstances;
  689. std::string mySubkeyName;
  690. // Enumerate tap instances and look for one tagged with this tag
  691. for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
  692. DWORD type;
  693. DWORD dataLen;
  694. DWORD subkeyNameLen = sizeof(subkeyName);
  695. DWORD subkeyClassLen = sizeof(subkeyClass);
  696. FILETIME lastWriteTime;
  697. switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) {
  698. case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break;
  699. case ERROR_SUCCESS:
  700. type = 0;
  701. dataLen = sizeof(data);
  702. if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
  703. data[dataLen] = '\0';
  704. if (!strnicmp(data,"zttap",5)) {
  705. std::string instanceId;
  706. type = 0;
  707. dataLen = sizeof(data);
  708. if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
  709. instanceId.assign(data,dataLen);
  710. existingDeviceInstances.insert(instanceId);
  711. }
  712. std::string instanceIdPath;
  713. type = 0;
  714. dataLen = sizeof(data);
  715. if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
  716. instanceIdPath.assign(data,dataLen);
  717. if ((_myDeviceInstanceId.length() == 0)&&(instanceId.length() != 0)&&(instanceIdPath.length() != 0)) {
  718. type = 0;
  719. dataLen = sizeof(data);
  720. if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
  721. data[dataLen] = '\0';
  722. if (!strcmp(data,tag)) {
  723. _myDeviceInstanceId = instanceId;
  724. _myDeviceInstanceIdPath = instanceIdPath;
  725. mySubkeyName = subkeyName;
  726. subkeyIndex = -1; // break outer loop
  727. }
  728. }
  729. }
  730. }
  731. }
  732. break;
  733. }
  734. }
  735. // If there is no device, try to create one
  736. if (_myDeviceInstanceId.length() == 0) {
  737. // Execute devcon to install an instance of the Microsoft Loopback Adapter
  738. STARTUPINFOA startupInfo;
  739. startupInfo.cb = sizeof(startupInfo);
  740. PROCESS_INFORMATION processInfo;
  741. memset(&startupInfo,0,sizeof(STARTUPINFOA));
  742. memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
  743. if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" install \"" + _r->homePath + "\\ztTap100.inf\" ztTap100").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
  744. RegCloseKey(nwAdapters);
  745. throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon);
  746. }
  747. WaitForSingleObject(processInfo.hProcess,INFINITE);
  748. CloseHandle(processInfo.hProcess);
  749. CloseHandle(processInfo.hThread);
  750. // Scan for the new instance by simply looking for taps that weren't
  751. // there originally.
  752. for(DWORD subkeyIndex=0;subkeyIndex!=-1;) {
  753. DWORD type;
  754. DWORD dataLen;
  755. DWORD subkeyNameLen = sizeof(subkeyName);
  756. DWORD subkeyClassLen = sizeof(subkeyClass);
  757. FILETIME lastWriteTime;
  758. switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) {
  759. case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break;
  760. case ERROR_SUCCESS:
  761. type = 0;
  762. dataLen = sizeof(data);
  763. if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
  764. data[dataLen] = '\0';
  765. if (!strnicmp(data,"zttap",5)) {
  766. type = 0;
  767. dataLen = sizeof(data);
  768. if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) {
  769. if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) {
  770. RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1));
  771. _myDeviceInstanceId.assign(data,dataLen);
  772. type = 0;
  773. dataLen = sizeof(data);
  774. if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS)
  775. _myDeviceInstanceIdPath.assign(data,dataLen);
  776. mySubkeyName = subkeyName;
  777. subkeyIndex = -1; // break outer loop
  778. }
  779. }
  780. }
  781. }
  782. break;
  783. }
  784. }
  785. }
  786. // If we have a device, configure it
  787. if (_myDeviceInstanceId.length() > 0) {
  788. char tmps[4096];
  789. unsigned int tmpsl = sprintf_s(tmps,"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac.data[0],(unsigned int)mac.data[1],(unsigned int)mac.data[2],(unsigned int)mac.data[3],(unsigned int)mac.data[4],(unsigned int)mac.data[5]) + 1;
  790. RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
  791. RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
  792. DWORD tmp = mtu;
  793. RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
  794. tmp = 0;
  795. RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp));
  796. }
  797. // Done with registry
  798. RegCloseKey(nwAdapters);
  799. // If we didn't get a device, we can't start
  800. if (_myDeviceInstanceId.length() == 0)
  801. throw std::runtime_error("unable to create new tap adapter");
  802. // Convert device GUID junk... blech
  803. {
  804. char nobraces[128];
  805. const char *nbtmp1 = _myDeviceInstanceId.c_str();
  806. char *nbtmp2 = nobraces;
  807. while (*nbtmp1) {
  808. if ((*nbtmp1 != '{')&&(*nbtmp1 != '}'))
  809. *nbtmp2++ = *nbtmp1;
  810. ++nbtmp1;
  811. }
  812. *nbtmp2 = (char)0;
  813. if (UuidFromStringA((RPC_CSTR)nobraces,&_deviceGuid) != RPC_S_OK)
  814. throw std::runtime_error("unable to convert instance ID GUID to native GUID (invalid NetCfgInstanceId in registry?)");
  815. }
  816. setDhcpEnabled(false);
  817. setDhcp6Enabled(false);
  818. // Disable and enable interface to ensure registry settings take effect
  819. {
  820. STARTUPINFOA startupInfo;
  821. startupInfo.cb = sizeof(startupInfo);
  822. PROCESS_INFORMATION processInfo;
  823. memset(&startupInfo,0,sizeof(STARTUPINFOA));
  824. memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
  825. if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
  826. RegCloseKey(nwAdapters);
  827. throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon);
  828. }
  829. WaitForSingleObject(processInfo.hProcess,INFINITE);
  830. CloseHandle(processInfo.hProcess);
  831. CloseHandle(processInfo.hThread);
  832. }
  833. {
  834. STARTUPINFOA startupInfo;
  835. startupInfo.cb = sizeof(startupInfo);
  836. PROCESS_INFORMATION processInfo;
  837. memset(&startupInfo,0,sizeof(STARTUPINFOA));
  838. memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
  839. if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" enable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
  840. RegCloseKey(nwAdapters);
  841. throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon);
  842. }
  843. WaitForSingleObject(processInfo.hProcess,INFINITE);
  844. CloseHandle(processInfo.hProcess);
  845. CloseHandle(processInfo.hThread);
  846. }
  847. // Open the tap, which is in this weird Windows analog of /dev
  848. char tapPath[4096];
  849. sprintf_s(tapPath,"\\\\.\\Global\\%s.tap",_myDeviceInstanceId.c_str());
  850. _tap = CreateFileA(tapPath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_SYSTEM|FILE_FLAG_OVERLAPPED,NULL);
  851. if (_tap == INVALID_HANDLE_VALUE)
  852. throw std::runtime_error("unable to open tap in \\\\.\\Global\\ namespace");
  853. // Set media status to enabled
  854. uint32_t tmpi = 1;
  855. DWORD bytesReturned = 0;
  856. DeviceIoControl(_tap,TAP_WIN_IOCTL_SET_MEDIA_STATUS,&tmpi,sizeof(tmpi),&tmpi,sizeof(tmpi),&bytesReturned,NULL);
  857. // Initialized overlapped I/O structures and related events
  858. memset(&_tapOvlRead,0,sizeof(_tapOvlRead));
  859. _tapOvlRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  860. memset(&_tapOvlWrite,0,sizeof(_tapOvlWrite));
  861. _tapOvlWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  862. // Start background thread that actually performs I/O
  863. _injectSemaphore = CreateSemaphore(NULL,0,1,NULL);
  864. _thread = Thread::start(this);
  865. }
  866. EthernetTap::~EthernetTap()
  867. {
  868. _run = false;
  869. ReleaseSemaphore(_injectSemaphore,1,NULL);
  870. Thread::join(_thread);
  871. CloseHandle(_tap);
  872. CloseHandle(_tapOvlRead.hEvent);
  873. CloseHandle(_tapOvlWrite.hEvent);
  874. CloseHandle(_injectSemaphore);
  875. // Disable network device on shutdown
  876. #ifdef _WIN64
  877. const char *devcon = "\\devcon64.exe";
  878. #else
  879. BOOL f64 = FALSE;
  880. const char *devcon = ((IsWow64Process(GetCurrentProcess(),&f64) == TRUE) ? "\\devcon64.exe" : "\\devcon32.exe");
  881. #endif
  882. {
  883. STARTUPINFOA startupInfo;
  884. startupInfo.cb = sizeof(startupInfo);
  885. PROCESS_INFORMATION processInfo;
  886. memset(&startupInfo,0,sizeof(STARTUPINFOA));
  887. memset(&processInfo,0,sizeof(PROCESS_INFORMATION));
  888. if (CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) {
  889. WaitForSingleObject(processInfo.hProcess,INFINITE);
  890. CloseHandle(processInfo.hProcess);
  891. CloseHandle(processInfo.hThread);
  892. }
  893. }
  894. }
  895. void EthernetTap::whack()
  896. {
  897. }
  898. bool EthernetTap::setDhcpEnabled(bool dhcp)
  899. {
  900. HKEY tcpIpInterfaces;
  901. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) {
  902. _dhcp = dhcp;
  903. DWORD enable = (dhcp ? 1 : 0);
  904. RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable));
  905. RegCloseKey(tcpIpInterfaces);
  906. } else _dhcp = false;
  907. return _dhcp;
  908. }
  909. bool EthernetTap::setDhcp6Enabled(bool dhcp)
  910. {
  911. // TODO
  912. return _dhcp6;
  913. }
  914. void EthernetTap::setDisplayName(const char *dn)
  915. {
  916. HKEY ifp;
  917. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,(std::string("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\") + _myDeviceInstanceId).c_str(),0,KEY_READ|KEY_WRITE,&ifp) == ERROR_SUCCESS) {
  918. RegSetKeyValueA(ifp,"Connection","Name",REG_SZ,(LPCVOID)dn,(DWORD)(strlen(dn)+1));
  919. RegCloseKey(ifp);
  920. }
  921. }
  922. bool EthernetTap::addIP(const InetAddress &ip)
  923. {
  924. Mutex::Lock _l(_ips_m);
  925. if (_ips.count(ip))
  926. return true;
  927. if (!ip.port())
  928. return false;
  929. try {
  930. std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
  931. MIB_UNICASTIPADDRESS_ROW ipr;
  932. InitializeUnicastIpAddressEntry(&ipr);
  933. if (ip.isV4()) {
  934. ipr.Address.Ipv4.sin_family = AF_INET;
  935. ipr.Address.Ipv4.sin_addr.S_un.S_addr = *((const uint32_t *)ip.rawIpData());
  936. ipr.OnLinkPrefixLength = ip.port();
  937. } else if (ip.isV6()) {
  938. } else return false;
  939. ipr.PrefixOrigin = IpPrefixOriginManual;
  940. ipr.SuffixOrigin = IpSuffixOriginManual;
  941. ipr.ValidLifetime = 0xffffffff;
  942. ipr.PreferredLifetime = 0xffffffff;
  943. ipr.InterfaceLuid = ifidx.first;
  944. ipr.InterfaceIndex = ifidx.second;
  945. if (CreateUnicastIpAddressEntry(&ipr) == NO_ERROR) {
  946. _ips.insert(ip);
  947. return true;
  948. }
  949. } catch ( ... ) {}
  950. return false;
  951. }
  952. bool EthernetTap::removeIP(const InetAddress &ip)
  953. {
  954. try {
  955. MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
  956. std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
  957. if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
  958. for(DWORD i=0;i<ipt->NumEntries;++i) {
  959. if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
  960. InetAddress addr;
  961. switch(ipt->Table[i].Address.si_family) {
  962. case AF_INET:
  963. addr.set(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength);
  964. break;
  965. case AF_INET6:
  966. addr.set(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
  967. break;
  968. }
  969. if (addr == ip) {
  970. DeleteUnicastIpAddressEntry(&(ipt->Table[i]));
  971. FreeMibTable(ipt);
  972. Mutex::Lock _l(_ips_m);
  973. _ips.erase(ip);
  974. return true;
  975. }
  976. }
  977. }
  978. FreeMibTable(&ipt);
  979. }
  980. } catch ( ... ) {}
  981. return false;
  982. }
  983. std::set<InetAddress> EthernetTap::allIps() const
  984. {
  985. static const InetAddress ifLoopback("fe80::1",64);
  986. std::set<InetAddress> addrs;
  987. try {
  988. MIB_UNICASTIPADDRESS_TABLE *ipt = (MIB_UNICASTIPADDRESS_TABLE *)0;
  989. std::pair<NET_LUID,NET_IFINDEX> ifidx = _findAdapterByGuid(_deviceGuid);
  990. if (GetUnicastIpAddressTable(AF_UNSPEC,&ipt) == NO_ERROR) {
  991. for(DWORD i=0;i<ipt->NumEntries;++i) {
  992. if ((ipt->Table[i].InterfaceLuid.Value == ifidx.first.Value)&&(ipt->Table[i].InterfaceIndex == ifidx.second)) {
  993. switch(ipt->Table[i].Address.si_family) {
  994. case AF_INET:
  995. addrs.insert(InetAddress(&(ipt->Table[i].Address.Ipv4.sin_addr.S_un.S_addr),4,ipt->Table[i].OnLinkPrefixLength));
  996. break;
  997. case AF_INET6: {
  998. InetAddress ip(ipt->Table[i].Address.Ipv6.sin6_addr.u.Byte,16,ipt->Table[i].OnLinkPrefixLength);
  999. if (ip != ifLoopback) // don't include fe80::1
  1000. addrs.insert(ip);
  1001. } break;
  1002. }
  1003. }
  1004. }
  1005. FreeMibTable(ipt);
  1006. }
  1007. } catch ( ... ) {}
  1008. return addrs;
  1009. }
  1010. void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const void *data,unsigned int len)
  1011. {
  1012. if (len > (ZT_IF_MTU))
  1013. return;
  1014. {
  1015. Mutex::Lock _l(_injectPending_m);
  1016. _injectPending.push( std::pair<Array<char,ZT_IF_MTU + 32>,unsigned int>(Array<char,ZT_IF_MTU + 32>(),len + 14) );
  1017. char *d = _injectPending.back().first.data;
  1018. memcpy(d,to.data,6);
  1019. memcpy(d + 6,from.data,6);
  1020. *((uint16_t *)(d + 12)) = Utils::hton(etherType);
  1021. memcpy(d + 14,data,len);
  1022. }
  1023. ReleaseSemaphore(_injectSemaphore,1,NULL);
  1024. }
  1025. std::string EthernetTap::deviceName() const
  1026. {
  1027. return _myDeviceInstanceId;
  1028. }
  1029. bool EthernetTap::updateMulticastGroups(std::set<MulticastGroup> &groups)
  1030. {
  1031. std::set<MulticastGroup> newGroups;
  1032. std::set<InetAddress> ipaddrs(allIps());
  1033. for(std::set<InetAddress>::const_iterator i(ipaddrs.begin());i!=ipaddrs.end();++i)
  1034. newGroups.insert(MulticastGroup::deriveMulticastGroupForAddressResolution(*i));
  1035. bool changed = false;
  1036. newGroups.insert(_blindWildcardMulticastGroup); // always join this
  1037. for(std::set<MulticastGroup>::iterator mg(newGroups.begin());mg!=newGroups.end();++mg) {
  1038. if (!groups.count(*mg)) {
  1039. groups.insert(*mg);
  1040. changed = true;
  1041. }
  1042. }
  1043. for(std::set<MulticastGroup>::iterator mg(groups.begin());mg!=groups.end();) {
  1044. if (!newGroups.count(*mg)) {
  1045. groups.erase(mg++);
  1046. changed = true;
  1047. } else ++mg;
  1048. }
  1049. return changed;
  1050. }
  1051. void EthernetTap::threadMain()
  1052. throw()
  1053. {
  1054. HANDLE wait4[3];
  1055. wait4[0] = _injectSemaphore;
  1056. wait4[1] = _tapOvlRead.hEvent;
  1057. wait4[2] = _tapOvlWrite.hEvent;
  1058. ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
  1059. bool writeInProgress = false;
  1060. for(;;) {
  1061. if (!_run) break;
  1062. WaitForMultipleObjectsEx(3,wait4,FALSE,INFINITE,TRUE);
  1063. if (!_run) break;
  1064. if (HasOverlappedIoCompleted(&_tapOvlRead)) {
  1065. DWORD bytesRead = 0;
  1066. if (GetOverlappedResult(_tap,&_tapOvlRead,&bytesRead,FALSE)) {
  1067. if (bytesRead > 14) {
  1068. MAC to(_tapReadBuf);
  1069. MAC from(_tapReadBuf + 6);
  1070. unsigned int etherType = Utils::ntoh(*((const uint16_t *)(_tapReadBuf + 12)));
  1071. Buffer<4096> tmp(_tapReadBuf + 14,bytesRead - 14);
  1072. //printf("GOT FRAME: %u bytes: %s\r\n",(unsigned int)bytesRead,Utils::hex(_tapReadBuf,bytesRead).c_str());
  1073. _handler(_arg,from,to,etherType,tmp);
  1074. }
  1075. }
  1076. ReadFile(_tap,_tapReadBuf,sizeof(_tapReadBuf),NULL,&_tapOvlRead);
  1077. }
  1078. if (writeInProgress) {
  1079. if (HasOverlappedIoCompleted(&_tapOvlWrite)) {
  1080. writeInProgress = false;
  1081. _injectPending_m.lock();
  1082. _injectPending.pop();
  1083. } else continue; // still writing, so skip code below and wait
  1084. } else _injectPending_m.lock();
  1085. if (!_injectPending.empty()) {
  1086. WriteFile(_tap,_injectPending.front().first.data,_injectPending.front().second,NULL,&_tapOvlWrite);
  1087. writeInProgress = true;
  1088. }
  1089. _injectPending_m.unlock();
  1090. }
  1091. CancelIo(_tap);
  1092. }
  1093. } // namespace ZeroTier
  1094. #endif // __WINDOWS__ ////////////////////////////////////////////////////////