ZT_jniutils.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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, (jint)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, (jint)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, (jint)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, (jint)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, (jint)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, (jint)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, (jbyteArray)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, (jbyteArray)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, (jobject)inetAddressObject, (jint)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. (jobject)addressObject,
  182. (jlong)ppp.lastSend,
  183. (jlong)ppp.lastReceive,
  184. (jboolean)ppp.preferred); // ANDROID-56: cast to correct size
  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. (jlong)peer.address,
  207. (jint)peer.versionMajor,
  208. (jint)peer.versionMinor,
  209. (jint)peer.versionRev,
  210. (jint)peer.latency,
  211. (jobject)peerRoleObj,
  212. (jobjectArray)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. (jlong)vnetConfig.nwid,
  257. (jlong)vnetConfig.mac,
  258. (jstring)nameStr,
  259. (jobject)statusObject,
  260. (jobject)typeObject,
  261. (jint)vnetConfig.mtu,
  262. (jboolean)vnetConfig.dhcp, // ANDROID-56: cast to correct size
  263. (jboolean)vnetConfig.bridge, // ANDROID-56: cast to correct size
  264. (jboolean)vnetConfig.broadcastEnabled, // ANDROID-56: cast to correct size
  265. (jint)vnetConfig.portError,
  266. (jlong)vnetConfig.netconfRevision,
  267. (jobjectArray)assignedAddrArrayObj,
  268. (jobjectArray)routesArrayObj,
  269. (jobject)dnsObj);
  270. if(env->ExceptionCheck() || vnetConfigObj == NULL)
  271. {
  272. LOGE("Error creating new VirtualNetworkConfig object");
  273. return NULL;
  274. }
  275. return vnetConfigObj;
  276. }
  277. jobject newVersion(JNIEnv *env, int major, int minor, int rev)
  278. {
  279. // create a com.zerotier.sdk.Version object
  280. jobject versionObj = env->NewObject(Version_class, Version_ctor, (jint)major, (jint)minor, (jint)rev);
  281. if(env->ExceptionCheck() || versionObj == NULL)
  282. {
  283. LOGE("Error creating new Version object");
  284. return NULL;
  285. }
  286. return versionObj;
  287. }
  288. jobject newVirtualNetworkRoute(JNIEnv *env, const ZT_VirtualNetworkRoute &route)
  289. {
  290. //
  291. // may be NULL
  292. //
  293. jobject targetObj = newInetSocketAddress(env, route.target);
  294. if (env->ExceptionCheck()) {
  295. return NULL;
  296. }
  297. //
  298. // may be NULL
  299. //
  300. jobject viaObj = newInetSocketAddress(env, route.via);
  301. if (env->ExceptionCheck()) {
  302. return NULL;
  303. }
  304. jobject routeObj = env->NewObject(
  305. VirtualNetworkRoute_class,
  306. VirtualNetworkRoute_ctor,
  307. (jobject)targetObj,
  308. (jobject)viaObj,
  309. (jint)route.flags, // ANDROID-56: cast to correct size
  310. (jint)route.metric); // ANDROID-56: cast to correct size
  311. if(env->ExceptionCheck() || routeObj == NULL)
  312. {
  313. LOGE("Exception creating VirtualNetworkRoute");
  314. return NULL;
  315. }
  316. return routeObj;
  317. }
  318. //
  319. // may return NULL
  320. //
  321. jobject newVirtualNetworkDNS(JNIEnv *env, const ZT_VirtualNetworkDNS &dns)
  322. {
  323. if (strlen(dns.domain) == 0) {
  324. LOGD("dns.domain is empty; returning NULL");
  325. return NULL;
  326. }
  327. jstring domain = env->NewStringUTF(dns.domain);
  328. if (env->ExceptionCheck() || domain == NULL) {
  329. LOGE("Exception creating new string");
  330. return NULL;
  331. }
  332. jobject addrList = env->NewObject(ArrayList_class, ArrayList_ctor, (jint)0);
  333. if (env->ExceptionCheck() || addrList == NULL) {
  334. LOGE("Exception creating new ArrayList");
  335. return NULL;
  336. }
  337. for (int i = 0; i < ZT_MAX_DNS_SERVERS; ++i) { //NOLINT
  338. struct sockaddr_storage tmp = dns.server_addr[i];
  339. //
  340. // may be NULL
  341. //
  342. jobject addr = newInetSocketAddress(env, tmp);
  343. if (env->ExceptionCheck()) {
  344. return NULL;
  345. }
  346. if (addr == NULL) {
  347. continue;
  348. }
  349. env->CallBooleanMethod(addrList, ArrayList_add_method, (jobject)addr);
  350. if(env->ExceptionCheck())
  351. {
  352. LOGE("Exception calling add");
  353. return NULL;
  354. }
  355. env->DeleteLocalRef(addr);
  356. }
  357. jobject dnsObj = env->NewObject(
  358. VirtualNetworkDNS_class,
  359. VirtualNetworkDNS_ctor,
  360. (jstring)domain,
  361. (jobject)addrList);
  362. if (env->ExceptionCheck() || dnsObj == NULL) {
  363. LOGE("Exception creating new VirtualNetworkDNS");
  364. return NULL;
  365. }
  366. return dnsObj;
  367. }
  368. jobject newNodeStatus(JNIEnv *env, const ZT_NodeStatus &status) {
  369. jstring pubIdentStr = env->NewStringUTF(status.publicIdentity);
  370. if(env->ExceptionCheck() || pubIdentStr == NULL)
  371. {
  372. LOGE("Exception creating new string");
  373. return NULL;
  374. }
  375. jstring secIdentStr = env->NewStringUTF(status.secretIdentity);
  376. if(env->ExceptionCheck() || secIdentStr == NULL)
  377. {
  378. LOGE("Exception creating new string");
  379. return NULL;
  380. }
  381. jobject nodeStatusObj = env->NewObject(
  382. NodeStatus_class,
  383. NodeStatus_ctor,
  384. (jlong)status.address,
  385. (jstring)pubIdentStr,
  386. (jstring)secIdentStr,
  387. (jboolean)status.online);
  388. if(env->ExceptionCheck() || nodeStatusObj == NULL) {
  389. LOGE("Exception creating new NodeStatus");
  390. return NULL;
  391. }
  392. return nodeStatusObj;
  393. }
  394. jobjectArray newPeerArray(JNIEnv *env, const ZT_Peer *peers, size_t count) {
  395. return newArrayObject<ZT_Peer, newPeer>(env, peers, count, Peer_class);
  396. }
  397. jobjectArray newVirtualNetworkConfigArray(JNIEnv *env, const ZT_VirtualNetworkConfig *networks, size_t count) {
  398. return newArrayObject<ZT_VirtualNetworkConfig, newNetworkConfig>(env, networks, count, VirtualNetworkConfig_class);
  399. }
  400. jobjectArray newPeerPhysicalPathArray(JNIEnv *env, const ZT_PeerPhysicalPath *paths, size_t count) {
  401. return newArrayObject<ZT_PeerPhysicalPath, newPeerPhysicalPath>(env, paths, count, PeerPhysicalPath_class);
  402. }
  403. jobjectArray newInetSocketAddressArray(JNIEnv *env, const sockaddr_storage *addresses, size_t count) {
  404. return newArrayObject<sockaddr_storage, newInetSocketAddress>(env, addresses, count, InetSocketAddress_class);
  405. }
  406. jobjectArray newVirtualNetworkRouteArray(JNIEnv *env, const ZT_VirtualNetworkRoute *routes, size_t count) {
  407. return newArrayObject<ZT_VirtualNetworkRoute, newVirtualNetworkRoute>(env, routes, count, VirtualNetworkRoute_class);
  408. }
  409. void newArrayObject_logCount(size_t count) {
  410. LOGE("count > JSIZE_MAX: %zu", count);
  411. }
  412. void newArrayObject_log(const char *msg) {
  413. LOGE("%s", msg);
  414. }
  415. jbyteArray newByteArray(JNIEnv *env, const unsigned char *bytes, size_t count) {
  416. if (count > JSIZE_MAX) {
  417. LOGE("count > JSIZE_MAX: %zu", count);
  418. return NULL;
  419. }
  420. jsize jCount = static_cast<jsize>(count);
  421. const jbyte *jBytes = reinterpret_cast<const jbyte *>(bytes);
  422. jbyteArray byteArrayObj = env->NewByteArray(jCount);
  423. if(byteArrayObj == NULL)
  424. {
  425. LOGE("NewByteArray returned NULL");
  426. return NULL;
  427. }
  428. env->SetByteArrayRegion(byteArrayObj, 0, jCount, jBytes);
  429. if (env->ExceptionCheck()) {
  430. LOGE("Exception when calling SetByteArrayRegion");
  431. return NULL;
  432. }
  433. return byteArrayObj;
  434. }
  435. jbyteArray newByteArray(JNIEnv *env, size_t count) {
  436. if (count > JSIZE_MAX) {
  437. LOGE("count > JSIZE_MAX: %zu", count);
  438. return NULL;
  439. }
  440. jsize jCount = static_cast<jsize>(count);
  441. jbyteArray byteArrayObj = env->NewByteArray(jCount);
  442. if(byteArrayObj == NULL)
  443. {
  444. LOGE("NewByteArray returned NULL");
  445. return NULL;
  446. }
  447. return byteArrayObj;
  448. }
  449. bool isSocketAddressEmpty(const sockaddr_storage addr) {
  450. //
  451. // was:
  452. // struct sockaddr_storage nullAddress = {0};
  453. //
  454. // but was getting this warning:
  455. // warning: suggest braces around initialization of subobject
  456. //
  457. // when building ZeroTierOne
  458. //
  459. sockaddr_storage emptyAddress; //NOLINT
  460. //
  461. // It is possible to assume knowledge about internals of sockaddr_storage and construct
  462. // correct 0-initializer, but it is simpler to just treat sockaddr_storage as opaque and
  463. // use memset here to fill with 0
  464. //
  465. // This is also done in InetAddress.hpp for InetAddress
  466. //
  467. memset(&emptyAddress, 0, sizeof(sockaddr_storage));
  468. return (memcmp(&addr, &emptyAddress, sizeof(sockaddr_storage)) == 0); //NOLINT
  469. }
  470. //
  471. // returns empty sockaddr_storage on error
  472. //
  473. sockaddr_storage fromSocketAddressObject(JNIEnv *env, jobject sockAddressObject) {
  474. sockaddr_storage emptyAddress; //NOLINT
  475. memset(&emptyAddress, 0, sizeof(sockaddr_storage));
  476. jint port = env->CallIntMethod(sockAddressObject, InetSocketAddress_getPort_method);
  477. if(env->ExceptionCheck())
  478. {
  479. LOGE("Exception calling getPort");
  480. return emptyAddress;
  481. }
  482. jobject addressObject = env->CallObjectMethod(sockAddressObject, InetSocketAddress_getAddress_method);
  483. if(env->ExceptionCheck() || addressObject == NULL)
  484. {
  485. LOGE("Exception calling getAddress");
  486. return emptyAddress;
  487. }
  488. jbyteArray addressArrayObj = reinterpret_cast<jbyteArray>(env->CallObjectMethod(addressObject, InetAddress_getAddress_method));
  489. if(env->ExceptionCheck() || addressArrayObj == NULL)
  490. {
  491. LOGE("Exception calling getAddress");
  492. return emptyAddress;
  493. }
  494. sockaddr_storage addr = {};
  495. if (env->IsInstanceOf(addressObject, Inet4Address_class)) {
  496. // IPV4
  497. assert(env->GetArrayLength(addressArrayObj) == 4);
  498. sockaddr_in *addr_4 = reinterpret_cast<sockaddr_in *>(&addr);
  499. addr_4->sin_family = AF_INET;
  500. addr_4->sin_port = htons(port);
  501. void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
  502. memcpy(&addr_4->sin_addr.s_addr, data, 4);
  503. env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
  504. } else if (env->IsInstanceOf(addressObject, Inet6Address_class)) {
  505. // IPV6
  506. assert(env->GetArrayLength(addressArrayObj) == 16);
  507. sockaddr_in6 *addr_6 = reinterpret_cast<sockaddr_in6 *>(&addr);
  508. addr_6->sin6_family = AF_INET6;
  509. addr_6->sin6_port = htons(port);
  510. void *data = env->GetPrimitiveArrayCritical(addressArrayObj, NULL);
  511. memcpy(&addr_6->sin6_addr.s6_addr, data, 16);
  512. env->ReleasePrimitiveArrayCritical(addressArrayObj, data, 0);
  513. } else {
  514. assert(false && "addressObject is neither Inet4Address nor Inet6Address");
  515. }
  516. return addr;
  517. }