ZT_jniutils.cpp 16 KB

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