1 /* 2 * Copyright (c) 2001, 2018, 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 26 #include <netdb.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <errno.h> 32 33 #if defined(__linux__) || defined(_ALLBSD_SOURCE) 34 #include <netinet/in.h> 35 #endif 36 37 #include "jni.h" 38 #include "jni_util.h" 39 #include "jlong.h" 40 #include "net_util.h" 41 #include "nio.h" 42 #include "nio_util.h" 43 44 #include "sun_nio_ch_DatagramChannelImpl.h" 45 46 JNIEXPORT void JNICALL 47 Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jclass clazz, 48 jobject fdo, jboolean isIPv6) 49 { 50 jint fd = fdval(env, fdo); 51 int rv; 52 53 #if defined(__solaris__) 54 rv = connect(fd, 0, 0); 55 #else 56 SOCKETADDRESS sa; 57 socklen_t len = isIPv6 ? sizeof(struct sockaddr_in6) : 58 sizeof(struct sockaddr_in); 59 60 memset(&sa, 0, sizeof(sa)); 61 #if defined(_ALLBSD_SOURCE) 62 sa.sa.sa_family = isIPv6 ? AF_INET6 : AF_INET; 63 #else 64 sa.sa.sa_family = AF_UNSPEC; 65 #endif 66 67 rv = connect(fd, &sa.sa, len); 68 69 #if defined(_ALLBSD_SOURCE) 70 if (rv < 0 && errno == EADDRNOTAVAIL) 71 rv = errno = 0; 72 #elif defined(_AIX) 73 /* See W. Richard Stevens, "UNIX Network Programming, Volume 1", p. 254: 74 * 'Setting the address family to AF_UNSPEC might return EAFNOSUPPORT 75 * but that is acceptable. 76 */ 77 if (rv < 0 && errno == EAFNOSUPPORT) 78 rv = errno = 0; 79 #endif // defined(_ALLBSD_SOURCE) || defined(_AIX) 80 81 #endif // defined(__solaris__) 82 83 if (rv < 0) 84 handleSocketError(env, errno); 85 } 86 87 JNIEXPORT jint JNICALL 88 Java_sun_nio_ch_DatagramChannelImpl_receive0(JNIEnv *env, jclass clazz, 89 jobject fdo, jlong bufAddress, 90 jint len, jlong senderAddress, 91 jboolean connected) 92 { 93 jint fd = fdval(env, fdo); 94 void *buf = (void *)jlong_to_ptr(bufAddress); 95 SOCKETADDRESS *sa = (SOCKETADDRESS *)jlong_to_ptr(senderAddress); 96 socklen_t sa_len = sizeof(SOCKETADDRESS); 97 jboolean retry = JNI_FALSE; 98 jint n; 99 100 if (len > MAX_PACKET_LEN) { 101 len = MAX_PACKET_LEN; 102 } 103 104 do { 105 retry = JNI_FALSE; 106 n = recvfrom(fd, buf, len, 0, (struct sockaddr *)sa, &sa_len); 107 if (n < 0) { 108 if (errno == EAGAIN || errno == EWOULDBLOCK) { 109 return IOS_UNAVAILABLE; 110 } 111 if (errno == EINTR) { 112 return IOS_INTERRUPTED; 113 } 114 if (errno == ECONNREFUSED) { 115 if (connected == JNI_FALSE) { 116 retry = JNI_TRUE; 117 } else { 118 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); 119 return IOS_THROWN; 120 } 121 } else { 122 return handleSocketError(env, errno); 123 } 124 } 125 } while (retry == JNI_TRUE); 126 127 return n; 128 } 129 130 JNIEXPORT jint JNICALL 131 Java_sun_nio_ch_DatagramChannelImpl_send0(JNIEnv *env, jclass clazz, 132 jobject fdo, jlong bufAddress, jint len, 133 jlong targetAddress, jint targetAddressLen) 134 { 135 jint fd = fdval(env, fdo); 136 void *buf = (void *)jlong_to_ptr(bufAddress); 137 SOCKETADDRESS *sa = (SOCKETADDRESS *)jlong_to_ptr(targetAddress); 138 socklen_t sa_len = (socklen_t) targetAddressLen; 139 jint n; 140 141 if (len > MAX_PACKET_LEN) { 142 len = MAX_PACKET_LEN; 143 } 144 145 n = sendto(fd, buf, len, 0, (struct sockaddr *)sa, sa_len); 146 if (n < 0) { 147 if (errno == EAGAIN || errno == EWOULDBLOCK) { 148 return IOS_UNAVAILABLE; 149 } 150 if (errno == EINTR) { 151 return IOS_INTERRUPTED; 152 } 153 if (errno == ECONNREFUSED) { 154 JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", 0); 155 return IOS_THROWN; 156 } 157 return handleSocketError(env, errno); 158 } 159 return n; 160 }