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