1 /* |
1 /* |
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
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 |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
|
26 #include <sys/poll.h> |
26 #include <sys/types.h> |
27 #include <sys/types.h> |
27 #include <sys/socket.h> |
28 #include <sys/socket.h> |
28 #include <string.h> |
29 #include <string.h> |
29 #include <netinet/in.h> |
30 #include <netinet/in.h> |
30 #include <netinet/tcp.h> |
31 #include <netinet/tcp.h> |
50 #define IP_MULTICAST_ALL 49 |
54 #define IP_MULTICAST_ALL 49 |
51 #endif |
55 #endif |
52 #endif |
56 #endif |
53 |
57 |
54 /** |
58 /** |
55 * IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP may not be defined on OSX |
59 * IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP may not be defined on OSX and AIX |
56 */ |
60 */ |
57 #ifdef __APPLE__ |
61 #if defined(__APPLE__) || defined(_AIX) |
58 #ifndef IPV6_ADD_MEMBERSHIP |
62 #ifndef IPV6_ADD_MEMBERSHIP |
59 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP |
63 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP |
60 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP |
64 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP |
61 #endif |
65 #endif |
62 #endif |
66 #endif |
|
67 |
|
68 #if defined(_AIX) |
|
69 #ifndef IP_BLOCK_SOURCE |
|
70 #define IP_BLOCK_SOURCE 58 /* Block data from a given source to a given group */ |
|
71 #define IP_UNBLOCK_SOURCE 59 /* Unblock data from a given source to a given group */ |
|
72 #define IP_ADD_SOURCE_MEMBERSHIP 60 /* Join a source-specific group */ |
|
73 #define IP_DROP_SOURCE_MEMBERSHIP 61 /* Leave a source-specific group */ |
|
74 #endif |
|
75 |
|
76 #ifndef MCAST_BLOCK_SOURCE |
|
77 #define MCAST_BLOCK_SOURCE 64 |
|
78 #define MCAST_UNBLOCK_SOURCE 65 |
|
79 #define MCAST_JOIN_SOURCE_GROUP 66 |
|
80 #define MCAST_LEAVE_SOURCE_GROUP 67 |
|
81 #endif |
|
82 #endif /* _AIX */ |
63 |
83 |
64 #define COPY_INET6_ADDRESS(env, source, target) \ |
84 #define COPY_INET6_ADDRESS(env, source, target) \ |
65 (*env)->GetByteArrayRegion(env, source, 0, 16, target) |
85 (*env)->GetByteArrayRegion(env, source, 0, 16, target) |
66 |
86 |
67 /* |
87 /* |
84 sin6->sin6_family = AF_INET6; |
104 sin6->sin6_family = AF_INET6; |
85 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr)); |
105 COPY_INET6_ADDRESS(env, source, (jbyte*)&(sin6->sin6_addr)); |
86 } |
106 } |
87 #endif |
107 #endif |
88 |
108 |
|
109 #ifdef _AIX |
|
110 |
|
111 /* |
|
112 * Checks whether or not "socket extensions for multicast source filters" is supported. |
|
113 * Returns JNI_TRUE if it is supported, JNI_FALSE otherwise |
|
114 */ |
|
115 static jboolean isSourceFilterSupported(){ |
|
116 static jboolean alreadyChecked = JNI_FALSE; |
|
117 static jboolean result = JNI_TRUE; |
|
118 if (alreadyChecked != JNI_TRUE){ |
|
119 struct utsname uts; |
|
120 memset(&uts, 0, sizeof(uts)); |
|
121 strcpy(uts.sysname, "?"); |
|
122 const int utsRes = uname(&uts); |
|
123 int major = -1; |
|
124 int minor = -1; |
|
125 major = atoi(uts.version); |
|
126 minor = atoi(uts.release); |
|
127 if (strcmp(uts.sysname, "AIX") == 0) { |
|
128 if (major < 6 || (major == 6 && minor < 1)) {// unsupported on aix < 6.1 |
|
129 result = JNI_FALSE; |
|
130 } |
|
131 } |
|
132 alreadyChecked = JNI_TRUE; |
|
133 } |
|
134 return result; |
|
135 } |
|
136 |
|
137 #endif /* _AIX */ |
|
138 |
89 JNIEXPORT void JNICALL |
139 JNIEXPORT void JNICALL |
90 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
140 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) |
91 { |
141 { |
92 /* Here because Windows native code does need to init IDs */ |
142 /* Here because Windows native code does need to init IDs */ |
93 } |
143 } |
432 mreq.imr_interface.s_addr = htonl(interf); |
482 mreq.imr_interface.s_addr = htonl(interf); |
433 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; |
483 opt = (join) ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; |
434 optval = (void*)&mreq; |
484 optval = (void*)&mreq; |
435 optlen = sizeof(mreq); |
485 optlen = sizeof(mreq); |
436 } else { |
486 } else { |
|
487 |
|
488 #ifdef _AIX |
|
489 /* check AIX for support of source filtering */ |
|
490 if (isSourceFilterSupported() != JNI_TRUE){ |
|
491 return IOS_UNAVAILABLE; |
|
492 } |
|
493 #endif |
|
494 |
437 mreq_source.imr_multiaddr.s_addr = htonl(group); |
495 mreq_source.imr_multiaddr.s_addr = htonl(group); |
438 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
496 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
439 mreq_source.imr_interface.s_addr = htonl(interf); |
497 mreq_source.imr_interface.s_addr = htonl(interf); |
440 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP; |
498 opt = (join) ? IP_ADD_SOURCE_MEMBERSHIP : IP_DROP_SOURCE_MEMBERSHIP; |
441 optval = (void*)&mreq_source; |
499 optval = (void*)&mreq_source; |
442 optlen = sizeof(mreq_source); |
500 optlen = sizeof(mreq_source); |
443 } |
501 } |
444 |
502 |
445 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen); |
503 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, optval, optlen); |
446 if (n < 0) { |
504 if (n < 0) { |
447 if (join && (errno == ENOPROTOOPT)) |
505 if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP)) |
448 return IOS_UNAVAILABLE; |
506 return IOS_UNAVAILABLE; |
449 handleSocketError(env, errno); |
507 handleSocketError(env, errno); |
450 } |
508 } |
451 return 0; |
509 return 0; |
452 } |
510 } |
461 #else |
519 #else |
462 struct ip_mreq_source mreq_source; |
520 struct ip_mreq_source mreq_source; |
463 int n; |
521 int n; |
464 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE; |
522 int opt = (block) ? IP_BLOCK_SOURCE : IP_UNBLOCK_SOURCE; |
465 |
523 |
|
524 #ifdef _AIX |
|
525 /* check AIX for support of source filtering */ |
|
526 if (isSourceFilterSupported() != JNI_TRUE){ |
|
527 return IOS_UNAVAILABLE; |
|
528 } |
|
529 #endif |
|
530 |
466 mreq_source.imr_multiaddr.s_addr = htonl(group); |
531 mreq_source.imr_multiaddr.s_addr = htonl(group); |
467 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
532 mreq_source.imr_sourceaddr.s_addr = htonl(source); |
468 mreq_source.imr_interface.s_addr = htonl(interf); |
533 mreq_source.imr_interface.s_addr = htonl(interf); |
469 |
534 |
470 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, |
535 n = setsockopt(fdval(env,fdo), IPPROTO_IP, opt, |
471 (void*)&mreq_source, sizeof(mreq_source)); |
536 (void*)&mreq_source, sizeof(mreq_source)); |
472 if (n < 0) { |
537 if (n < 0) { |
473 if (block && (errno == ENOPROTOOPT)) |
538 if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP)) |
474 return IOS_UNAVAILABLE; |
539 return IOS_UNAVAILABLE; |
475 handleSocketError(env, errno); |
540 handleSocketError(env, errno); |
476 } |
541 } |
477 return 0; |
542 return 0; |
478 #endif |
543 #endif |
506 #endif |
571 #endif |
507 } |
572 } |
508 |
573 |
509 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen); |
574 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, optval, optlen); |
510 if (n < 0) { |
575 if (n < 0) { |
511 if (join && (errno == ENOPROTOOPT)) |
576 if (join && (errno == ENOPROTOOPT || errno == EOPNOTSUPP)) |
512 return IOS_UNAVAILABLE; |
577 return IOS_UNAVAILABLE; |
513 handleSocketError(env, errno); |
578 handleSocketError(env, errno); |
514 } |
579 } |
515 return 0; |
580 return 0; |
516 #else |
581 #else |
535 initGroupSourceReq(env, group, index, source, &req); |
600 initGroupSourceReq(env, group, index, source, &req); |
536 |
601 |
537 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, |
602 n = setsockopt(fdval(env,fdo), IPPROTO_IPV6, opt, |
538 (void*)&req, sizeof(req)); |
603 (void*)&req, sizeof(req)); |
539 if (n < 0) { |
604 if (n < 0) { |
540 if (block && (errno == ENOPROTOOPT)) |
605 if (block && (errno == ENOPROTOOPT || errno == EOPNOTSUPP)) |
541 return IOS_UNAVAILABLE; |
606 return IOS_UNAVAILABLE; |
542 handleSocketError(env, errno); |
607 handleSocketError(env, errno); |
543 } |
608 } |
544 return 0; |
609 return 0; |
545 #endif |
610 #endif |
633 return IOS_INTERRUPTED; |
698 return IOS_INTERRUPTED; |
634 } else { |
699 } else { |
635 handleSocketError(env, errno); |
700 handleSocketError(env, errno); |
636 return IOS_THROWN; |
701 return IOS_THROWN; |
637 } |
702 } |
|
703 } |
|
704 |
|
705 JNIEXPORT jshort JNICALL |
|
706 Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this) |
|
707 { |
|
708 return (jshort)POLLIN; |
|
709 } |
|
710 |
|
711 JNIEXPORT jshort JNICALL |
|
712 Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this) |
|
713 { |
|
714 return (jshort)POLLOUT; |
|
715 } |
|
716 |
|
717 JNIEXPORT jshort JNICALL |
|
718 Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this) |
|
719 { |
|
720 return (jshort)POLLERR; |
|
721 } |
|
722 |
|
723 JNIEXPORT jshort JNICALL |
|
724 Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this) |
|
725 { |
|
726 return (jshort)POLLHUP; |
|
727 } |
|
728 |
|
729 JNIEXPORT jshort JNICALL |
|
730 Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this) |
|
731 { |
|
732 return (jshort)POLLNVAL; |
|
733 } |
|
734 |
|
735 JNIEXPORT jshort JNICALL |
|
736 Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this) |
|
737 { |
|
738 return (jshort)POLLOUT; |
638 } |
739 } |
639 |
740 |
640 |
741 |
641 /* Declared in nio_util.h */ |
742 /* Declared in nio_util.h */ |
642 |
743 |