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 <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29
30 #if defined(__solaris__)
31 #include <sys/filio.h>
32 #endif
33
34 #include "net_util.h"
35
36 #include "java_net_PlainDatagramSocketImpl.h"
37 #include "java_net_InetAddress.h"
38 #include "java_net_NetworkInterface.h"
39 #include "java_net_SocketOptions.h"
40
41 #ifdef __linux__
42 #define IPV6_MULTICAST_IF 17
43 #ifndef SO_BSDCOMPAT
44 #define SO_BSDCOMPAT 14
45 #endif
46 /**
47 * IP_MULTICAST_ALL has been supported since kernel version 2.6.31
48 * but we may be building on a machine that is older than that.
49 */
50 #ifndef IP_MULTICAST_ALL
51 #define IP_MULTICAST_ALL 49
52 #endif
53 #endif // __linux__
54
55 #ifdef __solaris__
56 #ifndef BSD_COMP
57 #define BSD_COMP
58 #endif
59 #endif
60
61 #ifndef IPTOS_TOS_MASK
62 #define IPTOS_TOS_MASK 0x1e
63 #endif
64 #ifndef IPTOS_PREC_MASK
65 #define IPTOS_PREC_MASK 0xe0
66 #endif
67
68 /************************************************************************
69 * PlainDatagramSocketImpl
70 */
71
72 static jfieldID IO_fd_fdID;
73
74 static jfieldID pdsi_fdID;
75 static jfieldID pdsi_timeoutID;
76 static jfieldID pdsi_trafficClassID;
77 static jfieldID pdsi_localPortID;
78 static jfieldID pdsi_connected;
79 static jfieldID pdsi_connectedAddress;
80 static jfieldID pdsi_connectedPort;
481 if (ret == 0) {
482 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
483 "Peek timed out");
484 return ret;
485 } else if (ret == -1) {
486 if (errno == EBADF) {
487 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
488 } else if (errno == ENOMEM) {
489 JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
490 } else {
491 JNU_ThrowByNameWithMessageAndLastError
492 (env, JNU_JAVANETPKG "SocketException", "Peek failed");
493 }
494 return ret;
495 }
496 }
497
498 n = NET_RecvFrom(fd, buf, 1, MSG_PEEK, &rmtaddr.sa, &slen);
499
500 if (n == -1) {
501
502 #ifdef __solaris__
503 if (errno == ECONNREFUSED) {
504 int orig_errno = errno;
505 recv(fd, buf, 1, 0);
506 errno = orig_errno;
507 }
508 #endif
509 if (errno == ECONNREFUSED) {
510 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
511 "ICMP Port Unreachable");
512 } else {
513 if (errno == EBADF) {
514 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
515 } else {
516 JNU_ThrowByNameWithMessageAndLastError
517 (env, JNU_JAVANETPKG "SocketException", "Peek failed");
518 }
519 }
520 return 0;
521 }
522
523 iaObj = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
524 family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
525 AF_INET : AF_INET6;
526 JNU_CHECK_EXCEPTION_RETURN(env, -1);
527 if (family == AF_INET) { /* this API can't handle IPV6 addresses */
528 int address = getInetAddress_addr(env, iaObj);
615 }
616 fullPacket = (char *)malloc(packetBufferLen);
617
618 if (!fullPacket) {
619 JNU_ThrowOutOfMemoryError(env, "Peek buffer native heap allocation failed");
620 return -1;
621 } else {
622 mallocedPacket = JNI_TRUE;
623 }
624 } else {
625 fullPacket = &(BUF[0]);
626 }
627
628 n = NET_RecvFrom(fd, fullPacket, packetBufferLen, MSG_PEEK,
629 &rmtaddr.sa, &slen);
630 /* truncate the data if the packet's length is too small */
631 if (n > packetBufferLen) {
632 n = packetBufferLen;
633 }
634 if (n == -1) {
635
636 #ifdef __solaris__
637 if (errno == ECONNREFUSED) {
638 int orig_errno = errno;
639 (void) recv(fd, fullPacket, 1, 0);
640 errno = orig_errno;
641 }
642 #endif
643 (*env)->SetIntField(env, packet, dp_offsetID, 0);
644 (*env)->SetIntField(env, packet, dp_lengthID, 0);
645 if (errno == ECONNREFUSED) {
646 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
647 "ICMP Port Unreachable");
648 } else {
649 if (errno == EBADF) {
650 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
651 } else {
652 JNU_ThrowByNameWithMessageAndLastError
653 (env, JNU_JAVANETPKG "SocketException", "Receive failed");
654 }
655 }
656 } else {
657 /*
658 * success - fill in received address...
659 *
660 * REMIND: Fill in an int on the packet, and create inetadd
661 * object in Java, as a performance improvement. Also
662 * construct the inetadd object lazily.
|
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 <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29
30 #include "net_util.h"
31
32 #include "java_net_PlainDatagramSocketImpl.h"
33 #include "java_net_InetAddress.h"
34 #include "java_net_NetworkInterface.h"
35 #include "java_net_SocketOptions.h"
36
37 #ifdef __linux__
38 #define IPV6_MULTICAST_IF 17
39 #ifndef SO_BSDCOMPAT
40 #define SO_BSDCOMPAT 14
41 #endif
42 /**
43 * IP_MULTICAST_ALL has been supported since kernel version 2.6.31
44 * but we may be building on a machine that is older than that.
45 */
46 #ifndef IP_MULTICAST_ALL
47 #define IP_MULTICAST_ALL 49
48 #endif
49 #endif // __linux__
50
51 #ifndef IPTOS_TOS_MASK
52 #define IPTOS_TOS_MASK 0x1e
53 #endif
54 #ifndef IPTOS_PREC_MASK
55 #define IPTOS_PREC_MASK 0xe0
56 #endif
57
58 /************************************************************************
59 * PlainDatagramSocketImpl
60 */
61
62 static jfieldID IO_fd_fdID;
63
64 static jfieldID pdsi_fdID;
65 static jfieldID pdsi_timeoutID;
66 static jfieldID pdsi_trafficClassID;
67 static jfieldID pdsi_localPortID;
68 static jfieldID pdsi_connected;
69 static jfieldID pdsi_connectedAddress;
70 static jfieldID pdsi_connectedPort;
471 if (ret == 0) {
472 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
473 "Peek timed out");
474 return ret;
475 } else if (ret == -1) {
476 if (errno == EBADF) {
477 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
478 } else if (errno == ENOMEM) {
479 JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
480 } else {
481 JNU_ThrowByNameWithMessageAndLastError
482 (env, JNU_JAVANETPKG "SocketException", "Peek failed");
483 }
484 return ret;
485 }
486 }
487
488 n = NET_RecvFrom(fd, buf, 1, MSG_PEEK, &rmtaddr.sa, &slen);
489
490 if (n == -1) {
491 if (errno == ECONNREFUSED) {
492 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
493 "ICMP Port Unreachable");
494 } else {
495 if (errno == EBADF) {
496 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
497 } else {
498 JNU_ThrowByNameWithMessageAndLastError
499 (env, JNU_JAVANETPKG "SocketException", "Peek failed");
500 }
501 }
502 return 0;
503 }
504
505 iaObj = NET_SockaddrToInetAddress(env, &rmtaddr, &port);
506 family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
507 AF_INET : AF_INET6;
508 JNU_CHECK_EXCEPTION_RETURN(env, -1);
509 if (family == AF_INET) { /* this API can't handle IPV6 addresses */
510 int address = getInetAddress_addr(env, iaObj);
597 }
598 fullPacket = (char *)malloc(packetBufferLen);
599
600 if (!fullPacket) {
601 JNU_ThrowOutOfMemoryError(env, "Peek buffer native heap allocation failed");
602 return -1;
603 } else {
604 mallocedPacket = JNI_TRUE;
605 }
606 } else {
607 fullPacket = &(BUF[0]);
608 }
609
610 n = NET_RecvFrom(fd, fullPacket, packetBufferLen, MSG_PEEK,
611 &rmtaddr.sa, &slen);
612 /* truncate the data if the packet's length is too small */
613 if (n > packetBufferLen) {
614 n = packetBufferLen;
615 }
616 if (n == -1) {
617 (*env)->SetIntField(env, packet, dp_offsetID, 0);
618 (*env)->SetIntField(env, packet, dp_lengthID, 0);
619 if (errno == ECONNREFUSED) {
620 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
621 "ICMP Port Unreachable");
622 } else {
623 if (errno == EBADF) {
624 JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
625 } else {
626 JNU_ThrowByNameWithMessageAndLastError
627 (env, JNU_JAVANETPKG "SocketException", "Receive failed");
628 }
629 }
630 } else {
631 /*
632 * success - fill in received address...
633 *
634 * REMIND: Fill in an int on the packet, and create inetadd
635 * object in Java, as a performance improvement. Also
636 * construct the inetadd object lazily.
|