1 /*
2  * Copyright (c) 2003, 2017, 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 <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 
32 #include "jni.h"
33 
34 #include "jni.h"
35 #include "jni_util.h"
36 #include "net_util.h"
37 
38 #include "sun_nio_ch_InheritedChannel.h"
39 
matchFamily(SOCKETADDRESS * sa)40 static int matchFamily(SOCKETADDRESS *sa) {
41     return (sa->sa.sa_family == (ipv6_available() ? AF_INET6 : AF_INET));
42 }
43 
44 JNIEXPORT void JNICALL
Java_sun_nio_ch_InheritedChannel_initIDs(JNIEnv * env,jclass cla)45 Java_sun_nio_ch_InheritedChannel_initIDs(JNIEnv *env, jclass cla)
46 {
47     /* Initialize InetAddress IDs before later use of NET_XXX functions */
48     initInetAddressIDs(env);
49 }
50 
51 JNIEXPORT jobject JNICALL
Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv * env,jclass cla,jint fd)52 Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd)
53 {
54     SOCKETADDRESS sa;
55     socklen_t len = sizeof(SOCKETADDRESS);
56     jobject remote_ia = NULL;
57     jint remote_port;
58 
59     if (getpeername(fd, &sa.sa, &len) == 0) {
60         if (matchFamily(&sa)) {
61             remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
62         }
63     }
64 
65     return remote_ia;
66 }
67 
68 JNIEXPORT jint JNICALL
Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv * env,jclass cla,jint fd)69 Java_sun_nio_ch_InheritedChannel_peerPort0(JNIEnv *env, jclass cla, jint fd)
70 {
71     SOCKETADDRESS sa;
72     socklen_t len = sizeof(SOCKETADDRESS);
73     jint remote_port = -1;
74 
75     if (getpeername(fd, &sa.sa, &len) == 0) {
76         if (matchFamily(&sa)) {
77             NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
78         }
79     }
80 
81     return remote_port;
82 }
83 
84 JNIEXPORT jint JNICALL
Java_sun_nio_ch_InheritedChannel_soType0(JNIEnv * env,jclass cla,jint fd)85 Java_sun_nio_ch_InheritedChannel_soType0(JNIEnv *env, jclass cla, jint fd)
86 {
87     int sotype;
88     socklen_t arglen = sizeof(sotype);
89     if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) == 0) {
90         if (sotype == SOCK_STREAM)
91             return sun_nio_ch_InheritedChannel_SOCK_STREAM;
92         if (sotype == SOCK_DGRAM)
93             return sun_nio_ch_InheritedChannel_SOCK_DGRAM;
94     }
95     return sun_nio_ch_InheritedChannel_UNKNOWN;
96 }
97 
98 JNIEXPORT jint JNICALL
Java_sun_nio_ch_InheritedChannel_dup(JNIEnv * env,jclass cla,jint fd)99 Java_sun_nio_ch_InheritedChannel_dup(JNIEnv *env, jclass cla, jint fd)
100 {
101    int newfd = dup(fd);
102    if (newfd < 0) {
103         JNU_ThrowIOExceptionWithLastError(env, "dup failed");
104    }
105    return (jint)newfd;
106 }
107 
108 JNIEXPORT void JNICALL
Java_sun_nio_ch_InheritedChannel_dup2(JNIEnv * env,jclass cla,jint fd,jint fd2)109 Java_sun_nio_ch_InheritedChannel_dup2(JNIEnv *env, jclass cla, jint fd, jint fd2)
110 {
111    if (dup2(fd, fd2) < 0) {
112         JNU_ThrowIOExceptionWithLastError(env, "dup2 failed");
113    }
114 }
115 
116 JNIEXPORT jint JNICALL
Java_sun_nio_ch_InheritedChannel_open0(JNIEnv * env,jclass cla,jstring path,jint oflag)117 Java_sun_nio_ch_InheritedChannel_open0(JNIEnv *env, jclass cla, jstring path, jint oflag)
118 {
119     const char *str;
120     int oflag_actual;
121 
122     /* convert to OS specific value */
123     switch (oflag) {
124         case sun_nio_ch_InheritedChannel_O_RDWR :
125             oflag_actual = O_RDWR;
126             break;
127         case sun_nio_ch_InheritedChannel_O_RDONLY :
128             oflag_actual = O_RDONLY;
129             break;
130         case sun_nio_ch_InheritedChannel_O_WRONLY :
131             oflag_actual = O_WRONLY;
132             break;
133         default :
134             JNU_ThrowInternalError(env, "Unrecognized file mode");
135             return -1;
136     }
137 
138     str = JNU_GetStringPlatformChars(env, path, NULL);
139     if (str == NULL) {
140         return (jint)-1;
141     } else {
142         int fd = open(str, oflag_actual);
143         if (fd < 0) {
144             JNU_ThrowIOExceptionWithLastError(env, str);
145         }
146         JNU_ReleaseStringPlatformChars(env, path, str);
147         return (jint)fd;
148     }
149 }
150 
151 JNIEXPORT void JNICALL
Java_sun_nio_ch_InheritedChannel_close0(JNIEnv * env,jclass cla,jint fd)152 Java_sun_nio_ch_InheritedChannel_close0(JNIEnv *env, jclass cla, jint fd)
153 {
154     if (close(fd) < 0) {
155         JNU_ThrowIOExceptionWithLastError(env, "close failed");
156     }
157 }
158