LinuxNetLink.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2018 ZeroTier, Inc. https://www.zerotier.com/
  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. * You can be released from the requirements of the license by purchasing
  21. * a commercial license. Buying such a license is mandatory as soon as you
  22. * develop commercial closed-source software that incorporates or links
  23. * directly against ZeroTier software without disclosing the source code
  24. * of your own application.
  25. */
  26. #include "LinuxNetLink.hpp"
  27. #include <unistd.h>
  28. #include <linux/if_tun.h>
  29. namespace ZeroTier {
  30. struct nl_route_req {
  31. struct nlmsghdr nl;
  32. struct rtmsg rt;
  33. char buf[8192];
  34. };
  35. struct nl_if_req {
  36. struct nlmsghdr nl;
  37. struct ifinfomsg ifa;
  38. char buf[8192];
  39. };
  40. struct nl_adr_req {
  41. struct nlmsghdr nl;
  42. struct ifaddrmsg ifa;
  43. char buf[8192];
  44. };
  45. LinuxNetLink::LinuxNetLink()
  46. : _t()
  47. , _running(false)
  48. , _routes_ipv4()
  49. , _routes_ipv6()
  50. , _seq(0)
  51. , _fd(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE))
  52. , _la({0})
  53. {
  54. // set socket timeout to 1 sec so we're not permablocking recv() calls
  55. struct timeval tv;
  56. tv.tv_sec = 1;
  57. tv.tv_usec = 0;
  58. if(setsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) != 0) {
  59. fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
  60. }
  61. _la.nl_family = AF_NETLINK;
  62. _la.nl_pid = getpid();
  63. _la.nl_groups = RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR|RTMGRP_IPV4_ROUTE|RTMGRP_IPV6_ROUTE|RTMGRP_NOTIFY;
  64. if (bind(_fd, (struct sockaddr*)&_la, sizeof(_la))) {
  65. fprintf(stderr, "Error connecting to RTNETLINK: %s\n", strerror(errno));
  66. ::exit(1);
  67. }
  68. _running = true;
  69. _t = Thread::start(this);
  70. fprintf(stderr, "Requesting IPV4 Routes\n");
  71. _requestIPv4Routes();
  72. Thread::sleep(10);
  73. fprintf(stderr, "Requesting IPV6 Routes\n");
  74. _requestIPv6Routes();
  75. Thread::sleep(10);
  76. fprintf(stderr, "Requesting Interface List\n");
  77. _requestInterfaceList();
  78. }
  79. LinuxNetLink::~LinuxNetLink()
  80. {
  81. _running = false;
  82. Thread::join(_t);
  83. ::close(_fd);
  84. }
  85. void LinuxNetLink::threadMain() throw()
  86. {
  87. char buf[8192];
  88. char *p = NULL;
  89. struct nlmsghdr *nlp;
  90. int nll = 0;
  91. int rtn = 0;
  92. p = buf;
  93. while(_running) {
  94. rtn = recv(_fd, p, sizeof(buf) - nll, 0);
  95. if (rtn > 0) {
  96. nlp = (struct nlmsghdr *)p;
  97. if(nlp->nlmsg_type == NLMSG_ERROR && (nlp->nlmsg_flags & NLM_F_ACK) != NLM_F_ACK) {
  98. fprintf(stderr, "NLMSG_ERROR\n");
  99. struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlp);
  100. if (err->error != 0) {
  101. fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
  102. }
  103. p = buf;
  104. nll = 0;
  105. continue;
  106. }
  107. if (nlp->nlmsg_type == NLMSG_NOOP) {
  108. fprintf(stderr, "noop\n");
  109. continue;
  110. }
  111. if( (nlp->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI || (nlp->nlmsg_type == NLMSG_DONE))
  112. {
  113. if (nlp->nlmsg_type == NLMSG_DONE) {
  114. _processMessage(nlp, nll);
  115. p = buf;
  116. nll = 0;
  117. continue;
  118. }
  119. p += rtn;
  120. nll += rtn;
  121. }
  122. if (nlp->nlmsg_type == NLMSG_OVERRUN) {
  123. fprintf(stderr, "NLMSG_OVERRUN: Data lost\n");
  124. p = buf;
  125. nll = 0;
  126. continue;
  127. }
  128. nll += rtn;
  129. _processMessage(nlp, nll);
  130. p = buf;
  131. nll = 0;
  132. }
  133. else {
  134. Thread::sleep(100);
  135. continue;
  136. }
  137. }
  138. }
  139. void LinuxNetLink::_processMessage(struct nlmsghdr *nlp, int nll)
  140. {
  141. for(; NLMSG_OK(nlp, nll); nlp=NLMSG_NEXT(nlp, nll))
  142. {
  143. switch(nlp->nlmsg_type)
  144. {
  145. case RTM_NEWLINK:
  146. _linkAdded(nlp);
  147. break;
  148. case RTM_DELLINK:
  149. _linkDeleted(nlp);
  150. break;
  151. case RTM_NEWADDR:
  152. _ipAddressAdded(nlp);
  153. break;
  154. case RTM_DELADDR:
  155. _ipAddressDeleted(nlp);
  156. break;
  157. case RTM_NEWROUTE:
  158. _routeAdded(nlp);
  159. break;
  160. case RTM_DELROUTE:
  161. _routeDeleted(nlp);
  162. break;
  163. default:
  164. fprintf(stderr, "ignore msgtype %d...\n", nlp->nlmsg_type);
  165. }
  166. }
  167. }
  168. void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
  169. {
  170. struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
  171. struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
  172. int ifal = IFA_PAYLOAD(nlp);
  173. char addr[40] = {0};
  174. char local[40] = {0};
  175. char label[40] = {0};
  176. char bcast[40] = {0};
  177. for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal))
  178. {
  179. switch(rtap->rta_type) {
  180. case IFA_ADDRESS:
  181. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
  182. break;
  183. case IFA_LOCAL:
  184. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), local, 40);
  185. break;
  186. case IFA_LABEL:
  187. memcpy(label, RTA_DATA(rtap), 40);
  188. break;
  189. case IFA_BROADCAST:
  190. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), bcast, 40);
  191. break;
  192. }
  193. }
  194. fprintf(stderr, "Added IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
  195. }
  196. void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
  197. {
  198. struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
  199. struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
  200. int ifal = IFA_PAYLOAD(nlp);
  201. char addr[40] = {0};
  202. char local[40] = {0};
  203. char label[40] = {0};
  204. char bcast[40] = {0};
  205. for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal))
  206. {
  207. switch(rtap->rta_type) {
  208. case IFA_ADDRESS:
  209. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
  210. break;
  211. case IFA_LOCAL:
  212. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), local, 40);
  213. break;
  214. case IFA_LABEL:
  215. memcpy(label, RTA_DATA(rtap), 40);
  216. break;
  217. case IFA_BROADCAST:
  218. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), bcast, 40);
  219. break;
  220. }
  221. }
  222. fprintf(stderr, "Removed IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
  223. }
  224. void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
  225. {
  226. char dsts[40] = {0};
  227. char gws[40] = {0};
  228. char ifs[16] = {0};
  229. char ms[24] = {0};
  230. struct rtmsg *rtp = (struct rtmsg *) NLMSG_DATA(nlp);
  231. struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
  232. int rtl = RTM_PAYLOAD(nlp);
  233. for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
  234. {
  235. switch(rtap->rta_type)
  236. {
  237. case RTA_DST:
  238. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
  239. break;
  240. case RTA_GATEWAY:
  241. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
  242. break;
  243. case RTA_OIF:
  244. sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
  245. break;
  246. }
  247. }
  248. sprintf(ms, "%d", rtp->rtm_dst_len);
  249. fprintf(stderr, "Route Added: dst %s/%s gw %s if %s\n", dsts, ms, gws, ifs);
  250. }
  251. void LinuxNetLink::_routeDeleted(struct nlmsghdr *nlp)
  252. {
  253. char dsts[40] = {0};
  254. char gws[40] = {0};
  255. char ifs[16] = {0};
  256. char ms[24] = {0};
  257. struct rtmsg *rtp = (struct rtmsg *) NLMSG_DATA(nlp);
  258. struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
  259. int rtl = RTM_PAYLOAD(nlp);
  260. for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
  261. {
  262. switch(rtap->rta_type)
  263. {
  264. case RTA_DST:
  265. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
  266. break;
  267. case RTA_GATEWAY:
  268. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
  269. break;
  270. case RTA_OIF:
  271. sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
  272. break;
  273. }
  274. }
  275. sprintf(ms, "%d", rtp->rtm_dst_len);
  276. fprintf(stderr, "Route Deleted: dst %s/%s gw %s if %s\n", dsts, ms, gws, ifs);
  277. }
  278. void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
  279. {
  280. char mac[18] = {0};
  281. char mac_bin[6] = {0};
  282. unsigned int mtu = 0;
  283. char ifname[IFNAMSIZ] = {0};
  284. struct ifinfomsg *ifip = (struct ifinfomsg *)NLMSG_DATA(nlp);
  285. struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
  286. int ifil = RTM_PAYLOAD(nlp);
  287. const char *ptr;
  288. unsigned char *ptr2;
  289. for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
  290. {
  291. switch(rtap->rta_type) {
  292. case IFLA_ADDRESS:
  293. ptr2 = (unsigned char*)RTA_DATA(rtap);
  294. snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
  295. ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
  296. memcpy(mac_bin, ptr, 6);
  297. break;
  298. case IFLA_IFNAME:
  299. ptr = (const char*)RTA_DATA(rtap);
  300. memcpy(ifname, ptr, strlen(ptr));
  301. break;
  302. case IFLA_MTU:
  303. memcpy(&mtu, RTA_DATA(rtap), sizeof(unsigned int));
  304. break;
  305. }
  306. }
  307. struct iface_entry &entry = _interfaces[ifip->ifi_index];
  308. entry.index = ifip->ifi_index;
  309. memcpy(entry.ifacename, ifname, sizeof(ifname));
  310. memcpy(entry.mac, mac, sizeof(mac));
  311. memcpy(entry.mac_bin, mac_bin, 6);
  312. entry.mtu = mtu;
  313. fprintf(stderr, "Link Added: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
  314. }
  315. void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
  316. {
  317. char mac[18] = {0};
  318. unsigned int mtu = 0;
  319. char ifname[40] = {0};
  320. struct ifinfomsg *ifip = (struct ifinfomsg *)NLMSG_DATA(nlp);
  321. struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
  322. int ifil = RTM_PAYLOAD(nlp);
  323. const char *ptr;
  324. unsigned char *ptr2;
  325. for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
  326. {
  327. switch(rtap->rta_type) {
  328. case IFLA_ADDRESS:
  329. ptr2 = (unsigned char*)RTA_DATA(rtap);
  330. snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
  331. ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
  332. break;
  333. case IFLA_IFNAME:
  334. ptr = (const char*)RTA_DATA(rtap);
  335. memcpy(ifname, ptr, strlen(ptr));
  336. break;
  337. case IFLA_MTU:
  338. memcpy(&mtu, RTA_DATA(rtap), sizeof(unsigned int));
  339. break;
  340. }
  341. }
  342. fprintf(stderr, "Link Deleted: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
  343. if(_interfaces.contains(ifip->ifi_index)) {
  344. _interfaces.erase(ifip->ifi_index);
  345. }
  346. }
  347. void LinuxNetLink::_requestIPv4Routes()
  348. {
  349. struct nl_route_req req;
  350. bzero(&req, sizeof(req));
  351. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  352. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  353. req.nl.nlmsg_type = RTM_GETROUTE;
  354. req.nl.nlmsg_pid = 0;
  355. req.nl.nlmsg_seq = ++_seq;
  356. req.rt.rtm_family = AF_INET;
  357. req.rt.rtm_table = RT_TABLE_MAIN;
  358. struct sockaddr_nl pa;
  359. bzero(&pa, sizeof(pa));
  360. pa.nl_family = AF_NETLINK;
  361. struct msghdr msg;
  362. bzero(&msg, sizeof(msg));
  363. msg.msg_name = (void*)&pa;
  364. msg.msg_namelen = sizeof(pa);
  365. struct iovec iov;
  366. bzero(&iov, sizeof(iov));
  367. iov.iov_base = (void*)&req.nl;
  368. iov.iov_len = req.nl.nlmsg_len;
  369. msg.msg_iov = &iov;
  370. msg.msg_iovlen = 1;
  371. sendmsg(_fd, &msg, 0);
  372. }
  373. void LinuxNetLink::_requestIPv6Routes()
  374. {
  375. struct nl_route_req req;
  376. bzero(&req, sizeof(req));
  377. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  378. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  379. req.nl.nlmsg_type = RTM_GETROUTE;
  380. req.nl.nlmsg_pid = 0;
  381. req.nl.nlmsg_seq = ++_seq;
  382. req.rt.rtm_family = AF_INET6;
  383. req.rt.rtm_table = RT_TABLE_MAIN;
  384. struct sockaddr_nl pa;
  385. bzero(&pa, sizeof(pa));
  386. pa.nl_family = AF_NETLINK;
  387. struct msghdr msg;
  388. bzero(&msg, sizeof(msg));
  389. msg.msg_name = (void*)&pa;
  390. msg.msg_namelen = sizeof(pa);
  391. struct iovec iov;
  392. bzero(&iov, sizeof(iov));
  393. iov.iov_base = (void*)&req.nl;
  394. iov.iov_len = req.nl.nlmsg_len;
  395. msg.msg_iov = &iov;
  396. msg.msg_iovlen = 1;
  397. sendmsg(_fd, &msg, 0);
  398. }
  399. void LinuxNetLink::_requestInterfaceList()
  400. {
  401. struct nl_if_req req;
  402. bzero(&req, sizeof(req));
  403. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  404. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  405. req.nl.nlmsg_type = RTM_GETLINK;
  406. req.nl.nlmsg_pid = 0;
  407. req.nl.nlmsg_seq = ++_seq;
  408. req.ifa.ifi_family = AF_UNSPEC;
  409. struct sockaddr_nl pa;
  410. bzero(&pa, sizeof(pa));
  411. pa.nl_family = AF_NETLINK;
  412. struct msghdr msg;
  413. bzero(&msg, sizeof(msg));
  414. msg.msg_name = (void*)&pa;
  415. msg.msg_namelen = sizeof(pa);
  416. struct iovec iov;
  417. bzero(&iov, sizeof(iov));
  418. iov.iov_base = (void*)&req.nl;
  419. iov.iov_len = req.nl.nlmsg_len;
  420. msg.msg_iov = &iov;
  421. msg.msg_iovlen = 1;
  422. sendmsg(_fd, &msg, 0);
  423. }
  424. void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, const char *ifaceName)
  425. {
  426. int rtl = sizeof(struct rtmsg);
  427. struct nl_route_req req;
  428. bzero(&req, sizeof(req));
  429. struct rtattr *rtap = (struct rtattr *)req.buf;
  430. rtap->rta_type = RTA_DST;
  431. if (target.isV4()) {
  432. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in_addr);
  433. memcpy((void*)((char*)rtap+sizeof(struct rtattr)), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
  434. } else {
  435. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in6_addr);
  436. memcpy((void*)((char*)rtap+sizeof(struct rtattr)), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
  437. }
  438. rtl += rtap->rta_len;
  439. int interface_index = -1;
  440. if (ifaceName != NULL) {
  441. Hashtable<int, iface_entry>::Iterator iter(_interfaces);
  442. int *k = NULL;
  443. iface_entry *v = NULL;
  444. while(iter.next(k, v)) {
  445. if(strcmp(ifaceName, v->ifacename) == 0) {
  446. interface_index = v->index;
  447. break;
  448. }
  449. }
  450. if (interface_index != -1) {
  451. rtap = (struct rtattr *) (((char*)rtap) + rtap->rta_len);
  452. rtap->rta_type = RTA_OIF;
  453. rtap->rta_len = sizeof(struct rtattr)+sizeof(int);
  454. memcpy(((char*)rtap)+sizeof(rtattr), &interface_index, sizeof(int));
  455. rtl += rtap->rta_len;
  456. }
  457. }
  458. if(via) {
  459. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  460. rtap->rta_type = RTA_GATEWAY;
  461. if(via.isV4()) {
  462. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in_addr);
  463. memcpy((char*)rtap+sizeof(struct rtattr), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
  464. } else {
  465. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in6_addr);
  466. memcpy((char*)rtap+sizeof(struct rtattr), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
  467. }
  468. rtl += rtap->rta_len;
  469. }
  470. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  471. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
  472. req.nl.nlmsg_type = RTM_NEWROUTE;
  473. req.nl.nlmsg_pid = 0;
  474. req.nl.nlmsg_seq = ++_seq;
  475. req.rt.rtm_family = target.ss_family;
  476. req.rt.rtm_table = RT_TABLE_MAIN;
  477. req.rt.rtm_protocol = RTPROT_STATIC;
  478. req.rt.rtm_scope = RT_SCOPE_UNIVERSE;
  479. req.rt.rtm_type = RTN_UNICAST;
  480. req.rt.rtm_dst_len = target.netmaskBits();
  481. struct sockaddr_nl pa;
  482. bzero(&pa, sizeof(pa));
  483. pa.nl_family = AF_NETLINK;
  484. struct msghdr msg;
  485. bzero(&msg, sizeof(msg));
  486. msg.msg_name = (void*)&pa;
  487. msg.msg_namelen = sizeof(pa);
  488. struct iovec iov;
  489. bzero(&iov, sizeof(iov));
  490. iov.iov_base = (void*)&req.nl;
  491. iov.iov_len = req.nl.nlmsg_len;
  492. msg.msg_iov = &iov;
  493. msg.msg_iovlen = 1;
  494. sendmsg(_fd, &msg, 0);
  495. }
  496. void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, const char *ifaceName)
  497. {
  498. int rtl = sizeof(struct rtmsg);
  499. struct nl_route_req req;
  500. bzero(&req, sizeof(req));
  501. struct rtattr *rtap = (struct rtattr *)req.buf;
  502. rtap->rta_type = RTA_DST;
  503. if (target.isV4()) {
  504. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in_addr);
  505. memcpy((void*)((char*)rtap+sizeof(struct rtattr)), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
  506. } else {
  507. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in6_addr);
  508. memcpy((void*)((char*)rtap+sizeof(struct rtattr)), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
  509. }
  510. rtl += rtap->rta_len;
  511. int interface_index = -1;
  512. if (ifaceName != NULL) {
  513. Hashtable<int, iface_entry>::Iterator iter(_interfaces);
  514. int *k = NULL;
  515. iface_entry *v = NULL;
  516. while(iter.next(k, v)) {
  517. if(strcmp(ifaceName, v->ifacename) == 0) {
  518. interface_index = v->index;
  519. break;
  520. }
  521. }
  522. if (interface_index != -1) {
  523. rtap = (struct rtattr *) (((char*)rtap) + rtap->rta_len);
  524. rtap->rta_type = RTA_OIF;
  525. rtap->rta_len = sizeof(struct rtattr)+sizeof(int);
  526. memcpy(((char*)rtap)+sizeof(rtattr), &interface_index, sizeof(int));
  527. rtl += rtap->rta_len;
  528. }
  529. }
  530. if(via) {
  531. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  532. rtap->rta_type = RTA_GATEWAY;
  533. if(via.isV4()) {
  534. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in_addr);
  535. memcpy((char*)rtap+sizeof(struct rtattr), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
  536. } else {
  537. rtap->rta_len = sizeof(struct rtattr)+sizeof(struct in6_addr);
  538. memcpy((char*)rtap+sizeof(struct rtattr), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
  539. }
  540. rtl += rtap->rta_len;
  541. }
  542. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  543. req.nl.nlmsg_flags = NLM_F_REQUEST;
  544. req.nl.nlmsg_type = RTM_DELROUTE;
  545. req.nl.nlmsg_pid = 0;
  546. req.nl.nlmsg_seq = ++_seq;
  547. req.rt.rtm_family = target.ss_family;
  548. req.rt.rtm_table = RT_TABLE_MAIN;
  549. req.rt.rtm_protocol = RTPROT_STATIC;
  550. req.rt.rtm_scope = RT_SCOPE_UNIVERSE;
  551. req.rt.rtm_type = RTN_UNICAST;
  552. req.rt.rtm_dst_len = target.netmaskBits();
  553. struct sockaddr_nl pa;
  554. bzero(&pa, sizeof(pa));
  555. pa.nl_family = AF_NETLINK;
  556. struct msghdr msg;
  557. bzero(&msg, sizeof(msg));
  558. msg.msg_name = (void*)&pa;
  559. msg.msg_namelen = sizeof(pa);
  560. struct iovec iov;
  561. bzero(&iov, sizeof(iov));
  562. iov.iov_base = (void*)&req.nl;
  563. iov.iov_len = req.nl.nlmsg_len;
  564. msg.msg_iov = &iov;
  565. msg.msg_iovlen = 1;
  566. sendmsg(_fd, &msg, 0);
  567. }
  568. // void LinuxNetLink::addInterface(const char *iface, unsigned int mtu, const MAC &mac)
  569. // {
  570. // int rtl = sizeof(struct ifinfomsg);
  571. // struct nl_if_req req;
  572. // bzero(&req, sizeof(nl_if_req));
  573. // struct rtattr *rtap = (struct rtattr *)req.buf;
  574. // rtap->rta_type = IFLA_IFNAME;
  575. // rtap->rta_len = sizeof(struct rtattr)+strlen(iface)+1;
  576. // rtl += rtap->rta_len;
  577. // rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  578. // rtap->rta_type = IFLA_MTU;
  579. // rtap->rta_len = sizeof(struct rtattr)+sizeof(unsigned int);
  580. // rtl += rtap->rta_len;
  581. // rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  582. // rtap->rta_type = IFLA_ADDRESS;
  583. // rtap->rta_len = sizeof(struct rtattr)+6;
  584. // mac.copyTo(((char*)rtap)+sizeof(struct rtattr), 6);
  585. // rtl += rtap->rta_len;
  586. // IFLA_LINKINFO;
  587. // req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  588. // req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
  589. // req.nl.nlmsg_type = RTM_NEWLINK;
  590. // req.nl.nlmsg_pid = 0;
  591. // req.nl.nlmsg_seq = ++_seq;
  592. // req.ifa.ifi_family = AF_UNSPEC;
  593. // req.ifa.ifi_type = 0; // TODO figure this one out
  594. // req.ifa.ifi_index = 0;
  595. // req.ifa.ifi_flags = IFF_UP;
  596. // struct sockaddr_nl pa;
  597. // bzero(&pa, sizeof(pa));
  598. // pa.nl_family = AF_NETLINK;
  599. // struct msghdr msg;
  600. // bzero(&msg, sizeof(msg));
  601. // msg.msg_name = (void*)&pa;
  602. // msg.msg_namelen = sizeof(pa);
  603. // struct iovec iov;
  604. // iov.iov_base = (void*)&req.nl;
  605. // iov.iov_len = req.nl.nlmsg_len;
  606. // msg.msg_iov = &iov;
  607. // msg.msg_iovlen = 1;
  608. // sendmsg(_fd, &msg, 0);
  609. // }
  610. // void LinuxNetLink::removeInterface(const char *iface)
  611. // {
  612. // }
  613. void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
  614. {
  615. }
  616. void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
  617. {
  618. }
  619. RouteList LinuxNetLink::getIPV4Routes() const
  620. {
  621. return _routes_ipv4;
  622. }
  623. RouteList LinuxNetLink::getIPV6Routes() const
  624. {
  625. return _routes_ipv6;
  626. }
  627. } // namespace ZeroTier