ZT_jniutils.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /*
  2. * ZeroTier One - Network Virtualization Everywhere
  3. * Copyright (C) 2011-2016 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. #include "ZT_jniutils.h"
  19. #include "ZT_jnicache.h"
  20. #include <string>
  21. #include <cassert>
  22. #include <arpa/inet.h>
  23. #include <netinet/in.h>
  24. #include <sys/types.h>
  25. #define LOG_TAG "Utils"
  26. jobject createResultObject(JNIEnv *env, ZT_ResultCode code)
  27. {
  28. jobject resultObject = env->CallStaticObjectMethod(ResultCode_class, ResultCode_fromInt_method, code);
  29. if(env->ExceptionCheck() || resultObject == NULL) {
  30. LOGE("Error creating ResultCode object");
  31. return NULL;
  32. }
  33. return resultObject;
  34. }
  35. jobject createVirtualNetworkStatus(JNIEnv *env, ZT_VirtualNetworkStatus status)
  36. {
  37. jobject statusObject = env->CallStaticObjectMethod(VirtualNetworkStatus_class, VirtualNetworkStatus_fromInt_method, status);
  38. if (env->ExceptionCheck() || statusObject == NULL) {
  39. LOGE("Error creating VirtualNetworkStatus object");
  40. return NULL;
  41. }
  42. return statusObject;
  43. }
  44. jobject createEvent(JNIEnv *env, ZT_Event event)
  45. {
  46. jobject eventObject = env->CallStaticObjectMethod(Event_class, Event_fromInt_method, event);
  47. if (env->ExceptionCheck() || eventObject == NULL) {
  48. LOGE("Error creating Event object");
  49. return NULL;
  50. }
  51. return eventObject;
  52. }
  53. jobject createPeerRole(JNIEnv *env, ZT_PeerRole role)
  54. {
  55. jobject peerRoleObject = env->CallStaticObjectMethod(PeerRole_class, PeerRole_fromInt_method, role);
  56. if (env->ExceptionCheck() || peerRoleObject == NULL) {
  57. LOGE("Error creating PeerRole object");
  58. return NULL;
  59. }
  60. return peerRoleObject;
  61. }
  62. jobject createVirtualNetworkType(JNIEnv *env, ZT_VirtualNetworkType type)
  63. {
  64. jobject vntypeObject = env->CallStaticObjectMethod(VirtualNetworkType_class, VirtualNetworkType_fromInt_method, type);
  65. if (env->ExceptionCheck() || vntypeObject == NULL) {
  66. LOGE("Error creating VirtualNetworkType object");
  67. return NULL;
  68. }
  69. return vntypeObject;
  70. }
  71. jobject createVirtualNetworkConfigOperation(JNIEnv *env, ZT_VirtualNetworkConfigOperation op)
  72. {
  73. jobject vnetConfigOpObject = env->CallStaticObjectMethod(VirtualNetworkConfigOperation_class, VirtualNetworkConfigOperation_fromInt_method, op);
  74. if (env->ExceptionCheck() || vnetConfigOpObject == NULL) {
  75. LOGE("Error creating VirtualNetworkConfigOperation object");
  76. return NULL;
  77. }
  78. return vnetConfigOpObject;
  79. }
  80. jobject newInetAddress(JNIEnv *env, const sockaddr_storage &addr)
  81. {
  82. jobject inetAddressObj = NULL;
  83. switch(addr.ss_family)
  84. {
  85. case AF_INET6:
  86. {
  87. sockaddr_in6 *ipv6 = (sockaddr_in6*)&addr;
  88. const unsigned char *bytes = reinterpret_cast<const unsigned char *>(&ipv6->sin6_addr.s6_addr);
  89. jbyteArray buff = newByteArray(env, bytes, 16);
  90. if(env->ExceptionCheck() || buff == NULL)
  91. {
  92. return NULL;
  93. }
  94. inetAddressObj = env->CallStaticObjectMethod(
  95. InetAddress_class, InetAddress_getByAddress_method, buff);
  96. }
  97. break;
  98. case AF_INET:
  99. {
  100. sockaddr_in *ipv4 = (sockaddr_in*)&addr;
  101. const unsigned char *bytes = reinterpret_cast<const unsigned char *>(&ipv4->sin_addr.s_addr);
  102. jbyteArray buff = newByteArray(env, bytes, 4);
  103. if(env->ExceptionCheck() || buff == NULL)
  104. {
  105. return NULL;
  106. }
  107. inetAddressObj = env->CallStaticObjectMethod(
  108. InetAddress_class, InetAddress_getByAddress_method, buff);
  109. }
  110. break;
  111. default:
  112. {
  113. assert(false && "addr.ss_family is neither AF_INET6 nor AF_INET");
  114. }
  115. }
  116. if(env->ExceptionCheck() || inetAddressObj == NULL) {
  117. LOGE("Error creating InetAddress object");
  118. return NULL;
  119. }
  120. return inetAddressObj;
  121. }
  122. int addressPort(const sockaddr_storage addr) {
  123. int port = 0;
  124. switch(addr.ss_family)
  125. {
  126. case AF_INET6:
  127. {
  128. sockaddr_in6 *ipv6 = (sockaddr_in6*)&addr;
  129. port = ntohs(ipv6->sin6_port);
  130. }
  131. break;
  132. case AF_INET:
  133. {
  134. sockaddr_in *ipv4 = (sockaddr_in*)&addr;
  135. port = ntohs(ipv4->sin_port);
  136. }
  137. break;
  138. default:
  139. {
  140. assert(false && "addr.ss_family is neither AF_INET6 nor AF_INET");
  141. }
  142. }
  143. return port;
  144. }
  145. //
  146. // addr may be empty
  147. //
  148. // may return NULL
  149. //
  150. jobject newInetSocketAddress(JNIEnv *env, const sockaddr_storage &addr)
  151. {
  152. if(isSocketAddressEmpty(addr))
  153. {
  154. return NULL;
  155. }
  156. jobject inetAddressObject = newInetAddress(env, addr);
  157. if(env->ExceptionCheck() || inetAddressObject == NULL)
  158. {
  159. return NULL;
  160. }
  161. int port = addressPort(addr);
  162. jobject inetSocketAddressObject = env->NewObject(InetSocketAddress_class, InetSocketAddress_ctor, inetAddressObject, port);
  163. if(env->ExceptionCheck() || inetSocketAddressObject == NULL) {
  164. LOGE("Error creating InetSocketAddress object");
  165. return NULL;
  166. }
  167. return inetSocketAddressObject;
  168. }
  169. jobject newPeerPhysicalPath(JNIEnv *env, const ZT_PeerPhysicalPath &ppp)
  170. {
  171. //
  172. // may be NULL
  173. //
  174. jobject addressObject = newInetSocketAddress(env, ppp.address);
  175. if(env->ExceptionCheck()) {
  176. return NULL;
  177. }
  178. jobject pppObject = env->NewObject(
  179. PeerPhysicalPath_class,
  180. PeerPhysicalPath_ctor,
  181. addressObject,
  182. ppp.lastSend,
  183. ppp.lastReceive,
  184. ppp.preferred);
  185. if(env->ExceptionCheck() || pppObject == NULL)
  186. {
  187. LOGE("Error creating PPP object");
  188. return NULL;
  189. }
  190. return pppObject;
  191. }
  192. jobject newPeer(JNIEnv *env, const ZT_Peer &peer)
  193. {
  194. jobject peerRoleObj = createPeerRole(env, peer.role);
  195. if(env->ExceptionCheck() || peerRoleObj == NULL)
  196. {
  197. return NULL; // out of memory
  198. }
  199. jobjectArray arrayObject = newPeerPhysicalPathArray(env, peer.paths, peer.pathCount);
  200. if (env->ExceptionCheck() || arrayObject == NULL) {
  201. return NULL;
  202. }
  203. jobject peerObject = env->NewObject(
  204. Peer_class,
  205. Peer_ctor,
  206. peer.address,
  207. peer.versionMajor,
  208. peer.versionMinor,
  209. peer.versionRev,
  210. peer.latency,
  211. peerRoleObj,
  212. arrayObject);
  213. if(env->ExceptionCheck() || peerObject == NULL)
  214. {
  215. LOGE("Error creating Peer object");
  216. return NULL;
  217. }
  218. return peerObject;
  219. }
  220. jobject newNetworkConfig(JNIEnv *env, const ZT_VirtualNetworkConfig &vnetConfig)
  221. {
  222. jstring nameStr = env->NewStringUTF(vnetConfig.name);
  223. if(env->ExceptionCheck() || nameStr == NULL)
  224. {
  225. LOGE("Exception creating new string");
  226. return NULL; // out of memory
  227. }
  228. jobject statusObject = createVirtualNetworkStatus(env, vnetConfig.status);
  229. if(env->ExceptionCheck() || statusObject == NULL)
  230. {
  231. return NULL;
  232. }
  233. jobject typeObject = createVirtualNetworkType(env, vnetConfig.type);
  234. if(env->ExceptionCheck() || typeObject == NULL)
  235. {
  236. return NULL;
  237. }
  238. jobjectArray assignedAddrArrayObj = newInetSocketAddressArray(env, vnetConfig.assignedAddresses, vnetConfig.assignedAddressCount);
  239. if (env->ExceptionCheck() || assignedAddrArrayObj == NULL) {
  240. return NULL;
  241. }
  242. jobjectArray routesArrayObj = newVirtualNetworkRouteArray(env, vnetConfig.routes, vnetConfig.routeCount);
  243. if (env->ExceptionCheck() || routesArrayObj == NULL) {
  244. return NULL;
  245. }
  246. //
  247. // may be NULL
  248. //
  249. jobject dnsObj = newVirtualNetworkDNS(env, vnetConfig.dns);
  250. if(env->ExceptionCheck()) {
  251. return NULL;
  252. }
  253. jobject vnetConfigObj = env->NewObject(
  254. VirtualNetworkConfig_class,
  255. VirtualNetworkConfig_ctor,
  256. vnetConfig.nwid,
  257. vnetConfig.mac,
  258. nameStr,
  259. statusObject,
  260. typeObject,
  261. vnetConfig.mtu,
  262. vnetConfig.dhcp,
  263. vnetConfig.bridge,
  264. vnetConfig.broadcastEnabled,
  265. //
  266. // ANDROID-56: temporarily remove parameters to prevent crashing
  267. //
  268. // vnetConfig.portError,
  269. // vnetConfig.netconfRevision,
  270. assignedAddrArrayObj,
  271. routesArrayObj,
  272. dnsObj);
  273. if(env->ExceptionCheck() || vnetConfigObj == NULL)
  274. {
  275. LOGE("Error creating new VirtualNetworkConfig object");
  276. return NULL;
  277. }
  278. return vnetConfigObj;
  279. }
  280. jobject newVersion(JNIEnv *env, int major, int minor, int rev)
  281. {
  282. // create a com.zerotier.sdk.Version object
  283. jobject versionObj = env->NewObject(Version_class, Version_ctor, major, minor, rev);
  284. if(env->ExceptionCheck() || versionObj == NULL)
  285. {
  286. LOGE("Error creating new Version object");
  287. return NULL;
  288. }
  289. return versionObj;
  290. }
  291. jobject newVirtualNetworkRoute(JNIEnv *env, const ZT_VirtualNetworkRoute &route)
  292. {
  293. //
  294. // may be NULL
  295. //
  296. jobject targetObj = newInetSocketAddress(env, route.target);
  297. if (env->ExceptionCheck()) {
  298. return NULL;
  299. }
  300. //
  301. // may be NULL
  302. //
  303. jobject viaObj = newInetSocketAddress(env, route.via);
  304. if (env->ExceptionCheck()) {
  305. return NULL;
  306. }
  307. jobject routeObj = env->NewObject(
  308. VirtualNetworkRoute_class,
  309. VirtualNetworkRoute_ctor,
  310. targetObj,
  311. viaObj,
  312. route.flags,
  313. route.metric);
  314. if(env->ExceptionCheck() || routeObj == NULL)
  315. {
  316. LOGE("Exception creating VirtualNetworkRoute");
  317. return NULL;
  318. }
  319. return routeObj;
  320. }
  321. //
  322. // may return NULL
  323. //
  324. jobject newVirtualNetworkDNS(JNIEnv *env, const ZT_VirtualNetworkDNS &dns)
  325. {
  326. if (strlen(dns.domain) == 0) {
  327. LOGD("dns.domain is empty; returning NULL");
  328. return NULL;
  329. }
  330. jstring domain = env->NewStringUTF(dns.domain);
  331. if (env->ExceptionCheck() || domain == NULL) {
  332. LOGE("Exception creating new string");
  333. return NULL;
  334. }
  335. jobject addrList = env->NewObject(ArrayList_class, ArrayList_ctor, 0);
  336. if (env->ExceptionCheck() || addrList == NULL) {
  337. LOGE("Exception creating new ArrayList");
  338. return NULL;
  339. }
  340. for (int i = 0; i < ZT_MAX_DNS_SERVERS; ++i) { //NOLINT
  341. struct sockaddr_storage tmp = dns.server_addr[i];
  342. //
  343. // may be NULL
  344. //
  345. jobject addr = newInetSocketAddress(env, tmp);
  346. if (env->ExceptionCheck()) {
  347. return NULL;
  348. }
  349. if (addr == NULL) {
  350. continue;
  351. }
  352. env->CallBooleanMethod(addrList, ArrayList_add_method, addr);
  353. if(env->ExceptionCheck())
  354. {
  355. LOGE("Exception calling add");
  356. return NULL;
  357. }
  358. env->DeleteLocalRef(addr);
  359. }
  360. jobject dnsObj = env->NewObject(
  361. VirtualNetworkDNS_class,
  362. VirtualNetworkDNS_ctor,
  363. domain,
  364. addrList);
  365. if (env->ExceptionCheck() || dnsObj == NULL) {
  366. LOGE("Exception creating new VirtualNetworkDNS");
  367. return NULL;
  368. }
  369. return dnsObj;
  370. }
  371. jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status) {
  372. jstring pubIdentStr = env->NewStringUTF(status.publicIdentity);
  373. if(env->ExceptionCheck() || pubIdentStr == NULL)
  374. {
  375. LOGE("Exception creating new string");
  376. return NULL;
  377. }
  378. jstring secIdentStr = env->NewStringUTF(status.secretIdentity);
  379. if(env->ExceptionCheck() || secIdentStr == NULL)
  380. {
  381. LOGE("Exception creating new string");
  382. return NULL;
  383. }
  384. jobject nodeStatusObj = env->NewObject(
  385. NodeStatus_class,
  386. NodeStatus_ctor,
  387. status.address,
  388. pubIdentStr,
  389. secIdentStr,
  390. status.online);
  391. if(env->ExceptionCheck() || nodeStatusObj == NULL) {
  392. LOGE("Exception creating new NodeStatus");
  393. return NULL;
  394. }
  395. return nodeStatusObj;
  396. }
  397. jobjectArray newPeerArray(JNIEnv *env, const ZT_Peer *peers, size_t count) {
  398. return newArrayObject<ZT_Peer, newPeer>(env, peers, count, Peer_class);
  399. }
  400. jobjectArray newVirtualNetworkConfigArray(JNIEnv *env, const ZT_VirtualNetworkConfig *networks, size_t count) {
  401. return newArrayObject<ZT_VirtualNetworkConfig, newNetworkConfig>(env, networks, count, VirtualNetworkConfig_class);
  402. }
  403. jobjectArray newPeerPhysicalPathArray(JNIEnv *env, const ZT_PeerPhysicalPath *paths, size_t count) {
  404. return newArrayObject<ZT_PeerPhysicalPath, newPeerPhysicalPath>(env, paths, count, PeerPhysicalPath_class);
  405. }
  406. jobjectArray newInetSocketAddressArray(JNIEnv *env, const sockaddr_storage *addresses, size_t count) {
  407. return newArrayObject<sockaddr_storage, newInetSocketAddress>(env, addresses, count, InetSocketAddress_class);
  408. }
  409. jobjectArray newVirtualNetworkRouteArray(JNIEnv *env, const ZT_VirtualNetworkRoute *routes, size_t count) {
  410. return newArrayObject<ZT_VirtualNetworkRoute, newVirtualNetworkRoute>(env, routes, count, VirtualNetworkRoute_class);
  411. }
  412. void newArrayObject_logCount(size_t count) {
  413. LOGE("count > JSIZE_MAX: %zu", count);
  414. }
  415. void newArrayObject_log(const char *msg) {
  416. LOGE("%s", msg);
  417. }
  418. jbyteArray newByteArray(JNIEnv *env, const unsigned char *bytes, size_t count) {
  419. if (count > JSIZE_MAX) {
  420. LOGE("count > JSIZE_MAX: %zu", count);
  421. return NULL;
  422. }
  423. jsize jCount = static_cast<jsize>(count);
  424. const jbyte *jBytes = reinterpret_cast<const jbyte *>(bytes);
  425. jbyteArray byteArrayObj = env->NewByteArray(jCount);
  426. if(byteArrayObj == NULL)
  427. {
  428. LOGE("NewByteArray returned NULL");
  429. return NULL;
  430. }
  431. env->SetByteArrayRegion(byteArrayObj, 0, jCount, jBytes);
  432. if (env->ExceptionCheck()) {
  433. LOGE("Exception when calling SetByteArrayRegion");
  434. return NULL;
  435. }
  436. return byteArrayObj;
  437. }
  438. jbyteArray newByteArray(JNIEnv *env, size_t count) {
  439. if (count > JSIZE_MAX) {
  440. LOGE("count > JSIZE_MAX: %zu", count);
  441. return NULL;
  442. }
  443. jsize jCount = static_cast<jsize>(count);
  444. jbyteArray byteArrayObj = env->NewByteArray(jCount);
  445. if(byteArrayObj == NULL)
  446. {
  447. LOGE("NewByteArray returned NULL");
  448. return NULL;
  449. }
  450. return byteArrayObj;
  451. }
  452. bool isSocketAddressEmpty(const sockaddr_storage addr) {
  453. //
  454. // was:
  455. // struct sockaddr_storage nullAddress = {0};
  456. //
  457. // but was getting this warning:
  458. // warning: suggest braces around initialization of subobject
  459. //
  460. // when building ZeroTierOne
  461. //
  462. sockaddr_storage emptyAddress; //NOLINT
  463. //
  464. // It is possible to assume knowledge about internals of sockaddr_storage and construct
  465. // correct 0-initializer, but it is simpler to just treat sockaddr_storage as opaque and
  466. // use memset here to fill with 0
  467. //
  468. // This is also done in InetAddress.hpp for InetAddress
  469. //
  470. memset(&emptyAddress, 0, sizeof(sockaddr_storage));
  471. return (memcmp(&addr, &emptyAddress, sizeof(sockaddr_storage)) == 0); //NOLINT
  472. }
  473. //
  474. // returns empty sockaddr_storage on error
  475. //
  476. sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject) {
  477. sockaddr_storage emptyAddress; //NOLINT
  478. memset(&emptyAddress, 0, sizeof(sockaddr_storage));
  479. jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method);
  480. if(env->ExceptionCheck())
  481. {
  482. LOGE("Exception calling getPort");
  483. return emptyAddress;
  484. }
  485. jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method);
  486. if(env->ExceptionCheck() || addressObject == NULL)
  487. {
  488. LOGE("Exception calling getAddress");
  489. return emptyAddress;
  490. }
  491. jbyteArray addressArrayObj = reinterpret_cast<jbyteArray>(env->CallObjectMethod(addressObject, InetAddress_getAddress_method));
  492. if(env->ExceptionCheck() || addressArrayObj == NULL)
  493. {
  494. LOGE("Exception calling getAddress");
  495. return emptyAddress;
  496. }
  497. sockaddr_storage addr = {};
  498. if (env->IsInstanceOf(addressObject, Inet4Address_class)) {
  499. // IPV4
  500. assert(env->GetArrayLength(addressArrayObj) == 4);
  501. sockaddr_in *addr_4 = reinterpret_cast<sockaddr_in *>(&addr);
  502. addr_4->sin_family = AF_INET;
  503. addr_4->sin_port = htons(port);
  504. void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
  505. memcpy(&addr_4->sin_addr.s_addr, data, 4);
  506. env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
  507. } else if (env->IsInstanceOf(addressObject, Inet6Address_class)) {
  508. // IPV6
  509. assert(env->GetArrayLength(addressArrayObj) == 16);
  510. sockaddr_in6 *addr_6 = reinterpret_cast<sockaddr_in6 *>(&addr);
  511. addr_6->sin6_family = AF_INET6;
  512. addr_6->sin6_port = htons(port);
  513. void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
  514. memcpy(&addr_6->sin6_addr.s6_addr, data, 16);
  515. env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
  516. } else {
  517. assert(false && "addressObject is neither Inet4Address nor Inet6Address");
  518. }
  519. return addr;
  520. }