PageRenderTime 27ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/asiotap/src/posix/posix_tap_adapter.cpp

https://gitlab.com/freelan-developers/freelan
C++ | 816 lines | 571 code | 173 blank | 72 comment | 105 complexity | 47376d90a60d990f708cf00d3aacbcae MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0
  1. /*
  2. * libasiotap - A portable TAP adapter extension for Boost::ASIO.
  3. * Copyright (C) 2010-2011 Julien KAUFFMANN <julien.kauffmann@freelan.org>
  4. *
  5. * This file is part of libasiotap.
  6. *
  7. * libasiotap is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 3 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * libasiotap is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public
  18. * License along with this program. If not, see
  19. * <http://www.gnu.org/licenses/>.
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. *
  34. * If you intend to use libasiotap in a commercial software, please
  35. * contact me : we may arrange this for a small fee or no fee at all,
  36. * depending on the nature of your project.
  37. */
  38. /**
  39. * \file posix_tap_adapter.cpp
  40. * \author Julien KAUFFMANN <julien.kauffmann@freelan.org>
  41. * \brief The posix tap adapter class.
  42. */
  43. #include "posix/posix_tap_adapter.hpp"
  44. #include <boost/lexical_cast.hpp>
  45. #include <sys/types.h>
  46. #include <sys/wait.h>
  47. #include <ifaddrs.h>
  48. #include <errno.h>
  49. #include <unistd.h>
  50. #include <fcntl.h>
  51. #ifdef LINUX
  52. #include <linux/if_tun.h>
  53. /**
  54. * \struct in6_ifreq
  55. * \brief Replacement structure since the include of linux/ipv6.h introduces conflicts.
  56. *
  57. * If someone comes up with a better solution, feel free to contribute :)
  58. */
  59. struct in6_ifreq
  60. {
  61. struct in6_addr ifr6_addr; /**< IPv6 address */
  62. uint32_t ifr6_prefixlen; /**< Length of the prefix */
  63. int ifr6_ifindex; /**< Interface index */
  64. };
  65. #elif defined(MACINTOSH) || defined(BSD)
  66. /*
  67. * Note for Mac OS X users : you have to download and install the tun/tap driver from (http://tuntaposx.sourceforge.net).
  68. */
  69. #include <net/if_var.h>
  70. #include <net/if_types.h>
  71. #include <net/if_dl.h>
  72. #include <net/if.h>
  73. #include <netinet/in.h>
  74. #include <netinet6/in6_var.h>
  75. #endif
  76. namespace asiotap
  77. {
  78. namespace
  79. {
  80. unsigned int netmask_to_prefix_len(in_addr netmask)
  81. {
  82. uint32_t bits = ~ntohl(netmask.s_addr);
  83. unsigned int result = 0;
  84. while (bits > 0) {
  85. bits >>= 1;
  86. ++result;
  87. }
  88. return (sizeof(in_addr) * 8) - result;
  89. }
  90. unsigned int netmask_to_prefix_len(in6_addr netmask)
  91. {
  92. unsigned int result = 0;
  93. for (size_t i = 0; i < sizeof(netmask.s6_addr); ++i)
  94. {
  95. uint8_t bits = ~netmask.s6_addr[i];
  96. while (bits > 0) {
  97. bits >>= 1;
  98. ++result;
  99. }
  100. }
  101. return (sizeof(in6_addr) * 8) - result;
  102. }
  103. class descriptor_handler
  104. {
  105. public:
  106. descriptor_handler() : m_fd(-1) {}
  107. explicit descriptor_handler(int fd) : m_fd(fd) {}
  108. descriptor_handler(const descriptor_handler&) = delete;
  109. descriptor_handler& operator=(const descriptor_handler&) = delete;
  110. descriptor_handler(descriptor_handler&& other) : m_fd(other.m_fd) { other.m_fd = -1; }
  111. descriptor_handler& operator=(descriptor_handler&& other) { using std::swap; swap(m_fd, other.m_fd); return *this; }
  112. ~descriptor_handler() { if (m_fd >= 0) { ::close(m_fd); }}
  113. int native_handle() const { return m_fd; }
  114. bool valid() const { return (m_fd >= 0); }
  115. int release() { const int result = m_fd; m_fd = -1; return result; }
  116. private:
  117. int m_fd;
  118. };
  119. descriptor_handler open_device(const std::string& name, boost::system::error_code& ec)
  120. {
  121. const int device_fd = ::open(name.c_str(), O_RDWR);
  122. if (device_fd < 0)
  123. {
  124. // Unable to open the device.
  125. ec = boost::system::error_code(errno, boost::system::system_category());
  126. return descriptor_handler();
  127. }
  128. return descriptor_handler(device_fd);
  129. }
  130. descriptor_handler open_socket(int family, boost::system::error_code& ec)
  131. {
  132. const int socket_fd = ::socket(family, SOCK_DGRAM, 0);
  133. if (socket_fd < 0)
  134. {
  135. ec = boost::system::error_code(errno, boost::system::system_category());
  136. return descriptor_handler();
  137. }
  138. return descriptor_handler(socket_fd);
  139. }
  140. descriptor_handler open_socket(int family)
  141. {
  142. boost::system::error_code ec;
  143. descriptor_handler result = open_socket(family, ec);
  144. if (!result.valid())
  145. {
  146. throw boost::system::system_error(ec);
  147. }
  148. return result;
  149. }
  150. }
  151. std::map<std::string, std::string> posix_tap_adapter::enumerate(tap_adapter_layer _layer)
  152. {
  153. std::map<std::string, std::string> result;
  154. struct ifaddrs* addrs = nullptr;
  155. if (getifaddrs(&addrs) != -1)
  156. {
  157. boost::shared_ptr<struct ifaddrs> paddrs(addrs, freeifaddrs);
  158. for (struct ifaddrs* ifa = paddrs.get(); ifa != NULL ; ifa = ifa->ifa_next)
  159. {
  160. const std::string name(ifa->ifa_name);
  161. switch (_layer)
  162. {
  163. case tap_adapter_layer::ethernet:
  164. {
  165. if (name.substr(0, 3) == "tap")
  166. {
  167. result[name] = name;
  168. }
  169. }
  170. case tap_adapter_layer::ip:
  171. {
  172. if (name.substr(0, 3) == "tun")
  173. {
  174. result[name] = name;
  175. }
  176. }
  177. }
  178. }
  179. }
  180. return result;
  181. }
  182. void posix_tap_adapter::open(boost::system::error_code& ec)
  183. {
  184. open("", ec);
  185. }
  186. void posix_tap_adapter::open(const std::string& _name, boost::system::error_code& ec)
  187. {
  188. ec = boost::system::error_code();
  189. #if defined(LINUX)
  190. const std::string dev_name = (layer() == tap_adapter_layer::ethernet) ? "/dev/net/tap" : "/dev/net/tun";
  191. if (::access(dev_name.c_str(), F_OK) == -1)
  192. {
  193. if (errno != ENOENT)
  194. {
  195. // Unable to access the tap adapter yet it exists: this is an error.
  196. ec = boost::system::error_code(errno, boost::system::system_category());
  197. return;
  198. }
  199. // No tap found, create one.
  200. if (::mknod(dev_name.c_str(), S_IFCHR | S_IRUSR | S_IWUSR, ::makedev(10, 200)) == -1)
  201. {
  202. ec = boost::system::error_code(errno, boost::system::system_category());
  203. return;
  204. }
  205. }
  206. descriptor_handler device = open_device(dev_name, ec);
  207. if (!device.valid())
  208. {
  209. return;
  210. }
  211. struct ifreq ifr {};
  212. ifr.ifr_flags = IFF_NO_PI;
  213. #if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
  214. ifr.ifr_flags |= IFF_ONE_QUEUE;
  215. #endif
  216. if (layer() == tap_adapter_layer::ethernet)
  217. {
  218. ifr.ifr_flags |= IFF_TAP;
  219. }
  220. else
  221. {
  222. ifr.ifr_flags |= IFF_TUN;
  223. }
  224. if (!_name.empty())
  225. {
  226. strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
  227. }
  228. // Set the parameters on the tun device.
  229. if (::ioctl(device.native_handle(), TUNSETIFF, (void *)&ifr) < 0)
  230. {
  231. ec = boost::system::error_code(errno, boost::system::system_category());
  232. return;
  233. }
  234. descriptor_handler socket = open_socket(AF_INET, ec);
  235. if (!socket.valid())
  236. {
  237. return;
  238. }
  239. {
  240. struct ifreq netifr {};
  241. std::strncpy(netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
  242. #if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
  243. netifr.ifr_qlen = 100; // 100 is the default value
  244. if (::ioctl(socket.native_handle(), SIOCSIFTXQLEN, (void *)&netifr) < 0)
  245. {
  246. ec = boost::system::error_code(errno, boost::system::system_category());
  247. return;
  248. }
  249. // Reset the structure for the next call.
  250. netifr = {};
  251. std::strncpy(netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
  252. #endif
  253. // Get the interface hwaddr
  254. if (::ioctl(socket.native_handle(), SIOCGIFHWADDR, (void*)&netifr) < 0)
  255. {
  256. ec = boost::system::error_code(errno, boost::system::system_category());
  257. return;
  258. }
  259. osi::ethernet_address _ethernet_address;
  260. std::memcpy(_ethernet_address.data().data(), netifr.ifr_hwaddr.sa_data, _ethernet_address.data().size());
  261. set_ethernet_address(_ethernet_address);
  262. }
  263. set_name(ifr.ifr_name);
  264. #else /* *BSD and Mac OS X */
  265. const std::string dev_type = (layer() == tap_adapter_layer::ethernet) ? "tap" : "tun";
  266. std::string interface_name = _name;
  267. descriptor_handler device;
  268. if (!_name.empty())
  269. {
  270. device = open_device("/dev/" + _name, ec);
  271. }
  272. else
  273. {
  274. for (unsigned int i = 0 ; !device.valid(); ++i)
  275. {
  276. interface_name = dev_type + boost::lexical_cast<std::string>(i);
  277. device = open_device("/dev/" + interface_name, ec);
  278. if (!device.valid() && (errno == ENOENT))
  279. {
  280. // We reached the end of the available tap adapters.
  281. break;
  282. }
  283. }
  284. }
  285. if (!device.valid())
  286. {
  287. ec = make_error_code(asiotap_error::no_such_tap_adapter);
  288. return;
  289. }
  290. struct stat st {};
  291. if (::fstat(device.native_handle(), &st) != 0)
  292. {
  293. ec = boost::system::error_code(errno, boost::system::system_category());
  294. return;
  295. }
  296. char namebuf[256];
  297. memset(namebuf, 0x00, sizeof(namebuf));
  298. if (::devname_r(st.st_dev, S_IFCHR, namebuf, 255) != NULL)
  299. {
  300. set_name(namebuf);
  301. }
  302. else
  303. {
  304. set_name(interface_name);
  305. }
  306. if (if_nametoindex(name().c_str()) == 0)
  307. {
  308. ec = make_error_code(asiotap_error::no_such_tap_adapter);
  309. return;
  310. }
  311. // Do not pass the descriptor to child
  312. ::fcntl(device.native_handle(), F_SETFD, FD_CLOEXEC);
  313. descriptor_handler socket = open_socket(AF_INET, ec);
  314. if (!socket.valid())
  315. {
  316. return;
  317. }
  318. /* Get the hardware address of tap inteface. */
  319. struct ifaddrs* addrs = nullptr;
  320. if (getifaddrs(&addrs) < 0)
  321. {
  322. ec = boost::system::error_code(errno, boost::system::system_category());
  323. return;
  324. }
  325. boost::shared_ptr<struct ifaddrs> paddrs(addrs, freeifaddrs);
  326. for (struct ifaddrs* ifa = addrs; ifa != NULL; ifa = ifa->ifa_next)
  327. {
  328. const std::string if_name = name();
  329. if ((ifa->ifa_addr->sa_family == AF_LINK) && !std::memcmp(ifa->ifa_name, if_name.c_str(), if_name.length()))
  330. {
  331. struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifa->ifa_addr;
  332. if (sdl->sdl_type == IFT_ETHER)
  333. {
  334. osi::ethernet_address _ethernet_address;
  335. std::memcpy(_ethernet_address.data().data(), LLADDR(sdl), ethernet_address().data().size());
  336. set_ethernet_address(_ethernet_address);
  337. break;
  338. }
  339. }
  340. }
  341. #endif
  342. update_mtu_from_device();
  343. if (descriptor().assign(device.release(), ec))
  344. {
  345. return;
  346. }
  347. }
  348. void posix_tap_adapter::open(const std::string& _name)
  349. {
  350. boost::system::error_code ec;
  351. open(_name, ec);
  352. if (ec)
  353. {
  354. throw boost::system::system_error(ec);
  355. }
  356. }
  357. void posix_tap_adapter::destroy_device()
  358. {
  359. boost::system::error_code ec;
  360. destroy_device(ec);
  361. if (ec)
  362. {
  363. throw boost::system::system_error(ec);
  364. }
  365. }
  366. void posix_tap_adapter::destroy_device(boost::system::error_code& ec)
  367. {
  368. #if defined(MACINTOSH) || defined(BSD)
  369. descriptor_handler socket = open_socket(AF_INET, ec);
  370. if (!socket.valid())
  371. {
  372. return;
  373. }
  374. struct ifreq ifr {};
  375. strncpy(ifr.ifr_name, name().c_str(), IFNAMSIZ);
  376. // Destroy the virtual tap device
  377. if (ioctl(socket.native_handle(), SIOCIFDESTROY, &ifr) < 0)
  378. {
  379. ec = boost::system::error_code(errno, boost::system::system_category());
  380. }
  381. #else
  382. static_cast<void>(ec);
  383. #endif
  384. }
  385. void posix_tap_adapter::set_connected_state(bool connected)
  386. {
  387. descriptor_handler socket = open_socket(AF_INET);
  388. struct ifreq netifr {};
  389. strncpy(netifr.ifr_name, name().c_str(), IFNAMSIZ);
  390. // Set the interface UP
  391. if (::ioctl(socket.native_handle(), SIOCGIFFLAGS, static_cast<void*>(&netifr)) < 0)
  392. {
  393. throw boost::system::system_error(errno, boost::system::system_category());
  394. }
  395. if (connected)
  396. {
  397. #ifdef MACINTOSH
  398. netifr.ifr_flags |= IFF_UP;
  399. #else
  400. netifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
  401. #endif
  402. }
  403. else
  404. {
  405. #ifdef MACINTOSH
  406. // Mac OS X: set_connected_state(false) seems to confuse the TAP
  407. // so do nothing for the moment.
  408. return;
  409. #else
  410. netifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
  411. #endif
  412. }
  413. if (::ioctl(socket.native_handle(), SIOCSIFFLAGS, static_cast<void*>(&netifr)) < 0)
  414. {
  415. throw boost::system::system_error(errno, boost::system::system_category());
  416. }
  417. }
  418. ip_network_address_list posix_tap_adapter::get_ip_addresses()
  419. {
  420. ip_network_address_list result;
  421. struct ifaddrs* addrs = nullptr;
  422. if (::getifaddrs(&addrs) < 0)
  423. {
  424. throw boost::system::system_error(errno, boost::system::system_category());
  425. }
  426. boost::shared_ptr<struct ifaddrs> paddrs(addrs, ::freeifaddrs);
  427. for (struct ifaddrs* ifa = paddrs.get(); ifa != nullptr; ifa = ifa->ifa_next)
  428. {
  429. const std::string ifname(ifa->ifa_name);
  430. if ((ifa->ifa_addr) && (ifname == name()))
  431. {
  432. if (ifa->ifa_addr->sa_family == AF_INET)
  433. {
  434. struct sockaddr_in* sai = reinterpret_cast<struct sockaddr_in*>(ifa->ifa_addr);
  435. boost::asio::ip::address_v4::bytes_type bytes;
  436. memcpy(bytes.data(), &sai->sin_addr, bytes.size());
  437. boost::asio::ip::address_v4 address(bytes);
  438. unsigned int prefix_len = sizeof(in_addr) * 8;
  439. if (ifa->ifa_netmask)
  440. {
  441. struct sockaddr_in* sain = reinterpret_cast<struct sockaddr_in*>(ifa->ifa_netmask);
  442. prefix_len = netmask_to_prefix_len(sain->sin_addr);
  443. }
  444. result.push_back(ipv4_network_address{ address, prefix_len });
  445. }
  446. else if (ifa->ifa_addr->sa_family == AF_INET6)
  447. {
  448. struct sockaddr_in6* sai = reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_addr);
  449. boost::asio::ip::address_v6::bytes_type bytes;
  450. memcpy(bytes.data(), &sai->sin6_addr, bytes.size());
  451. boost::asio::ip::address_v6 address(bytes);
  452. unsigned int prefix_len = sizeof(in6_addr) * 8;
  453. if (ifa->ifa_netmask)
  454. {
  455. struct sockaddr_in6* sain = reinterpret_cast<struct sockaddr_in6*>(ifa->ifa_netmask);
  456. prefix_len = netmask_to_prefix_len(sain->sin6_addr);
  457. }
  458. result.push_back(ipv6_network_address{ address, prefix_len });
  459. }
  460. }
  461. }
  462. return result;
  463. }
  464. void posix_tap_adapter::configure(const configuration_type& configuration)
  465. {
  466. if (configuration.ipv4.network_address)
  467. {
  468. if (layer() == tap_adapter_layer::ethernet)
  469. {
  470. set_ip_address_v4(*configuration.ipv4.network_address);
  471. }
  472. else
  473. {
  474. if (configuration.ipv4.remote_address)
  475. {
  476. set_remote_ip_address_v4(*configuration.ipv4.network_address, *configuration.ipv4.remote_address);
  477. }
  478. }
  479. }
  480. if (configuration.ipv6.network_address)
  481. {
  482. set_ip_address_v6(*configuration.ipv6.network_address);
  483. }
  484. if (configuration.mtu > 0)
  485. {
  486. set_device_mtu(configuration.mtu);
  487. }
  488. }
  489. void posix_tap_adapter::update_mtu_from_device()
  490. {
  491. descriptor_handler socket = open_socket(AF_INET);
  492. struct ifreq netifr {};
  493. strncpy(netifr.ifr_name, name().c_str(), IFNAMSIZ);
  494. if (::ioctl(socket.native_handle(), SIOCGIFMTU, (void*)&netifr) >= 0)
  495. {
  496. set_mtu(netifr.ifr_mtu);
  497. }
  498. else
  499. {
  500. throw boost::system::system_error(errno, boost::system::system_category());
  501. }
  502. }
  503. void posix_tap_adapter::set_device_mtu(size_t _mtu)
  504. {
  505. descriptor_handler socket = open_socket(AF_INET);
  506. struct ifreq netifr {};
  507. strncpy(netifr.ifr_name, name().c_str(), IFNAMSIZ);
  508. netifr.ifr_mtu = _mtu;
  509. if (::ioctl(socket.native_handle(), SIOCSIFMTU, (void*)&netifr) < 0)
  510. {
  511. throw boost::system::system_error(errno, boost::system::system_category());
  512. }
  513. }
  514. void posix_tap_adapter::set_ip_address_v4(const ipv4_network_address& network_address)
  515. {
  516. const boost::asio::ip::address_v4& address = network_address.address();
  517. const unsigned int prefix_len = network_address.prefix_length();
  518. assert(prefix_len < 32);
  519. descriptor_handler socket = open_socket(AF_INET);
  520. ifreq ifr_a {};
  521. std::strncpy(ifr_a.ifr_name, name().c_str(), IFNAMSIZ - 1);
  522. sockaddr_in* ifr_a_addr = reinterpret_cast<sockaddr_in*>(&ifr_a.ifr_addr);
  523. ifr_a_addr->sin_family = AF_INET;
  524. #ifdef BSD
  525. ifr_a_addr->sin_len = sizeof(sockaddr_in);
  526. #endif
  527. std::memcpy(&ifr_a_addr->sin_addr.s_addr, address.to_bytes().data(), address.to_bytes().size());
  528. if (::ioctl(socket.native_handle(), SIOCSIFADDR, &ifr_a) < 0)
  529. {
  530. if (errno == EEXIST)
  531. {
  532. // The address is already set. We ignore this.
  533. }
  534. else
  535. {
  536. throw boost::system::system_error(errno, boost::system::system_category());
  537. }
  538. }
  539. if (prefix_len > 0)
  540. {
  541. ifreq ifr_n {};
  542. std::strncpy(ifr_n.ifr_name, name().c_str(), IFNAMSIZ - 1);
  543. sockaddr_in* ifr_n_addr = reinterpret_cast<sockaddr_in*>(&ifr_n.ifr_addr);
  544. ifr_n_addr->sin_family = AF_INET;
  545. #ifdef BSD
  546. ifr_n_addr->sin_len = sizeof(sockaddr_in);
  547. #endif
  548. ifr_n_addr->sin_addr.s_addr = htonl((0xFFFFFFFF >> (32 - prefix_len)) << (32 - prefix_len));
  549. if (::ioctl(socket.native_handle(), SIOCSIFNETMASK, &ifr_n) < 0)
  550. {
  551. if (errno == EEXIST)
  552. {
  553. // The netmask is already set. We ignore this.
  554. }
  555. else
  556. {
  557. throw boost::system::system_error(errno, boost::system::system_category());
  558. }
  559. }
  560. }
  561. }
  562. void posix_tap_adapter::set_ip_address_v6(const ipv6_network_address& network_address)
  563. {
  564. const boost::asio::ip::address_v6& address = network_address.address();
  565. const unsigned int prefix_len = network_address.prefix_length();
  566. assert(prefix_len < 128);
  567. descriptor_handler socket = open_socket(AF_INET6);
  568. #ifdef LINUX
  569. const unsigned int if_index = ::if_nametoindex(name().c_str());
  570. if (if_index == 0)
  571. {
  572. throw boost::system::system_error(errno, boost::system::system_category());
  573. }
  574. in6_ifreq ifr {};
  575. std::memcpy(&ifr.ifr6_addr, address.to_bytes().data(), address.to_bytes().size());
  576. ifr.ifr6_prefixlen = prefix_len;
  577. ifr.ifr6_ifindex = if_index;
  578. if (::ioctl(socket.native_handle(), SIOCSIFADDR, &ifr) < 0)
  579. #elif defined(MACINTOSH) || defined(BSD)
  580. in6_aliasreq iar {};
  581. std::memcpy(iar.ifra_name, name().c_str(), name().length());
  582. reinterpret_cast<sockaddr_in6*>(&iar.ifra_addr)->sin6_family = AF_INET6;
  583. reinterpret_cast<sockaddr_in6*>(&iar.ifra_prefixmask)->sin6_family = AF_INET6;
  584. std::memcpy(&reinterpret_cast<sockaddr_in6*>(&iar.ifra_addr)->sin6_addr, address.to_bytes().data(), address.to_bytes().size());
  585. std::memset(reinterpret_cast<sockaddr_in6*>(&iar.ifra_prefixmask)->sin6_addr.s6_addr, 0xFF, prefix_len / 8);
  586. reinterpret_cast<sockaddr_in6*>(&iar.ifra_prefixmask)->sin6_addr.s6_addr[prefix_len / 8] = (0xFF << (8 - (prefix_len % 8)));
  587. iar.ifra_lifetime.ia6t_pltime = 0xFFFFFFFF;
  588. iar.ifra_lifetime.ia6t_vltime = 0xFFFFFFFF;
  589. #ifdef SIN6_LEN
  590. reinterpret_cast<sockaddr_in6*>(&iar.ifra_addr)->sin6_len = sizeof(sockaddr_in6);
  591. reinterpret_cast<sockaddr_in6*>(&iar.ifra_prefixmask)->sin6_len = sizeof(sockaddr_in6);
  592. #endif
  593. if (::ioctl(socket.native_handle(), SIOCAIFADDR_IN6, &iar) < 0)
  594. #endif
  595. {
  596. if (errno == EEXIST)
  597. {
  598. // The address is already set. We ignore this.
  599. }
  600. else
  601. {
  602. throw boost::system::system_error(errno, boost::system::system_category());
  603. }
  604. }
  605. }
  606. void posix_tap_adapter::set_remote_ip_address_v4(const ipv4_network_address& network_address, const boost::asio::ip::address_v4& remote_address)
  607. {
  608. if (layer() != tap_adapter_layer::ip)
  609. {
  610. throw boost::system::system_error(make_error_code(asiotap_error::invalid_tap_adapter_layer));
  611. }
  612. #ifdef MACINTOSH
  613. // The TUN adapter for Mac OSX has a weird behavior regarding routes and ioctl.
  614. // For some reason, on Mac, setting up the IP address using ioctl() doesn't work for TUN devices.
  615. m_route_manager.ifconfig(name(), network_address, remote_address);
  616. // OSX apparently does not create a route even though ifconfig indicates that the netmask is understood.
  617. // We must create it ourselves.
  618. m_route_manager.set_route(posix_route_manager::route_action::add, name(), network_address);
  619. #else
  620. set_ip_address_v4(network_address);
  621. descriptor_handler socket = open_socket(AF_INET);
  622. ifreq ifr_d {};
  623. std::strncpy(ifr_d.ifr_name, name().c_str(), IFNAMSIZ - 1);
  624. sockaddr_in* ifr_dst_addr = reinterpret_cast<sockaddr_in*>(&ifr_d.ifr_dstaddr);
  625. ifr_dst_addr->sin_family = AF_INET;
  626. #ifdef BSD
  627. ifr_dst_addr->sin_len = sizeof(sockaddr_in);
  628. #endif
  629. std::memcpy(&ifr_dst_addr->sin_addr.s_addr, remote_address.to_bytes().data(), remote_address.to_bytes().size());
  630. if (::ioctl(socket.native_handle(), SIOCSIFDSTADDR, &ifr_d) < 0)
  631. {
  632. if (errno == EEXIST)
  633. {
  634. // The address is already set. We ignore this.
  635. }
  636. else
  637. {
  638. throw boost::system::system_error(errno, boost::system::system_category());
  639. }
  640. }
  641. #endif
  642. }
  643. }