ZT_jniutils.cpp 18 KB

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