1 /*
2 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include <malloc.h>
26
27 #include "net_util.h"
28
29 #include "java_net_InetAddress.h"
30 #include "java_net_Inet4AddressImpl.h"
31 #include "java_net_Inet6AddressImpl.h"
32
33 /*
34 * Inet6AddressImpl
35 */
36
37 /*
38 * Class: java_net_Inet6AddressImpl
39 * Method: getLocalHostName
40 * Signature: ()Ljava/lang/String;
41 */
42 JNIEXPORT jstring JNICALL
43 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
44 char hostname[256];
45
46 if (gethostname(hostname, sizeof(hostname)) == -1) {
47 strcpy(hostname, "localhost");
48 }
49 return JNU_NewStringPlatform(env, hostname);
50 }
51
52 /*
53 * Class: java_net_Inet6AddressImpl
54 * Method: lookupAllHostAddr
55 * Signature: (Ljava/lang/String;)[[B
56 */
57 JNIEXPORT jobjectArray JNICALL
58 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
59 jstring host) {
60 jobjectArray ret = NULL;
61 const char *hostname;
62 int error = 0;
63 struct addrinfo hints, *res = NULL, *resNew = NULL, *last = NULL,
64 *iterator;
65
66 initInetAddressIDs(env);
67 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
68
69 if (IS_NULL(host)) {
70 JNU_ThrowNullPointerException(env, "host argument is null");
71 return NULL;
72 }
73 hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
74 CHECK_NULL_RETURN(hostname, NULL);
75
76 // try once, with our static buffer
77 memset(&hints, 0, sizeof(hints));
78 hints.ai_flags = AI_CANONNAME;
79 hints.ai_family = AF_UNSPEC;
80
81 error = getaddrinfo(hostname, NULL, &hints, &res);
82
83 if (error) {
84 // report error
85 NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException",
86 hostname);
87 goto cleanupAndReturn;
88 } else {
89 int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
90 inet6Index = 0, originalIndex = 0;
91 int addressPreference =
92 (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
93 iterator = res;
94 while (iterator != NULL) {
95 // skip duplicates
96 int skip = 0;
97 struct addrinfo *iteratorNew = resNew;
98 while (iteratorNew != NULL) {
99 if (iterator->ai_family == iteratorNew->ai_family &&
100 iterator->ai_addrlen == iteratorNew->ai_addrlen) {
101 if (iteratorNew->ai_family == AF_INET) { /* AF_INET */
102 struct sockaddr_in *addr1, *addr2;
103 addr1 = (struct sockaddr_in *)iterator->ai_addr;
104 addr2 = (struct sockaddr_in *)iteratorNew->ai_addr;
105 if (addr1->sin_addr.s_addr == addr2->sin_addr.s_addr) {
106 skip = 1;
107 break;
108 }
109 } else {
110 int t;
111 struct sockaddr_in6 *addr1, *addr2;
112 addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
151 last->ai_next = next;
152 }
153 last = next;
154 i++;
155 if (iterator->ai_family == AF_INET) {
156 inetCount++;
157 } else if (iterator->ai_family == AF_INET6) {
158 inet6Count++;
159 }
160 }
161 iterator = iterator->ai_next;
162 }
163
164 // allocate array - at this point i contains the number of addresses
165 ret = (*env)->NewObjectArray(env, i, ia_class, NULL);
166 if (IS_NULL(ret)) {
167 /* we may have memory to free at the end of this */
168 goto cleanupAndReturn;
169 }
170
171 if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
172 inetIndex = inet6Count;
173 inet6Index = 0;
174 } else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
175 inetIndex = 0;
176 inet6Index = inetCount;
177 } else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
178 inetIndex = inet6Index = originalIndex = 0;
179 }
180
181 iterator = resNew;
182 while (iterator != NULL) {
183 if (iterator->ai_family == AF_INET) {
184 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
185 if (IS_NULL(iaObj)) {
186 ret = NULL;
187 goto cleanupAndReturn;
188 }
189 setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
190 if ((*env)->ExceptionCheck(env))
191 goto cleanupAndReturn;
192 setInetAddress_hostName(env, iaObj, host);
193 if ((*env)->ExceptionCheck(env))
194 goto cleanupAndReturn;
195 (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
196 inetIndex++;
197 } else if (iterator->ai_family == AF_INET6) {
200 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
201 if (IS_NULL(iaObj)) {
202 ret = NULL;
203 goto cleanupAndReturn;
204 }
205 ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
206 if (ret1 == JNI_FALSE) {
207 ret = NULL;
208 goto cleanupAndReturn;
209 }
210 scope = ((struct sockaddr_in6 *)iterator->ai_addr)->sin6_scope_id;
211 if (scope != 0) { // zero is default value, no need to set
212 setInet6Address_scopeid(env, iaObj, scope);
213 }
214 setInetAddress_hostName(env, iaObj, host);
215 if ((*env)->ExceptionCheck(env))
216 goto cleanupAndReturn;
217 (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
218 inet6Index++;
219 }
220 if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
221 originalIndex++;
222 inetIndex = inet6Index = 0;
223 }
224 iterator = iterator->ai_next;
225 }
226 }
227 cleanupAndReturn:
228 JNU_ReleaseStringPlatformChars(env, host, hostname);
229 while (resNew != NULL) {
230 last = resNew;
231 resNew = resNew->ai_next;
232 free(last);
233 }
234 if (res != NULL) {
235 freeaddrinfo(res);
236 }
237 return ret;
238 }
239
240 /*
|
1 /*
2 * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include <malloc.h>
26
27 #include "net_util.h"
28
29 #include "java_net_InetAddress.h"
30 #include "java_net_Inet4AddressImpl.h"
31 #include "java_net_Inet6AddressImpl.h"
32 #include "java_net_spi_InetAddressResolver_LookupPolicy.h"
33
34 /*
35 * Inet6AddressImpl
36 */
37
38 /*
39 * Class: java_net_Inet6AddressImpl
40 * Method: getLocalHostName
41 * Signature: ()Ljava/lang/String;
42 */
43 JNIEXPORT jstring JNICALL
44 Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
45 char hostname[256];
46
47 if (gethostname(hostname, sizeof(hostname)) == -1) {
48 strcpy(hostname, "localhost");
49 }
50 return JNU_NewStringPlatform(env, hostname);
51 }
52
53 /*
54 * Class: java_net_Inet6AddressImpl
55 * Method: lookupAllHostAddr
56 * Signature: (Ljava/lang/String;)[[B
57 */
58 JNIEXPORT jobjectArray JNICALL
59 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
60 jstring host, jint characteristics) {
61 jobjectArray ret = NULL;
62 const char *hostname;
63 int error = 0;
64 struct addrinfo hints, *res = NULL, *resNew = NULL, *last = NULL,
65 *iterator;
66
67 initInetAddressIDs(env);
68 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
69
70 if (IS_NULL(host)) {
71 JNU_ThrowNullPointerException(env, "host argument is null");
72 return NULL;
73 }
74 hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
75 CHECK_NULL_RETURN(hostname, NULL);
76
77 // try once, with our static buffer
78 memset(&hints, 0, sizeof(hints));
79 hints.ai_flags = AI_CANONNAME;
80 hints.ai_family = lookupCharacteristicsToAddressFamily(characteristics);
81
82 error = getaddrinfo(hostname, NULL, &hints, &res);
83
84 if (error) {
85 // report error
86 NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException",
87 hostname);
88 goto cleanupAndReturn;
89 } else {
90 int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,
91 inet6Index = 0, originalIndex = 0;
92 iterator = res;
93 while (iterator != NULL) {
94 // skip duplicates
95 int skip = 0;
96 struct addrinfo *iteratorNew = resNew;
97 while (iteratorNew != NULL) {
98 if (iterator->ai_family == iteratorNew->ai_family &&
99 iterator->ai_addrlen == iteratorNew->ai_addrlen) {
100 if (iteratorNew->ai_family == AF_INET) { /* AF_INET */
101 struct sockaddr_in *addr1, *addr2;
102 addr1 = (struct sockaddr_in *)iterator->ai_addr;
103 addr2 = (struct sockaddr_in *)iteratorNew->ai_addr;
104 if (addr1->sin_addr.s_addr == addr2->sin_addr.s_addr) {
105 skip = 1;
106 break;
107 }
108 } else {
109 int t;
110 struct sockaddr_in6 *addr1, *addr2;
111 addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
150 last->ai_next = next;
151 }
152 last = next;
153 i++;
154 if (iterator->ai_family == AF_INET) {
155 inetCount++;
156 } else if (iterator->ai_family == AF_INET6) {
157 inet6Count++;
158 }
159 }
160 iterator = iterator->ai_next;
161 }
162
163 // allocate array - at this point i contains the number of addresses
164 ret = (*env)->NewObjectArray(env, i, ia_class, NULL);
165 if (IS_NULL(ret)) {
166 /* we may have memory to free at the end of this */
167 goto cleanupAndReturn;
168 }
169
170 if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV6_FIRST) != 0) {
171 inetIndex = inet6Count;
172 inet6Index = 0;
173 } else if ((characteristics & java_net_spi_InetAddressResolver_LookupPolicy_IPV4_FIRST) != 0) {
174 inetIndex = 0;
175 inet6Index = inetCount;
176 } else {
177 inetIndex = inet6Index = originalIndex = 0;
178 }
179
180 iterator = resNew;
181 while (iterator != NULL) {
182 if (iterator->ai_family == AF_INET) {
183 jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
184 if (IS_NULL(iaObj)) {
185 ret = NULL;
186 goto cleanupAndReturn;
187 }
188 setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
189 if ((*env)->ExceptionCheck(env))
190 goto cleanupAndReturn;
191 setInetAddress_hostName(env, iaObj, host);
192 if ((*env)->ExceptionCheck(env))
193 goto cleanupAndReturn;
194 (*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
195 inetIndex++;
196 } else if (iterator->ai_family == AF_INET6) {
199 jobject iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
200 if (IS_NULL(iaObj)) {
201 ret = NULL;
202 goto cleanupAndReturn;
203 }
204 ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
205 if (ret1 == JNI_FALSE) {
206 ret = NULL;
207 goto cleanupAndReturn;
208 }
209 scope = ((struct sockaddr_in6 *)iterator->ai_addr)->sin6_scope_id;
210 if (scope != 0) { // zero is default value, no need to set
211 setInet6Address_scopeid(env, iaObj, scope);
212 }
213 setInetAddress_hostName(env, iaObj, host);
214 if ((*env)->ExceptionCheck(env))
215 goto cleanupAndReturn;
216 (*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
217 inet6Index++;
218 }
219 // Check if addresses are requested to be returned in SYSTEM order
220 if (addressesInSystemOrder(characteristics)) {
221 originalIndex++;
222 inetIndex = inet6Index = 0;
223 }
224 iterator = iterator->ai_next;
225 }
226 }
227 cleanupAndReturn:
228 JNU_ReleaseStringPlatformChars(env, host, hostname);
229 while (resNew != NULL) {
230 last = resNew;
231 resNew = resNew->ai_next;
232 free(last);
233 }
234 if (res != NULL) {
235 freeaddrinfo(res);
236 }
237 return ret;
238 }
239
240 /*
|