ZT_jniutils.cpp 18 KB

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