LinuxNetLink.cpp 27 KB

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