LinuxNetLink.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  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. , _rv4_m()
  50. , _routes_ipv6()
  51. , _rv6_m()
  52. , _seq(0)
  53. , _interfaces()
  54. , _if_m()
  55. , _fd(socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE))
  56. , _la({0})
  57. {
  58. // set socket timeout to 1 sec so we're not permablocking recv() calls
  59. _setSocketTimeout(_fd, 1);
  60. int yes=1;
  61. setsockopt(_fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  62. _la.nl_family = AF_NETLINK;
  63. _la.nl_pid = getpid()+1;
  64. _la.nl_groups = RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR|RTMGRP_IPV4_ROUTE|RTMGRP_IPV6_ROUTE|RTMGRP_NOTIFY;
  65. if (bind(_fd, (struct sockaddr*)&_la, sizeof(_la))) {
  66. fprintf(stderr, "Error connecting to RTNETLINK: %s\n", strerror(errno));
  67. ::exit(1);
  68. }
  69. fprintf(stderr, "Requesting IPV4 Routes\n");
  70. _requestIPv4Routes();
  71. fprintf(stderr, "Requesting IPV6 Routes\n");
  72. _requestIPv6Routes();
  73. fprintf(stderr, "Requesting Interface List\n");
  74. _requestInterfaceList();
  75. _running = true;
  76. _t = Thread::start(this);
  77. }
  78. LinuxNetLink::~LinuxNetLink()
  79. {
  80. _running = false;
  81. Thread::join(_t);
  82. ::close(_fd);
  83. }
  84. void LinuxNetLink::_setSocketTimeout(int fd, int seconds)
  85. {
  86. struct timeval tv;
  87. tv.tv_sec = seconds;
  88. tv.tv_usec = 0;
  89. if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) != 0) {
  90. #ifdef ZT_TRACE
  91. fprintf(stderr, "setsockopt failed: %s\n", strerror(errno));
  92. #endif
  93. }
  94. }
  95. int LinuxNetLink::_doRecv(int fd)
  96. {
  97. char buf[8192];
  98. char *p = NULL;
  99. struct nlmsghdr *nlp;
  100. int nll = 0;
  101. int rtn = 0;
  102. p = buf;
  103. while(true) {
  104. rtn = recv(fd, p, sizeof(buf) - nll, 0);
  105. if (rtn > 0) {
  106. nlp = (struct nlmsghdr *)p;
  107. if(nlp->nlmsg_type == NLMSG_ERROR && (nlp->nlmsg_flags & NLM_F_ACK) != NLM_F_ACK) {
  108. struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(nlp);
  109. if (err->error != 0) {
  110. #ifdef ZT_TRACE
  111. fprintf(stderr, "rtnetlink error: %s\n", strerror(-(err->error)));
  112. #endif
  113. }
  114. p = buf;
  115. nll = 0;
  116. break;
  117. }
  118. if (nlp->nlmsg_type == NLMSG_NOOP) {
  119. break;
  120. }
  121. if( (nlp->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI || (nlp->nlmsg_type == NLMSG_DONE))
  122. {
  123. if (nlp->nlmsg_type == NLMSG_DONE) {
  124. _processMessage(nlp, nll);
  125. p = buf;
  126. nll = 0;
  127. break;
  128. }
  129. p += rtn;
  130. nll += rtn;
  131. }
  132. if (nlp->nlmsg_type == NLMSG_OVERRUN) {
  133. #ifdef ZT_TRACE
  134. fprintf(stderr, "NLMSG_OVERRUN: Data lost\n");
  135. #endif
  136. p = buf;
  137. nll = 0;
  138. break;
  139. }
  140. nll += rtn;
  141. _processMessage(nlp, nll);
  142. p = buf;
  143. nll = 0;
  144. break;
  145. } else {
  146. break;
  147. }
  148. }
  149. return rtn;
  150. }
  151. void LinuxNetLink::threadMain() throw()
  152. {
  153. int rtn = 0;
  154. while(_running) {
  155. rtn = _doRecv(_fd);
  156. if (rtn <= 0) {
  157. Thread::sleep(100);
  158. continue;
  159. }
  160. }
  161. }
  162. void LinuxNetLink::_processMessage(struct nlmsghdr *nlp, int nll)
  163. {
  164. for(; NLMSG_OK(nlp, nll); nlp=NLMSG_NEXT(nlp, nll))
  165. {
  166. switch(nlp->nlmsg_type)
  167. {
  168. case RTM_NEWLINK:
  169. _linkAdded(nlp);
  170. break;
  171. case RTM_DELLINK:
  172. _linkDeleted(nlp);
  173. break;
  174. case RTM_NEWADDR:
  175. _ipAddressAdded(nlp);
  176. break;
  177. case RTM_DELADDR:
  178. _ipAddressDeleted(nlp);
  179. break;
  180. case RTM_NEWROUTE:
  181. _routeAdded(nlp);
  182. break;
  183. case RTM_DELROUTE:
  184. _routeDeleted(nlp);
  185. break;
  186. default:
  187. break;
  188. }
  189. }
  190. }
  191. void LinuxNetLink::_ipAddressAdded(struct nlmsghdr *nlp)
  192. {
  193. struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
  194. struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
  195. int ifal = IFA_PAYLOAD(nlp);
  196. char addr[40] = {0};
  197. char local[40] = {0};
  198. char label[40] = {0};
  199. char bcast[40] = {0};
  200. for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal))
  201. {
  202. switch(rtap->rta_type) {
  203. case IFA_ADDRESS:
  204. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
  205. break;
  206. case IFA_LOCAL:
  207. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), local, 40);
  208. break;
  209. case IFA_LABEL:
  210. memcpy(label, RTA_DATA(rtap), 40);
  211. break;
  212. case IFA_BROADCAST:
  213. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), bcast, 40);
  214. break;
  215. }
  216. }
  217. #ifdef ZT_TRACE
  218. fprintf(stderr,"Added IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
  219. #endif
  220. }
  221. void LinuxNetLink::_ipAddressDeleted(struct nlmsghdr *nlp)
  222. {
  223. struct ifaddrmsg *ifap = (struct ifaddrmsg *)NLMSG_DATA(nlp);
  224. struct rtattr *rtap = (struct rtattr *)IFA_RTA(ifap);
  225. int ifal = IFA_PAYLOAD(nlp);
  226. char addr[40] = {0};
  227. char local[40] = {0};
  228. char label[40] = {0};
  229. char bcast[40] = {0};
  230. for(;RTA_OK(rtap, ifal); rtap=RTA_NEXT(rtap,ifal))
  231. {
  232. switch(rtap->rta_type) {
  233. case IFA_ADDRESS:
  234. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), addr, 40);
  235. break;
  236. case IFA_LOCAL:
  237. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), local, 40);
  238. break;
  239. case IFA_LABEL:
  240. memcpy(label, RTA_DATA(rtap), 40);
  241. break;
  242. case IFA_BROADCAST:
  243. inet_ntop(ifap->ifa_family, RTA_DATA(rtap), bcast, 40);
  244. break;
  245. }
  246. }
  247. #ifdef ZT_TRACE
  248. fprintf(stderr, "Removed IP Address %s local: %s label: %s broadcast: %s\n", addr, local, label, bcast);
  249. #endif
  250. }
  251. void LinuxNetLink::_routeAdded(struct nlmsghdr *nlp)
  252. {
  253. char dsts[40] = {0};
  254. char gws[40] = {0};
  255. char srcs[40] = {0};
  256. char ifs[16] = {0};
  257. char ms[24] = {0};
  258. struct rtmsg *rtp = (struct rtmsg *) NLMSG_DATA(nlp);
  259. struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
  260. int rtl = RTM_PAYLOAD(nlp);
  261. for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
  262. {
  263. switch(rtap->rta_type)
  264. {
  265. case RTA_DST:
  266. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
  267. break;
  268. case RTA_SRC:
  269. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, rtp->rtm_family == AF_INET ? 24: 40);
  270. break;
  271. case RTA_GATEWAY:
  272. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
  273. break;
  274. case RTA_OIF:
  275. sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
  276. break;
  277. }
  278. }
  279. sprintf(ms, "%d", rtp->rtm_dst_len);
  280. #ifdef ZT_TRACE
  281. fprintf(stderr, "Route Added: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
  282. #endif
  283. }
  284. void LinuxNetLink::_routeDeleted(struct nlmsghdr *nlp)
  285. {
  286. char dsts[40] = {0};
  287. char gws[40] = {0};
  288. char srcs[40] = {0};
  289. char ifs[16] = {0};
  290. char ms[24] = {0};
  291. struct rtmsg *rtp = (struct rtmsg *) NLMSG_DATA(nlp);
  292. struct rtattr *rtap = (struct rtattr *)RTM_RTA(rtp);
  293. int rtl = RTM_PAYLOAD(nlp);
  294. for(;RTA_OK(rtap, rtl); rtap=RTA_NEXT(rtap, rtl))
  295. {
  296. switch(rtap->rta_type)
  297. {
  298. case RTA_DST:
  299. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), dsts, rtp->rtm_family == AF_INET ? 24 : 40);
  300. break;
  301. case RTA_SRC:
  302. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), srcs, rtp->rtm_family == AF_INET ? 24 : 40);
  303. break;
  304. case RTA_GATEWAY:
  305. inet_ntop(rtp->rtm_family, RTA_DATA(rtap), gws, rtp->rtm_family == AF_INET ? 24 : 40);
  306. break;
  307. case RTA_OIF:
  308. sprintf(ifs, "%d", *((int*)RTA_DATA(rtap)));
  309. break;
  310. }
  311. }
  312. sprintf(ms, "%d", rtp->rtm_dst_len);
  313. #ifdef ZT_TRACE
  314. fprintf(stderr, "Route Deleted: dst %s/%s gw %s src %s if %s\n", dsts, ms, gws, srcs, ifs);
  315. #endif
  316. }
  317. void LinuxNetLink::_linkAdded(struct nlmsghdr *nlp)
  318. {
  319. char mac[18] = {0};
  320. char mac_bin[6] = {0};
  321. unsigned int mtu = 0;
  322. char ifname[IFNAMSIZ] = {0};
  323. struct ifinfomsg *ifip = (struct ifinfomsg *)NLMSG_DATA(nlp);
  324. struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
  325. int ifil = RTM_PAYLOAD(nlp);
  326. const char *ptr;
  327. unsigned char *ptr2;
  328. for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
  329. {
  330. switch(rtap->rta_type) {
  331. case IFLA_ADDRESS:
  332. ptr2 = (unsigned char*)RTA_DATA(rtap);
  333. snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
  334. ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
  335. memcpy(mac_bin, ptr, 6);
  336. break;
  337. case IFLA_IFNAME:
  338. ptr = (const char*)RTA_DATA(rtap);
  339. memcpy(ifname, ptr, strlen(ptr));
  340. break;
  341. case IFLA_MTU:
  342. memcpy(&mtu, RTA_DATA(rtap), sizeof(unsigned int));
  343. break;
  344. }
  345. }
  346. {
  347. Mutex::Lock l(_if_m);
  348. struct iface_entry &entry = _interfaces[ifip->ifi_index];
  349. entry.index = ifip->ifi_index;
  350. memcpy(entry.ifacename, ifname, sizeof(ifname));
  351. memcpy(entry.mac, mac, sizeof(mac));
  352. memcpy(entry.mac_bin, mac_bin, 6);
  353. entry.mtu = mtu;
  354. }
  355. #ifdef ZT_TRACE
  356. fprintf(stderr, "Link Added: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
  357. #endif
  358. }
  359. void LinuxNetLink::_linkDeleted(struct nlmsghdr *nlp)
  360. {
  361. char mac[18] = {0};
  362. unsigned int mtu = 0;
  363. char ifname[40] = {0};
  364. struct ifinfomsg *ifip = (struct ifinfomsg *)NLMSG_DATA(nlp);
  365. struct rtattr *rtap = (struct rtattr *)IFLA_RTA(ifip);
  366. int ifil = RTM_PAYLOAD(nlp);
  367. const char *ptr;
  368. unsigned char *ptr2;
  369. for(;RTA_OK(rtap, ifil);rtap=RTA_NEXT(rtap, ifil))
  370. {
  371. switch(rtap->rta_type) {
  372. case IFLA_ADDRESS:
  373. ptr2 = (unsigned char*)RTA_DATA(rtap);
  374. snprintf(mac, 20, "%02x:%02x:%02x:%02x:%02x:%02x",
  375. ptr2[0], ptr2[1], ptr2[2], ptr2[3], ptr2[4], ptr2[5]);
  376. break;
  377. case IFLA_IFNAME:
  378. ptr = (const char*)RTA_DATA(rtap);
  379. memcpy(ifname, ptr, strlen(ptr));
  380. break;
  381. case IFLA_MTU:
  382. memcpy(&mtu, RTA_DATA(rtap), sizeof(unsigned int));
  383. break;
  384. }
  385. }
  386. #ifdef ZT_TRACE
  387. fprintf(stderr, "Link Deleted: %s mac: %s, mtu: %d\n", ifname, mac, mtu);
  388. #endif
  389. {
  390. Mutex::Lock l(_if_m);
  391. if(_interfaces.contains(ifip->ifi_index)) {
  392. _interfaces.erase(ifip->ifi_index);
  393. }
  394. }
  395. }
  396. void LinuxNetLink::_requestIPv4Routes()
  397. {
  398. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  399. int yes=1;
  400. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  401. if (fd == -1) {
  402. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  403. return;
  404. }
  405. _setSocketTimeout(fd);
  406. struct sockaddr_nl la;
  407. la.nl_family = AF_NETLINK;
  408. la.nl_pid = getpid();
  409. la.nl_groups = RTMGRP_IPV4_ROUTE;
  410. if(bind(fd, (struct sockaddr*)&la, sizeof(la))) {
  411. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  412. return;
  413. }
  414. struct nl_route_req req;
  415. bzero(&req, sizeof(req));
  416. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  417. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  418. req.nl.nlmsg_type = RTM_GETROUTE;
  419. req.nl.nlmsg_pid = 0;
  420. req.nl.nlmsg_seq = ++_seq;
  421. req.rt.rtm_family = AF_INET;
  422. req.rt.rtm_table = RT_TABLE_MAIN;
  423. struct sockaddr_nl pa;
  424. bzero(&pa, sizeof(pa));
  425. pa.nl_family = AF_NETLINK;
  426. struct msghdr msg;
  427. bzero(&msg, sizeof(msg));
  428. msg.msg_name = (void*)&pa;
  429. msg.msg_namelen = sizeof(pa);
  430. struct iovec iov;
  431. bzero(&iov, sizeof(iov));
  432. iov.iov_base = (void*)&req.nl;
  433. iov.iov_len = req.nl.nlmsg_len;
  434. msg.msg_iov = &iov;
  435. msg.msg_iovlen = 1;
  436. sendmsg(fd, &msg, 0);
  437. _doRecv(fd);
  438. close(fd);
  439. }
  440. void LinuxNetLink::_requestIPv6Routes()
  441. {
  442. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  443. int yes=1;
  444. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  445. if (fd == -1) {
  446. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  447. return;
  448. }
  449. _setSocketTimeout(fd);
  450. struct sockaddr_nl la;
  451. la.nl_family = AF_NETLINK;
  452. la.nl_pid = getpid();
  453. la.nl_groups = RTMGRP_IPV6_ROUTE;
  454. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  455. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  456. return;
  457. }
  458. struct nl_route_req req;
  459. bzero(&req, sizeof(req));
  460. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
  461. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  462. req.nl.nlmsg_type = RTM_GETROUTE;
  463. req.nl.nlmsg_pid = 0;
  464. req.nl.nlmsg_seq = ++_seq;
  465. req.rt.rtm_family = AF_INET6;
  466. req.rt.rtm_table = RT_TABLE_MAIN;
  467. struct sockaddr_nl pa;
  468. bzero(&pa, sizeof(pa));
  469. pa.nl_family = AF_NETLINK;
  470. struct msghdr msg;
  471. bzero(&msg, sizeof(msg));
  472. msg.msg_name = (void*)&pa;
  473. msg.msg_namelen = sizeof(pa);
  474. struct iovec iov;
  475. bzero(&iov, sizeof(iov));
  476. iov.iov_base = (void*)&req.nl;
  477. iov.iov_len = req.nl.nlmsg_len;
  478. msg.msg_iov = &iov;
  479. msg.msg_iovlen = 1;
  480. sendmsg(fd, &msg, 0);
  481. _doRecv(fd);
  482. close(fd);
  483. }
  484. void LinuxNetLink::_requestInterfaceList()
  485. {
  486. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  487. int yes=1;
  488. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  489. if (fd == -1) {
  490. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  491. return;
  492. }
  493. _setSocketTimeout(fd);
  494. struct sockaddr_nl la;
  495. la.nl_family = AF_NETLINK;
  496. la.nl_pid = getpid();
  497. la.nl_groups = RTMGRP_LINK;
  498. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  499. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  500. return;
  501. }
  502. struct nl_if_req req;
  503. bzero(&req, sizeof(req));
  504. req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
  505. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
  506. req.nl.nlmsg_type = RTM_GETLINK;
  507. req.nl.nlmsg_pid = 0;
  508. req.nl.nlmsg_seq = ++_seq;
  509. req.ifa.ifi_family = AF_UNSPEC;
  510. struct sockaddr_nl pa;
  511. bzero(&pa, sizeof(pa));
  512. pa.nl_family = AF_NETLINK;
  513. struct msghdr msg;
  514. bzero(&msg, sizeof(msg));
  515. msg.msg_name = (void*)&pa;
  516. msg.msg_namelen = sizeof(pa);
  517. struct iovec iov;
  518. bzero(&iov, sizeof(iov));
  519. iov.iov_base = (void*)&req.nl;
  520. iov.iov_len = req.nl.nlmsg_len;
  521. msg.msg_iov = &iov;
  522. msg.msg_iovlen = 1;
  523. sendmsg(fd, &msg, 0);
  524. _doRecv(fd);
  525. close(fd);
  526. }
  527. void LinuxNetLink::addRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName)
  528. {
  529. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  530. int yes=1;
  531. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  532. if (fd == -1) {
  533. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  534. return;
  535. }
  536. _setSocketTimeout(fd);
  537. struct sockaddr_nl la;
  538. bzero(&la, sizeof(la));
  539. la.nl_family = AF_NETLINK;
  540. la.nl_pid = getpid();
  541. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  542. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  543. return;
  544. }
  545. #ifdef ZT_TRACE
  546. char tmp[64];
  547. char tmp2[64];
  548. char tmp3[64];
  549. fprintf(stderr, "Adding Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
  550. #endif
  551. if(!target) {
  552. #ifdef ZT_TRACE
  553. fprintf(stderr, "Uhhhh adding an empty route?!?!?");
  554. #endif
  555. return;
  556. }
  557. int rtl = sizeof(struct rtmsg);
  558. struct nl_route_req req;
  559. bzero(&req, sizeof(req));
  560. struct rtattr *rtap = (struct rtattr *)req.buf;
  561. rtap->rta_type = RTA_DST;
  562. if (target.isV4()) {
  563. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  564. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
  565. } else {
  566. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  567. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
  568. }
  569. rtl += rtap->rta_len;
  570. if(via) {
  571. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  572. rtap->rta_type = RTA_GATEWAY;
  573. if(via.isV4()) {
  574. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  575. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
  576. } else {
  577. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  578. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
  579. }
  580. rtl += rtap->rta_len;
  581. } else if (src) {
  582. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  583. rtap->rta_type = RTA_SRC;
  584. if(src.isV4()) {
  585. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  586. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr));
  587. } else {
  588. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  589. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr));
  590. }
  591. req.rt.rtm_src_len = src.netmaskBits();
  592. }
  593. if (ifaceName != NULL) {
  594. int interface_index = _indexForInterface(ifaceName);
  595. if (interface_index != -1) {
  596. rtap = (struct rtattr *) (((char*)rtap) + rtap->rta_len);
  597. rtap->rta_type = RTA_OIF;
  598. rtap->rta_len = RTA_LENGTH(sizeof(int));
  599. memcpy(RTA_DATA(rtap), &interface_index, sizeof(int));
  600. rtl += rtap->rta_len;
  601. }
  602. }
  603. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  604. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_EXCL | NLM_F_CREATE | NLM_F_ACK;
  605. req.nl.nlmsg_type = RTM_NEWROUTE;
  606. req.nl.nlmsg_pid = 0;
  607. req.nl.nlmsg_seq = ++_seq;
  608. req.rt.rtm_family = target.ss_family;
  609. req.rt.rtm_table = RT_TABLE_MAIN;
  610. req.rt.rtm_protocol = RTPROT_STATIC;
  611. req.rt.rtm_scope = RT_SCOPE_UNIVERSE;
  612. req.rt.rtm_type = RTN_UNICAST;
  613. req.rt.rtm_dst_len = target.netmaskBits();
  614. req.rt.rtm_flags = 0;
  615. struct sockaddr_nl pa;
  616. bzero(&pa, sizeof(pa));
  617. pa.nl_family = AF_NETLINK;
  618. struct msghdr msg;
  619. bzero(&msg, sizeof(msg));
  620. msg.msg_name = (void*)&pa;
  621. msg.msg_namelen = sizeof(pa);
  622. struct iovec iov;
  623. bzero(&iov, sizeof(iov));
  624. iov.iov_base = (void*)&req.nl;
  625. iov.iov_len = req.nl.nlmsg_len;
  626. msg.msg_iov = &iov;
  627. msg.msg_iovlen = 1;
  628. sendmsg(fd, &msg, 0);
  629. _doRecv(fd);
  630. close(fd);
  631. }
  632. void LinuxNetLink::delRoute(const InetAddress &target, const InetAddress &via, const InetAddress &src, const char *ifaceName)
  633. {
  634. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  635. int yes=1;
  636. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  637. if (fd == -1) {
  638. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  639. return;
  640. }
  641. _setSocketTimeout(fd);
  642. struct sockaddr_nl la;
  643. la.nl_family = AF_NETLINK;
  644. la.nl_pid = getpid();
  645. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  646. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  647. return;
  648. }
  649. #ifdef ZT_TRACE
  650. char tmp[64];
  651. char tmp2[64];
  652. char tmp3[64];
  653. fprintf(stderr, "Removing Route. target: %s via: %s src: %s iface: %s\n", target.toString(tmp), via.toString(tmp2), src.toString(tmp3), ifaceName);
  654. #endif
  655. if(!target) {
  656. #ifdef ZT_TRACE
  657. fprintf(stderr, "Uhhhh deleting an empty route?!?!?");
  658. #endif
  659. return;
  660. }
  661. int rtl = sizeof(struct rtmsg);
  662. struct nl_route_req req;
  663. bzero(&req, sizeof(req));
  664. struct rtattr *rtap = (struct rtattr *)req.buf;
  665. rtap->rta_type = RTA_DST;
  666. if (target.isV4()) {
  667. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  668. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&target)->sin_addr, sizeof(struct in_addr));
  669. } else {
  670. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  671. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&target)->sin6_addr, sizeof(struct in6_addr));
  672. }
  673. rtl += rtap->rta_len;
  674. if(via) {
  675. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  676. rtap->rta_type = RTA_GATEWAY;
  677. if(via.isV4()) {
  678. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  679. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&via)->sin_addr, sizeof(struct in_addr));
  680. } else {
  681. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  682. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&via)->sin6_addr, sizeof(struct in6_addr));
  683. }
  684. rtl += rtap->rta_len;
  685. } else if (src) {
  686. rtap = (struct rtattr *)(((char*)rtap)+rtap->rta_len);
  687. rtap->rta_type = RTA_SRC;
  688. if(src.isV4()) {
  689. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  690. memcpy(RTA_DATA(rtap), &((struct sockaddr_in*)&src)->sin_addr, sizeof(struct in_addr));
  691. } else {
  692. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  693. memcpy(RTA_DATA(rtap), &((struct sockaddr_in6*)&src)->sin6_addr, sizeof(struct in6_addr));
  694. }
  695. req.rt.rtm_src_len = src.netmaskBits();
  696. }
  697. if (ifaceName != NULL) {
  698. int interface_index = _indexForInterface(ifaceName);
  699. if (interface_index != -1) {
  700. rtap = (struct rtattr *) (((char*)rtap) + rtap->rta_len);
  701. rtap->rta_type = RTA_OIF;
  702. rtap->rta_len = RTA_LENGTH(sizeof(int));
  703. memcpy(RTA_DATA(rtap), &interface_index, sizeof(int));
  704. rtl += rtap->rta_len;
  705. }
  706. }
  707. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  708. req.nl.nlmsg_flags = NLM_F_REQUEST;
  709. req.nl.nlmsg_type = RTM_DELROUTE;
  710. req.nl.nlmsg_pid = 0;
  711. req.nl.nlmsg_seq = ++_seq;
  712. req.rt.rtm_family = target.ss_family;
  713. req.rt.rtm_table = RT_TABLE_MAIN;
  714. req.rt.rtm_protocol = RTPROT_STATIC;
  715. req.rt.rtm_scope = RT_SCOPE_UNIVERSE;
  716. req.rt.rtm_type = RTN_UNICAST;
  717. req.rt.rtm_dst_len = target.netmaskBits();
  718. req.rt.rtm_flags = 0;
  719. struct sockaddr_nl pa;
  720. bzero(&pa, sizeof(pa));
  721. pa.nl_family = AF_NETLINK;
  722. struct msghdr msg;
  723. bzero(&msg, sizeof(msg));
  724. msg.msg_name = (void*)&pa;
  725. msg.msg_namelen = sizeof(pa);
  726. struct iovec iov;
  727. bzero(&iov, sizeof(iov));
  728. iov.iov_base = (void*)&req.nl;
  729. iov.iov_len = req.nl.nlmsg_len;
  730. msg.msg_iov = &iov;
  731. msg.msg_iovlen = 1;
  732. sendmsg(fd, &msg, 0);
  733. _doRecv(fd);
  734. close(fd);
  735. }
  736. void LinuxNetLink::addAddress(const InetAddress &addr, const char *iface)
  737. {
  738. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  739. int yes=1;
  740. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  741. if (fd == -1) {
  742. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  743. return;
  744. }
  745. _setSocketTimeout(fd);
  746. struct sockaddr_nl la;
  747. la.nl_family = AF_NETLINK;
  748. la.nl_pid = getpid();
  749. if (addr.isV4()) {
  750. la.nl_groups = RTMGRP_IPV4_IFADDR;
  751. } else {
  752. la.nl_groups = RTMGRP_IPV6_IFADDR;
  753. }
  754. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  755. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  756. return;
  757. }
  758. #ifdef ZT_TRACE
  759. char tmp[128];
  760. fprintf(stderr, "Adding IP address %s to interface %s", addr.toString(tmp), iface);
  761. #endif
  762. int interface_index = _indexForInterface(iface);
  763. if (interface_index == -1) {
  764. fprintf(stderr, "Unable to find index for interface %s\n", iface);
  765. return;
  766. }
  767. int rtl = sizeof(struct ifaddrmsg);
  768. struct nl_adr_req req;
  769. bzero(&req, sizeof(struct nl_adr_req));
  770. struct rtattr *rtap = (struct rtattr *)req.buf;;
  771. if(addr.isV4()) {
  772. struct sockaddr_in *addr_v4 = (struct sockaddr_in*)&addr;
  773. rtap->rta_type = IFA_ADDRESS;
  774. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  775. memcpy(RTA_DATA(rtap), &addr_v4->sin_addr, sizeof(struct in_addr));
  776. rtl += rtap->rta_len;
  777. rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len);
  778. rtap->rta_type = IFA_LOCAL;
  779. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  780. memcpy(RTA_DATA(rtap), &addr_v4->sin_addr, sizeof(struct in_addr));
  781. rtl += rtap->rta_len;
  782. InetAddress broadcast = addr.broadcast();
  783. if(broadcast) {
  784. rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  785. struct sockaddr_in *bcast = (struct sockaddr_in*)&broadcast;
  786. rtap->rta_type = IFA_BROADCAST;
  787. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  788. memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr));
  789. rtl += rtap->rta_len;
  790. }
  791. } else { //V6
  792. rtap->rta_type = IFA_ADDRESS;
  793. struct sockaddr_in6 *addr_v6 = (struct sockaddr_in6*)&addr;
  794. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  795. memcpy(RTA_DATA(rtap), &addr_v6->sin6_addr, sizeof(struct in6_addr));
  796. rtl += rtap->rta_len;
  797. }
  798. if (iface) {
  799. rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  800. rtap->rta_type = IFA_LABEL;
  801. rtap->rta_len = RTA_LENGTH(strlen(iface));
  802. memcpy(RTA_DATA(rtap), iface, strlen(iface));
  803. rtl += rtap->rta_len;
  804. }
  805. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  806. req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
  807. req.nl.nlmsg_type = RTM_NEWADDR;
  808. req.nl.nlmsg_pid = 0;
  809. req.nl.nlmsg_seq = ++_seq;
  810. req.ifa.ifa_family = addr.ss_family;
  811. req.ifa.ifa_prefixlen = addr.port();
  812. req.ifa.ifa_flags = IFA_F_PERMANENT;
  813. req.ifa.ifa_scope = 0;
  814. req.ifa.ifa_index = interface_index;
  815. struct sockaddr_nl pa;
  816. bzero(&pa, sizeof(sockaddr_nl));
  817. pa.nl_family = AF_NETLINK;
  818. struct msghdr msg;
  819. bzero(&msg, sizeof(msg));
  820. msg.msg_name = (void*)&pa;
  821. msg.msg_namelen = sizeof(pa);
  822. struct iovec iov;
  823. iov.iov_base = (void*)&req.nl;
  824. iov.iov_len = req.nl.nlmsg_len;
  825. msg.msg_iov = &iov;
  826. msg.msg_iovlen = 1;
  827. sendmsg(fd, &msg, 0);
  828. _doRecv(fd);
  829. close(fd);
  830. }
  831. void LinuxNetLink::removeAddress(const InetAddress &addr, const char *iface)
  832. {
  833. int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  834. int yes=1;
  835. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&yes,sizeof(yes));
  836. if (fd == -1) {
  837. fprintf(stderr, "Error opening RTNETLINK socket: %s\n", strerror(errno));
  838. return;
  839. }
  840. _setSocketTimeout(fd);
  841. struct sockaddr_nl la;
  842. la.nl_family = AF_NETLINK;
  843. la.nl_pid = getpid();
  844. if (addr.isV4()) {
  845. la.nl_groups = RTMGRP_IPV4_IFADDR;
  846. } else {
  847. la.nl_groups = RTMGRP_IPV6_IFADDR;
  848. }
  849. if(bind(fd, (struct sockaddr*)&la, sizeof(struct sockaddr_nl))) {
  850. fprintf(stderr, "Error binding RTNETLINK: %s\n", strerror(errno));
  851. return;
  852. }
  853. #ifdef ZT_TRACE
  854. char tmp[128];
  855. fprintf(stderr, "Removing IP address %s from interface %s", addr.toString(tmp), iface);
  856. #endif
  857. int interface_index = _indexForInterface(iface);
  858. if (interface_index == -1) {
  859. fprintf(stderr, "Unable to find index for interface %s\n", iface);
  860. return;
  861. }
  862. int rtl = sizeof(struct ifaddrmsg);
  863. struct nl_adr_req req;
  864. bzero(&req, sizeof(struct nl_adr_req));
  865. struct rtattr *rtap = (struct rtattr *)req.buf;
  866. if(addr.isV4()) {
  867. struct sockaddr_in *addr_v4 = (struct sockaddr_in*)&addr;
  868. rtap->rta_type = IFA_ADDRESS;
  869. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  870. memcpy(RTA_DATA(rtap), &addr_v4->sin_addr, sizeof(struct in_addr));
  871. rtl += rtap->rta_len;
  872. rtap = (struct rtattr*)(((char*)rtap) + rtap->rta_len);
  873. rtap->rta_type = IFA_LOCAL;
  874. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  875. memcpy(RTA_DATA(rtap), &addr_v4->sin_addr, sizeof(struct in_addr));
  876. rtl += rtap->rta_len;
  877. InetAddress broadcast = addr.broadcast();
  878. if(broadcast) {
  879. rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  880. struct sockaddr_in *bcast = (struct sockaddr_in*)&broadcast;
  881. rtap->rta_type = IFA_BROADCAST;
  882. rtap->rta_len = RTA_LENGTH(sizeof(struct in_addr));
  883. memcpy(RTA_DATA(rtap), &bcast->sin_addr, sizeof(struct in_addr));
  884. rtl += rtap->rta_len;
  885. }
  886. } else { //V6
  887. rtap->rta_type = IFA_ADDRESS;
  888. struct sockaddr_in6 *addr_v6 = (struct sockaddr_in6*)&addr;
  889. rtap->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
  890. memcpy(RTA_DATA(rtap), &addr_v6->sin6_addr, sizeof(struct in6_addr));
  891. rtl += rtap->rta_len;
  892. }
  893. if (iface) {
  894. rtap = (struct rtattr*)(((char*)rtap)+rtap->rta_len);
  895. rtap->rta_type = IFA_LABEL;
  896. rtap->rta_len = RTA_LENGTH(strlen(iface));
  897. memcpy(RTA_DATA(rtap), iface, strlen(iface));
  898. rtl += rtap->rta_len;
  899. }
  900. req.nl.nlmsg_len = NLMSG_LENGTH(rtl);
  901. req.nl.nlmsg_flags = NLM_F_REQUEST;
  902. req.nl.nlmsg_type = RTM_DELADDR;
  903. req.nl.nlmsg_pid = 0;
  904. req.nl.nlmsg_seq = ++_seq;
  905. req.ifa.ifa_family = addr.ss_family;
  906. req.ifa.ifa_prefixlen = addr.port();
  907. req.ifa.ifa_flags = IFA_F_PERMANENT;
  908. req.ifa.ifa_scope = 0;
  909. req.ifa.ifa_index = interface_index;
  910. struct sockaddr_nl pa;
  911. bzero(&pa, sizeof(sockaddr_nl));
  912. pa.nl_family = AF_NETLINK;
  913. struct msghdr msg;
  914. bzero(&msg, sizeof(msg));
  915. msg.msg_name = (void*)&pa;
  916. msg.msg_namelen = sizeof(pa);
  917. struct iovec iov;
  918. iov.iov_base = (void*)&req.nl;
  919. iov.iov_len = req.nl.nlmsg_len;
  920. msg.msg_iov = &iov;
  921. msg.msg_iovlen = 1;
  922. sendmsg(fd, &msg, 0);
  923. _doRecv(fd);
  924. close(fd);
  925. }
  926. RouteList LinuxNetLink::getIPV4Routes() const
  927. {
  928. return _routes_ipv4;
  929. }
  930. RouteList LinuxNetLink::getIPV6Routes() const
  931. {
  932. return _routes_ipv6;
  933. }
  934. int LinuxNetLink::_indexForInterface(const char *iface)
  935. {
  936. Mutex::Lock l(_if_m);
  937. int interface_index = -1;
  938. Hashtable<int, iface_entry>::Iterator iter(_interfaces);
  939. int *k = NULL;
  940. iface_entry *v = NULL;
  941. while(iter.next(k,v)) {
  942. if(strcmp(iface, v->ifacename) == 0) {
  943. interface_index = v->index;
  944. break;
  945. }
  946. }
  947. return interface_index;
  948. }
  949. } // namespace ZeroTier