NetPlatform_linux.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "util/platform/netdev/NetPlatform.h"
  16. #include "util/platform/Sockaddr.h"
  17. #include "memory/Allocator.h"
  18. #include "exception/Except.h"
  19. #include "wire/Message.h"
  20. #include "util/AddrTools.h"
  21. #include "util/Assert.h"
  22. #include <stdbool.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <sys/ioctl.h>
  27. #include <fcntl.h>
  28. #include <unistd.h>
  29. #include <sys/socket.h>
  30. #include <sys/types.h>
  31. #include <stdlib.h>
  32. #include <stddef.h>
  33. #include <arpa/inet.h>
  34. #include <linux/if.h>
  35. #include <linux/route.h>
  36. #if ! defined(android)
  37. #include <linux/ipv6_route.h>
  38. #endif
  39. #include <linux/netlink.h>
  40. #include <linux/rtnetlink.h>
  41. #include <net/if.h>
  42. // Way to identify our routes as opposed to statically created or otherwise...
  43. #define RTPROT_CJDNS 52
  44. /**
  45. * This hack exists because linux/in.h and linux/in6.h define
  46. * the same structures, leading to redefinition errors.
  47. * For the second operand, we're grateful to android/bionic, platform level 21.
  48. */
  49. struct Cjdns_in6_ifreq
  50. {
  51. struct in6_addr ifr6_addr;
  52. uint32_t ifr6_prefixlen;
  53. int ifr6_ifindex;
  54. };
  55. /**
  56. * Get a socket and ifRequest for a given interface by name.
  57. *
  58. * @param interfaceName the name of the interface, eg: tun0
  59. * @param af either AF_INET or AF_INET6
  60. * @param eg an exception handler in case something goes wrong.
  61. * this will send a -1 for all errors.
  62. * @param ifRequestOut an ifreq which will be populated with the interface index of the interface.
  63. * @return a socket for interacting with this interface.
  64. */
  65. static int socketForIfName(const char* interfaceName,
  66. int af,
  67. struct Except* eh,
  68. struct ifreq* ifRequestOut)
  69. {
  70. int s;
  71. if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
  72. Except_throw(eh, "socket() [%s]", strerror(errno));
  73. }
  74. memset(ifRequestOut, 0, sizeof(struct ifreq));
  75. strncpy(ifRequestOut->ifr_name, interfaceName, IFNAMSIZ);
  76. if (ioctl(s, SIOCGIFINDEX, ifRequestOut) < 0) {
  77. int err = errno;
  78. close(s);
  79. Except_throw(eh, "ioctl(SIOCGIFINDEX) [%s]", strerror(err));
  80. }
  81. return s;
  82. }
  83. /** don't use if_nametoindex() because it accesses the filesystem. */
  84. static int ifIndexForName(const char* interfaceName, struct Except* eh)
  85. {
  86. struct ifreq ifRequest;
  87. int s = socketForIfName(interfaceName, AF_INET, eh, &ifRequest);
  88. close(s);
  89. return ifRequest.ifr_ifindex;
  90. }
  91. static void checkInterfaceUp(int socket,
  92. struct ifreq* ifRequest,
  93. struct Log* logger,
  94. struct Except* eh)
  95. {
  96. if (ioctl(socket, SIOCGIFFLAGS, ifRequest) < 0) {
  97. int err = errno;
  98. close(socket);
  99. Except_throw(eh, "ioctl(SIOCGIFFLAGS) [%s]", strerror(err));
  100. }
  101. if (ifRequest->ifr_flags & IFF_UP & IFF_RUNNING) {
  102. // already up.
  103. return;
  104. }
  105. Log_info(logger, "Bringing up interface [%s]", ifRequest->ifr_name);
  106. ifRequest->ifr_flags |= IFF_UP | IFF_RUNNING;
  107. if (ioctl(socket, SIOCSIFFLAGS, ifRequest) < 0) {
  108. int err = errno;
  109. close(socket);
  110. Except_throw(eh, "ioctl(SIOCSIFFLAGS) [%s]", strerror(err));
  111. }
  112. }
  113. void NetPlatform_addAddress(const char* interfaceName,
  114. const uint8_t* address,
  115. int prefixLen,
  116. int addrFam,
  117. struct Log* logger,
  118. struct Allocator* tempAlloc,
  119. struct Except* eh)
  120. {
  121. struct ifreq ifRequest;
  122. int s = socketForIfName(interfaceName, addrFam, eh, &ifRequest);
  123. int ifIndex = ifRequest.ifr_ifindex;
  124. // checkInterfaceUp() clobbers the ifindex.
  125. checkInterfaceUp(s, &ifRequest, logger, eh);
  126. if (addrFam == Sockaddr_AF_INET6) {
  127. struct Cjdns_in6_ifreq ifr6 = {
  128. .ifr6_ifindex = ifIndex,
  129. .ifr6_prefixlen = prefixLen
  130. };
  131. memcpy(&ifr6.ifr6_addr, address, 16);
  132. if (ioctl(s, SIOCSIFADDR, &ifr6) < 0) {
  133. int err = errno;
  134. close(s);
  135. if (err == EPERM) {
  136. Except_throw(eh, "ioctl permission denied, Are you root and is ipv6 enabled?");
  137. } else {
  138. Except_throw(eh, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
  139. }
  140. }
  141. } else if (addrFam == Sockaddr_AF_INET) {
  142. struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = 0 };
  143. memcpy(&sin.sin_addr.s_addr, address, 4);
  144. memcpy(&ifRequest.ifr_addr, &sin, sizeof(struct sockaddr));
  145. if (ioctl(s, SIOCSIFADDR, &ifRequest) < 0) {
  146. int err = errno;
  147. close(s);
  148. Except_throw(eh, "ioctl(SIOCSIFADDR) failed: [%s]", strerror(err));
  149. }
  150. uint32_t x = (uint32_t)~0 << (32 - prefixLen);
  151. x = Endian_hostToBigEndian32(x);
  152. memcpy(&sin.sin_addr, &x, 4);
  153. memcpy(&ifRequest.ifr_addr, &sin, sizeof(struct sockaddr_in));
  154. if (ioctl(s, SIOCSIFNETMASK, &ifRequest) < 0) {
  155. int err = errno;
  156. close(s);
  157. Except_throw(eh, "ioctl(SIOCSIFNETMASK) failed: [%s]", strerror(err));
  158. }
  159. } else {
  160. Assert_true(0);
  161. }
  162. close(s);
  163. }
  164. void NetPlatform_setMTU(const char* interfaceName,
  165. uint32_t mtu,
  166. struct Log* logger,
  167. struct Except* eh)
  168. {
  169. struct ifreq ifRequest;
  170. int s = socketForIfName(interfaceName, AF_INET6, eh, &ifRequest);
  171. Log_info(logger, "Setting MTU for device [%s] to [%u] bytes.", interfaceName, mtu);
  172. ifRequest.ifr_mtu = mtu;
  173. if (ioctl(s, SIOCSIFMTU, &ifRequest) < 0) {
  174. int err = errno;
  175. close(s);
  176. Except_throw(eh, "ioctl(SIOCSIFMTU) [%s]", strerror(err));
  177. }
  178. close(s);
  179. }
  180. struct IfIndexAttr {
  181. struct rtattr rta;
  182. int ifIndex;
  183. };
  184. Assert_compileTime(sizeof(struct IfIndexAttr) == 8);
  185. struct RouteRequest {
  186. struct nlmsghdr hdr;
  187. struct rtmsg route;
  188. };
  189. Assert_compileTime(sizeof(struct nlmsghdr) == 16);
  190. Assert_compileTime(sizeof(struct rtmsg) == 12);
  191. Assert_compileTime(sizeof(struct RouteRequest) == 28);
  192. struct RouteInfo;
  193. struct RouteInfo {
  194. struct RouteInfo* next;
  195. int protocol;
  196. int prefix;
  197. uint8_t dstAddr[16];
  198. int ifIndex;
  199. int af;
  200. };
  201. #define BUFF_SZ 16384
  202. static bool getMoreMessages(struct RouteInfo** rio,
  203. int sock,
  204. int ifIndex,
  205. struct Allocator* alloc,
  206. struct Except* eh)
  207. {
  208. bool retVal = false;
  209. struct Allocator* tempAlloc = Allocator_child(alloc);
  210. struct Message* msg = Message_new(BUFF_SZ, 0, tempAlloc);
  211. ssize_t sz = recv(sock, msg->bytes, BUFF_SZ, MSG_TRUNC);
  212. if (sz < (ssize_t)sizeof(struct nlmsghdr)) {
  213. Except_throw(eh, "recv() -> %s", strerror(errno));
  214. } else if (sz > BUFF_SZ) {
  215. Except_throw(eh, "recv() -> buffer too small");
  216. }
  217. msg->length = sz;
  218. //printf("%s\n", Hex_print(msg->bytes, msg->length, tempAlloc));
  219. while (msg->length) {
  220. struct RouteInfo ri = { .protocol = 0 };
  221. int initMsgLen = msg->length;
  222. struct nlmsghdr hdr;
  223. Message_pop(msg, &hdr, sizeof(struct nlmsghdr), eh);
  224. //printf("\nHEADER %04x %04x\n", hdr.nlmsg_type, hdr.nlmsg_flags);
  225. if (hdr.nlmsg_flags & NLM_F_MULTI) { retVal = true; }
  226. if (hdr.nlmsg_type == NLMSG_DONE) {
  227. Allocator_free(tempAlloc);
  228. return false;
  229. }
  230. struct rtmsg rtm;
  231. Message_pop(msg, &rtm, sizeof(struct rtmsg), eh);
  232. ri.prefix = rtm.rtm_dst_len;
  233. ri.af = rtm.rtm_family;
  234. ri.protocol = rtm.rtm_protocol;
  235. for (;;) {
  236. int remainingLen = hdr.nlmsg_len - (initMsgLen - msg->length);
  237. if (remainingLen <= (int)sizeof(struct rtattr)) { break; }
  238. struct rtattr attrHead;
  239. //printf(">%s %d\n", Hex_print(msg->bytes, msg->length, tempAlloc), remainingLen);
  240. Message_pop(msg, &attrHead, sizeof(struct rtattr), eh);
  241. switch (attrHead.rta_type) {
  242. case RTA_OIF: {
  243. if (attrHead.rta_len != 8) {
  244. Except_throw(eh, "unexpected rta_len for ifIndex");
  245. }
  246. Message_pop(msg, &ri.ifIndex, 4, eh);
  247. break;
  248. }
  249. case RTA_DST: {
  250. if (rtm.rtm_family == AF_INET6) {
  251. if (attrHead.rta_len != 20) {
  252. Except_throw(eh, "unexpected rta_len for RTA_DST (ipv6)");
  253. }
  254. Message_pop(msg, ri.dstAddr, 16, eh);
  255. } else if (rtm.rtm_family == AF_INET) {
  256. if (attrHead.rta_len != 8) {
  257. Except_throw(eh, "unexpected rta_len for RTA_DST (ipv4)");
  258. }
  259. Message_pop(msg, ri.dstAddr, 4, eh);
  260. } else {
  261. Except_throw(eh, "unexpected af %d", rtm.rtm_family);
  262. }
  263. break;
  264. }
  265. default: {
  266. int effectiveLen = RTA_ALIGN(attrHead.rta_len);
  267. //printf("unrecognized %d (length %d)\n", attrHead.rta_type, effectiveLen);
  268. Message_pop(msg, NULL, effectiveLen - sizeof(struct rtattr), eh);
  269. break;
  270. }
  271. }
  272. }
  273. if (rtm.rtm_table != RT_TABLE_MAIN) { continue; }
  274. if (rtm.rtm_type != RTN_UNICAST) { continue; }
  275. if (ri.ifIndex != ifIndex) { continue; }
  276. if (ri.protocol != RTPROT_CJDNS) { continue; }
  277. struct RouteInfo* outRi = Allocator_clone(alloc, &ri);
  278. outRi->next = *rio;
  279. *rio = outRi;
  280. }
  281. Allocator_free(tempAlloc);
  282. return retVal;
  283. }
  284. static struct RouteInfo* getRoutes(int sock,
  285. int ifIndex,
  286. struct Allocator* alloc,
  287. struct Except* eh)
  288. {
  289. struct RouteRequest req = {
  290. .hdr = {
  291. .nlmsg_len = sizeof(struct RouteRequest),
  292. .nlmsg_type = RTM_GETROUTE,
  293. .nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT | NLM_F_MULTI
  294. },
  295. .route = {
  296. .rtm_family = AF_UNSPEC
  297. }
  298. };
  299. ssize_t sz = send(sock, &req, req.hdr.nlmsg_len, 0);
  300. if (sz < 0) {
  301. Except_throw(eh, "send() -> %s", strerror(errno));
  302. }
  303. struct RouteInfo* ri = NULL;
  304. while (getMoreMessages(&ri, sock, ifIndex, alloc, eh)) ;
  305. return ri;
  306. }
  307. static void bitShave(uint8_t* address, int prefix, int af)
  308. {
  309. int top;
  310. if (af == AF_INET) {
  311. top = 4;
  312. } else if (af == AF_INET6) {
  313. top = 16;
  314. } else {
  315. Assert_failure("bad af");
  316. }
  317. if (prefix < (8 * top)) {
  318. address[prefix >> 3] &= ( 0xff << (8 - (prefix % 8)) );
  319. for (int i = (prefix >> 3) + 1; i < top; i++) {
  320. address[i] = 0;
  321. }
  322. }
  323. }
  324. static void addDeleteRoutes(int sock,
  325. bool delete,
  326. struct RouteInfo* ri,
  327. struct Allocator* tempAlloc,
  328. struct Except* eh)
  329. {
  330. struct Message* msg = Message_new(0, 512, tempAlloc);
  331. for (;ri;ri = ri->next) {
  332. struct IfIndexAttr ifa = {
  333. .rta = {
  334. .rta_len = sizeof(struct IfIndexAttr),
  335. .rta_type = RTA_OIF
  336. },
  337. .ifIndex = ri->ifIndex
  338. };
  339. Message_push(msg, &ifa, sizeof(struct IfIndexAttr), NULL);
  340. int addrLen = (ri->af == AF_INET6) ? 16 : 4;
  341. Message_push(msg, ri->dstAddr, addrLen, NULL);
  342. bitShave(msg->bytes, ri->prefix, ri->af);
  343. struct rtattr rta = { .rta_len = sizeof(struct rtattr) + addrLen, .rta_type = RTA_DST };
  344. Message_push(msg, &rta, sizeof(struct rtattr), NULL);
  345. struct rtmsg route = {
  346. .rtm_family = ri->af,
  347. .rtm_dst_len = ri->prefix,
  348. .rtm_table = RT_TABLE_MAIN,
  349. .rtm_scope = (delete) ? RT_SCOPE_NOWHERE : RT_SCOPE_LINK,
  350. .rtm_protocol = (delete) ? RTPROT_UNSPEC : ri->protocol,
  351. .rtm_type = (delete) ? RTN_UNSPEC : RTN_UNICAST
  352. };
  353. Message_push(msg, &route, sizeof(struct rtmsg), NULL);
  354. struct nlmsghdr hdr = {
  355. .nlmsg_len = msg->length + sizeof(struct nlmsghdr),
  356. .nlmsg_type = (delete) ? RTM_DELROUTE : RTM_NEWROUTE,
  357. .nlmsg_flags = NLM_F_REQUEST | ((delete) ? 0 : NLM_F_CREATE) // | NLM_F_ACK,
  358. };
  359. Message_push(msg, &hdr, sizeof(struct nlmsghdr), NULL);
  360. ssize_t sz = send(sock, msg->bytes, msg->length, 0);
  361. if (sz < 0) {
  362. Except_throw(eh, "send() -> %s", strerror(errno));
  363. }
  364. Message_reset(msg);
  365. }
  366. }
  367. static int closeSocket(struct Allocator_OnFreeJob* job)
  368. {
  369. long sock = (long) job->userData;
  370. close((int)sock);
  371. return 0;
  372. }
  373. static int mkSocket(struct Allocator* alloc, struct Except* eh)
  374. {
  375. int sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  376. if (sock < 0) {
  377. Except_throw(eh, "socket(PF_NETLINK) -> %s", strerror(errno));
  378. }
  379. Allocator_onFree(alloc, closeSocket, (void*) ((long) sock));
  380. return sock;
  381. }
  382. static struct RouteInfo* riForSockaddrs(struct Sockaddr** prefixSet,
  383. int prefixCount,
  384. int ifIndex,
  385. struct Allocator* alloc)
  386. {
  387. struct RouteInfo* out = NULL;
  388. for (int i = 0; i < prefixCount; i++) {
  389. struct RouteInfo* ri = Allocator_calloc(alloc, sizeof(struct RouteInfo), 1);
  390. ri->protocol = RTPROT_CJDNS;
  391. ri->prefix = Sockaddr_getPrefix(prefixSet[i]);
  392. ri->af = Sockaddr_getFamily(prefixSet[i]);
  393. ri->ifIndex = ifIndex;
  394. uint8_t* addr;
  395. int len = Sockaddr_getAddress(prefixSet[i], &addr);
  396. Assert_true(len == 4 || len == 16);
  397. Bits_memcpy(ri->dstAddr, addr, len);
  398. ri->next = out;
  399. out = ri;
  400. }
  401. return out;
  402. }
  403. static void logRis(struct RouteInfo* ri, struct Log* logger, char* msg)
  404. {
  405. for (; ri; ri = ri->next) {
  406. uint8_t addrBuff[40] = {0};
  407. if (ri->af == AF_INET6) {
  408. AddrTools_printIp(addrBuff, ri->dstAddr);
  409. } else if (ri->af == AF_INET) {
  410. snprintf(addrBuff, 40, "%u.%u.%u.%u",
  411. ri->dstAddr[0], ri->dstAddr[1], ri->dstAddr[2], ri->dstAddr[3]);
  412. }
  413. Log_debug(logger, "%s %s/%u", msg, addrBuff, ri->prefix);
  414. }
  415. }
  416. void NetPlatform_setRoutes(const char* ifName,
  417. struct Sockaddr** prefixSet,
  418. int prefixCount,
  419. struct Log* logger,
  420. struct Allocator* tempAlloc,
  421. struct Except* eh)
  422. {
  423. int ifIndex = ifIndexForName(ifName, eh);
  424. struct RouteInfo* newRi = riForSockaddrs(prefixSet, prefixCount, ifIndex, tempAlloc);
  425. int sock = mkSocket(tempAlloc, eh);
  426. struct RouteInfo* oldRi = getRoutes(sock, ifIndex, tempAlloc, eh);
  427. logRis(oldRi, logger, "DELETE ROUTE");
  428. addDeleteRoutes(sock, true, oldRi, tempAlloc, eh);
  429. logRis(newRi, logger, "ADD ROUTE");
  430. addDeleteRoutes(sock, false, newRi, tempAlloc, eh);
  431. }