131 strcpy(uts.sysname, "?");
132 const int utsRes = uname(&uts);
133 int major = -1;
134 int minor = -1;
135 major = atoi(uts.version);
136 minor = atoi(uts.release);
137 if (strcmp(uts.sysname, "AIX") == 0) {
138 if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1
139 result = JNI_FALSE;
140 }
141 }
142 alreadyChecked = JNI_TRUE;
143 }
144 return result;
145 }
146
147 #endif /* _AIX */
148
149 static jclass isa_class; /* java.net.InetSocketAddress */
150 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
151
152 JNIEXPORT void JNICALL
153 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
154 {
155 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
156 CHECK_NULL(cls);
157 isa_class = (*env)->NewGlobalRef(env, cls);
158 if (isa_class == NULL) {
159 JNU_ThrowOutOfMemoryError(env, NULL);
160 return;
161 }
162 isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
163 CHECK_NULL(isa_ctorID);
164
165 initInetAddressIDs(env);
166 }
167
168 JNIEXPORT jboolean JNICALL
169 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
170 {
171 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
172 }
173
174 JNIEXPORT jboolean JNICALL
175 Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1)
176 {
177 return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
178 }
179
180 JNIEXPORT jint JNICALL
181 Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
182 return -1;
183 }
184
256 return -1;
257 }
258 }
259
260 /* By default, Linux uses the route default */
261 if (domain == AF_INET6 && type == SOCK_DGRAM) {
262 int arg = 1;
263 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
264 sizeof(arg)) < 0) {
265 JNU_ThrowByNameWithLastError(env,
266 JNU_JAVANETPKG "SocketException",
267 "Unable to set IPV6_MULTICAST_HOPS");
268 close(fd);
269 return -1;
270 }
271 }
272 #endif
273 return fd;
274 }
275
276 JNIEXPORT void JNICALL
277 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6,
278 jboolean useExclBind, jobject iao, int port)
279 {
280 SOCKETADDRESS sa;
281 int sa_len = 0;
282 int rv = 0;
283
284 if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
285 preferIPv6) != 0) {
286 return;
287 }
288
289 rv = NET_Bind(fdval(env, fdo), &sa, sa_len);
290 if (rv != 0) {
291 handleSocketError(env, errno);
292 }
293 }
294
295 JNIEXPORT void JNICALL
296 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
297 {
298 if (listen(fdval(env, fdo), backlog) < 0)
299 handleSocketError(env, errno);
300 }
301
302 JNIEXPORT jint JNICALL
303 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
304 jobject fdo, jobject iao, jint port)
305 {
306 SOCKETADDRESS sa;
307 int sa_len = 0;
308 int rv;
309
310 if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
311 return IOS_THROWN;
312 }
313
314 rv = connect(fdval(env, fdo), &sa.sa, sa_len);
315 if (rv != 0) {
316 if (errno == EINPROGRESS) {
317 return IOS_UNAVAILABLE;
318 } else if (errno == EINTR) {
319 return IOS_INTERRUPTED;
320 }
321 return handleSocketError(env, errno);
322 }
323 return 1;
324 }
325
326 JNIEXPORT jint JNICALL
327 Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
328 jobjectArray isaa)
329 {
330 jint fd = fdval(env, fdo);
331 jint newfd;
332 SOCKETADDRESS sa;
333 socklen_t sa_len = sizeof(SOCKETADDRESS);
334 jobject remote_ia;
335 jint remote_port = 0;
336 jobject isa;
337
338 /* accept connection but ignore ECONNABORTED */
339 for (;;) {
340 newfd = accept(fd, &sa.sa, &sa_len);
341 if (newfd >= 0) {
342 break;
343 }
344 if (errno != ECONNABORTED) {
345 break;
346 }
347 /* ECONNABORTED => restart accept */
348 }
349
350 if (newfd < 0) {
351 if (errno == EAGAIN || errno == EWOULDBLOCK)
352 return IOS_UNAVAILABLE;
353 if (errno == EINTR)
354 return IOS_INTERRUPTED;
355 JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
356 return IOS_THROWN;
357 }
358
359 setfdval(env, newfdo, newfd);
360
361 remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
362 CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
363
364 isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
365 CHECK_NULL_RETURN(isa, IOS_THROWN);
366 (*env)->SetObjectArrayElement(env, isaa, 0, isa);
367
368 return 1;
369 }
370
371 JNIEXPORT jint JNICALL
372 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
373 {
374 SOCKETADDRESS sa;
375 socklen_t sa_len = sizeof(SOCKETADDRESS);
376 if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
377 #ifdef _ALLBSD_SOURCE
378 /*
379 * XXXBSD:
380 * ECONNRESET is specific to the BSDs. We can not return an error,
381 * as the calling Java code with raise a java.lang.Error given the expectation
382 * that getsockname() will never fail. According to the Single UNIX Specification,
383 * it shouldn't fail. As such, we just fill in generic Linux-compatible values.
384 */
385 if (errno == ECONNRESET) {
386 bzero(&sa.sa4, sizeof(sa));
387 sa.sa4.sin_len = sizeof(struct sockaddr_in);
388 sa.sa4.sin_family = AF_INET;
414 * as the calling Java code with raise a java.lang.Error with the expectation
415 * that getsockname() will never fail. According to the Single UNIX Specification,
416 * it shouldn't fail. As such, we just fill in generic Linux-compatible values.
417 */
418 if (errno == ECONNRESET) {
419 bzero(&sa.sa4, sizeof(sa));
420 sa.sa4.sin_len = sizeof(struct sockaddr_in);
421 sa.sa4.sin_family = AF_INET;
422 sa.sa4.sin_port = htonl(0);
423 sa.sa4.sin_addr.s_addr = INADDR_ANY;
424 } else {
425 handleSocketError(env, errno);
426 return NULL;
427 }
428 #else /* _ALLBSD_SOURCE */
429 handleSocketError(env, errno);
430 return NULL;
431 #endif /* _ALLBSD_SOURCE */
432 }
433 return NET_SockaddrToInetAddress(env, &sa, &port);
434 }
435
436 JNIEXPORT jint JNICALL
437 Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
438 {
439 SOCKETADDRESS sa;
440 socklen_t sa_len = sizeof(sa);
441
442 if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
443 handleSocketError(env, errno);
444 return IOS_THROWN;
445 }
446 return NET_GetPortFromSockaddr(&sa);
447 }
448
449 JNIEXPORT jobject JNICALL
450 Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
451 {
452 SOCKETADDRESS sa;
453 socklen_t sa_len = sizeof(sa);
|
131 strcpy(uts.sysname, "?");
132 const int utsRes = uname(&uts);
133 int major = -1;
134 int minor = -1;
135 major = atoi(uts.version);
136 minor = atoi(uts.release);
137 if (strcmp(uts.sysname, "AIX") == 0) {
138 if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1
139 result = JNI_FALSE;
140 }
141 }
142 alreadyChecked = JNI_TRUE;
143 }
144 return result;
145 }
146
147 #endif /* _AIX */
148
149 static jclass isa_class; /* java.net.InetSocketAddress */
150 static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
151 static jclass usa_class; /* java.net.UnixSocketAddress */
152 static jmethodID usa_ctor; /* UnixSocketAddress() */
153 static jmethodID usa_ctorBytes; /* UnixSocketAddress(byte[]) */
154
155 JNIEXPORT void JNICALL
156 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
157 {
158 jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
159 CHECK_NULL(cls);
160 isa_class = (*env)->NewGlobalRef(env, cls);
161 if (isa_class == NULL) {
162 JNU_ThrowOutOfMemoryError(env, NULL);
163 return;
164 }
165 isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
166 CHECK_NULL(isa_ctorID);
167
168 cls = (*env)->FindClass(env, "java/net/UnixSocketAddress");
169 CHECK_NULL(cls);
170 usa_class = (*env)->NewGlobalRef(env, cls);
171 if (usa_class == NULL) {
172 JNU_ThrowOutOfMemoryError(env, NULL);
173 return;
174 }
175 usa_ctor = (*env)->GetMethodID(env, cls, "<init>", "()V");
176 CHECK_NULL(usa_ctor);
177 usa_ctorBytes = (*env)->GetMethodID(env, cls, "<init>", "([B)V");
178 CHECK_NULL(usa_ctorBytes);
179
180 initInetAddressIDs(env);
181 }
182
183 JNIEXPORT jboolean JNICALL
184 Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
185 {
186 return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
187 }
188
189 JNIEXPORT jboolean JNICALL
190 Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1)
191 {
192 return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
193 }
194
195 JNIEXPORT jint JNICALL
196 Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
197 return -1;
198 }
199
271 return -1;
272 }
273 }
274
275 /* By default, Linux uses the route default */
276 if (domain == AF_INET6 && type == SOCK_DGRAM) {
277 int arg = 1;
278 if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
279 sizeof(arg)) < 0) {
280 JNU_ThrowByNameWithLastError(env,
281 JNU_JAVANETPKG "SocketException",
282 "Unable to set IPV6_MULTICAST_HOPS");
283 close(fd);
284 return -1;
285 }
286 }
287 #endif
288 return fd;
289 }
290
291 JNIEXPORT jint JNICALL
292 Java_sun_nio_ch_Net_socket1 (JNIEnv *env, jclass clazz, jboolean stream)
293 {
294 int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
295 int fd = socket(AF_UNIX, type, 0);
296 if (fd < 0) {
297 return handleSocketError(env, errno);
298 }
299 return fd;
300 }
301
302 JNIEXPORT void JNICALL
303 Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, jobject fdo, jboolean preferIPv6,
304 jboolean useExclBind, jobject iao, int port)
305 {
306 SOCKETADDRESS sa;
307 int sa_len = 0;
308 int rv = 0;
309
310 if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
311 preferIPv6) != 0) {
312 return;
313 }
314
315 rv = NET_Bind(fdval(env, fdo), &sa, sa_len);
316 if (rv != 0) {
317 handleSocketError(env, errno);
318 }
319 }
320
321 JNIEXPORT void JNICALL
322 Java_sun_nio_ch_Net_bind1(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray uao)
323 {
324 SOCKETADDRESS sa;
325 memset(&sa, 0x00, sizeof (sa));
326 sa.sau.sun_family = AF_UNIX;
327 size_t uao_len = (* env) -> GetArrayLength(env, uao);
328 size_t sa_len = sizeof (sa.sau.sun_path);
329 if (uao_len > sa_len) {
330 // TODO: throw propper exception
331 return;
332 }
333 (* env) -> GetByteArrayRegion(env, uao, 0, uao_len, (jbyte *) sa.sau.sun_path);
334 int rv = bind(fdval(env, fdo), &sa.sa, sa_len);
335 if (rv != 0) {
336 handleSocketError(env, errno);
337 }
338 }
339
340 JNIEXPORT void JNICALL
341 Java_sun_nio_ch_Net_listen(JNIEnv *env, jclass cl, jobject fdo, jint backlog)
342 {
343 if (listen(fdval(env, fdo), backlog) < 0)
344 handleSocketError(env, errno);
345 }
346
347 JNIEXPORT jint JNICALL
348 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
349 jobject fdo, jobject iao, jint port)
350 {
351 SOCKETADDRESS sa;
352 int sa_len = 0;
353 int rv;
354
355 if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
356 return IOS_THROWN;
357 }
358
359 rv = connect(fdval(env, fdo), &sa.sa, sa_len);
360 if (rv != 0) {
361 if (errno == EINPROGRESS) {
362 return IOS_UNAVAILABLE;
363 } else if (errno == EINTR) {
364 return IOS_INTERRUPTED;
365 }
366 return handleSocketError(env, errno);
367 }
368 return 1;
369 }
370
371 JNIEXPORT jint JNICALL
372 Java_sun_nio_ch_Net_connect1(JNIEnv *env, jclass clazz, jobject fdo, jbyteArray uao)
373 {
374 SOCKETADDRESS sa;
375 memset(&sa, 0x00, sizeof (sa));
376 sa.sau.sun_family = AF_UNIX;
377 size_t uao_len = (* env) -> GetArrayLength(env, uao);
378 size_t sa_len = sizeof (sa.sau.sun_path);
379 if (uao_len > sa_len) {
380 // TODO: throw propper exception
381 return IOS_UNAVAILABLE;
382 }
383 (* env) -> GetByteArrayRegion(env, uao, 0, uao_len, (jbyte *) sa.sau.sun_path);
384
385 // TODO: refactoring, common method
386 int rv = connect(fdval(env, fdo), &sa.sa, sa_len);
387 if (rv != 0) {
388 if (errno == EINPROGRESS) {
389 return IOS_UNAVAILABLE;
390 } else if (errno == EINTR) {
391 return IOS_INTERRUPTED;
392 }
393 return handleSocketError(env, errno);
394 }
395 return 1;
396 }
397
398 JNIEXPORT jint JNICALL
399 Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
400 jobjectArray isaa)
401 {
402 jint fd = fdval(env, fdo);
403 jint newfd;
404 SOCKETADDRESS sa;
405 socklen_t sa_len = sizeof(SOCKETADDRESS);
406 jobject remote_ia;
407 jint remote_port = 0;
408 jobject isa;
409
410 /* accept connection but ignore ECONNABORTED */
411 for (;;) {
412 newfd = accept(fd, &sa.sa, &sa_len);
413 if (newfd >= 0) {
414 break;
415 }
416 if (errno != ECONNABORTED) {
417 break;
418 }
419 /* ECONNABORTED => restart accept */
420 }
421
422 if (newfd < 0) {
423 if (errno == EAGAIN || errno == EWOULDBLOCK)
424 return IOS_UNAVAILABLE;
425 if (errno == EINTR)
426 return IOS_INTERRUPTED;
427 JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
428 return IOS_THROWN;
429 }
430
431 setfdval(env, newfdo, newfd);
432
433 if (sa.sa.sa_family == AF_INET || sa.sa.sa_family == AF_INET6) {
434 remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
435 CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
436
437 isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
438 CHECK_NULL_RETURN(isa, IOS_THROWN);
439 (*env)->SetObjectArrayElement(env, isaa, 0, isa);
440
441 return 1;
442 } else if (sa.sa.sa_family == AF_UNIX) {
443 isa = (*env)->NewObject(env, usa_class, usa_ctor);
444 CHECK_NULL_RETURN(isa, IOS_THROWN);
445 (*env)->SetObjectArrayElement(env, isaa, 0, isa);
446 return 1;
447 } else {
448 return -6; // UNSUPPORTED_CASE
449 }
450 }
451
452 JNIEXPORT jint JNICALL
453 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
454 {
455 SOCKETADDRESS sa;
456 socklen_t sa_len = sizeof(SOCKETADDRESS);
457 if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
458 #ifdef _ALLBSD_SOURCE
459 /*
460 * XXXBSD:
461 * ECONNRESET is specific to the BSDs. We can not return an error,
462 * as the calling Java code with raise a java.lang.Error given the expectation
463 * that getsockname() will never fail. According to the Single UNIX Specification,
464 * it shouldn't fail. As such, we just fill in generic Linux-compatible values.
465 */
466 if (errno == ECONNRESET) {
467 bzero(&sa.sa4, sizeof(sa));
468 sa.sa4.sin_len = sizeof(struct sockaddr_in);
469 sa.sa4.sin_family = AF_INET;
495 * as the calling Java code with raise a java.lang.Error with the expectation
496 * that getsockname() will never fail. According to the Single UNIX Specification,
497 * it shouldn't fail. As such, we just fill in generic Linux-compatible values.
498 */
499 if (errno == ECONNRESET) {
500 bzero(&sa.sa4, sizeof(sa));
501 sa.sa4.sin_len = sizeof(struct sockaddr_in);
502 sa.sa4.sin_family = AF_INET;
503 sa.sa4.sin_port = htonl(0);
504 sa.sa4.sin_addr.s_addr = INADDR_ANY;
505 } else {
506 handleSocketError(env, errno);
507 return NULL;
508 }
509 #else /* _ALLBSD_SOURCE */
510 handleSocketError(env, errno);
511 return NULL;
512 #endif /* _ALLBSD_SOURCE */
513 }
514 return NET_SockaddrToInetAddress(env, &sa, &port);
515 }
516
517 JNIEXPORT jobject JNICALL
518 Java_sun_nio_ch_Net_localSocketAddress(JNIEnv *env, jclass clazz, jobject fdo)
519 {
520 SOCKETADDRESS sa;
521 socklen_t sa_len = sizeof (SOCKETADDRESS);
522 memset(&sa, 0x00, sa_len);
523 if (getsockname(fdval(env, fdo), &sa.sa, &sa_len) != 0) {
524 return NULL; // TODO: exception?
525 }
526
527 if (sa.sa.sa_family == AF_UNIX) {
528 jbyteArray addr = (*env)->NewByteArray(env, sizeof(sa.sau.sun_path));
529 (*env)->SetByteArrayRegion(env, addr, 0, sizeof(sa.sau.sun_path), (jbyte *) sa.sau.sun_path);
530 return (*env)->NewObject(env, usa_class, usa_ctorBytes, addr);
531 } else if (sa.sa.sa_family == AF_INET || sa.sa.sa_family == AF_INET6) {
532 jobject address = Java_sun_nio_ch_Net_localInetAddress(env, clazz, fdo);
533 jint port = Java_sun_nio_ch_Net_localPort(env, clazz, fdo);
534 return (*env)->NewObject(env, isa_class, isa_ctorID, address, port);
535 } else {
536 return NULL; // TODO: exception?
537 }
538 }
539
540 JNIEXPORT jint JNICALL
541 Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
542 {
543 SOCKETADDRESS sa;
544 socklen_t sa_len = sizeof(sa);
545
546 if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
547 handleSocketError(env, errno);
548 return IOS_THROWN;
549 }
550 return NET_GetPortFromSockaddr(&sa);
551 }
552
553 JNIEXPORT jobject JNICALL
554 Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
555 {
556 SOCKETADDRESS sa;
557 socklen_t sa_len = sizeof(sa);
|