ZT_jniutils.cpp 18 KB

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