NetPlatform_linux.c 16 KB

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