1 /*
2  * Copyright (c) 1998, 2013, 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 <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <sys/time.h>
36 #ifdef __solaris__
37 #include <thread.h>
38 #else
39 #include <pthread.h>
40 #include <sys/poll.h>
41 #endif
42 
43 #include "socket_md.h"
44 #include "sysSocket.h"
45 
46 int
dbgsysListen(int fd,int backlog)47 dbgsysListen(int fd, int backlog) {
48     return listen(fd, backlog);
49 }
50 
51 int
dbgsysConnect(int fd,struct sockaddr * name,socklen_t namelen)52 dbgsysConnect(int fd, struct sockaddr *name, socklen_t namelen) {
53     int rv = connect(fd, name, namelen);
54     if (rv < 0 && (errno == EINPROGRESS || errno == EINTR)) {
55         return DBG_EINPROGRESS;
56     } else {
57         return rv;
58     }
59 }
60 
61 int
dbgsysFinishConnect(int fd,int timeout)62 dbgsysFinishConnect(int fd, int timeout) {
63     int rv = dbgsysPoll(fd, 0, 1, timeout);
64     if (rv == 0) {
65         return DBG_ETIMEOUT;
66     }
67     if (rv > 0) {
68         return 0;
69     }
70     return rv;
71 }
72 
73 int
dbgsysAccept(int fd,struct sockaddr * name,socklen_t * namelen)74 dbgsysAccept(int fd, struct sockaddr *name, socklen_t *namelen) {
75     int rv;
76     for (;;) {
77         rv = accept(fd, name, namelen);
78         if (rv >= 0) {
79             return rv;
80         }
81         if (errno != ECONNABORTED && errno != EINTR) {
82             return rv;
83         }
84     }
85 }
86 
87 int
dbgsysRecvFrom(int fd,char * buf,size_t nBytes,int flags,struct sockaddr * from,socklen_t * fromlen)88 dbgsysRecvFrom(int fd, char *buf, size_t nBytes,
89                   int flags, struct sockaddr *from, socklen_t *fromlen) {
90     int rv;
91     do {
92         rv = recvfrom(fd, buf, nBytes, flags, from, fromlen);
93     } while (rv == -1 && errno == EINTR);
94 
95     return rv;
96 }
97 
98 int
dbgsysSendTo(int fd,char * buf,size_t len,int flags,struct sockaddr * to,socklen_t tolen)99 dbgsysSendTo(int fd, char *buf, size_t len,
100                 int flags, struct sockaddr *to, socklen_t tolen) {
101     int rv;
102     do {
103         rv = sendto(fd, buf, len, flags, to, tolen);
104     } while (rv == -1 && errno == EINTR);
105 
106     return rv;
107 }
108 
109 int
dbgsysRecv(int fd,char * buf,size_t nBytes,int flags)110 dbgsysRecv(int fd, char *buf, size_t nBytes, int flags) {
111     int rv;
112     do {
113         rv = recv(fd, buf, nBytes, flags);
114     } while (rv == -1 && errno == EINTR);
115 
116     return rv;
117 }
118 
119 int
dbgsysSend(int fd,char * buf,size_t nBytes,int flags)120 dbgsysSend(int fd, char *buf, size_t nBytes, int flags) {
121     int rv;
122     do {
123         rv = send(fd, buf, nBytes, flags);
124     } while (rv == -1 && errno == EINTR);
125 
126     return rv;
127 }
128 
129 struct hostent *
dbgsysGetHostByName(char * hostname)130 dbgsysGetHostByName(char *hostname) {
131     return gethostbyname(hostname);
132 }
133 
134 unsigned short
dbgsysHostToNetworkShort(unsigned short hostshort)135 dbgsysHostToNetworkShort(unsigned short hostshort) {
136     return htons(hostshort);
137 }
138 
139 int
dbgsysSocket(int domain,int type,int protocol)140 dbgsysSocket(int domain, int type, int protocol) {
141     return socket(domain, type, protocol);
142 }
143 
dbgsysSocketClose(int fd)144 int dbgsysSocketClose(int fd) {
145     int rv;
146     do {
147         rv = close(fd);
148     } while (rv == -1 && errno == EINTR);
149 
150     return rv;
151 }
152 
153 int
dbgsysBind(int fd,struct sockaddr * name,socklen_t namelen)154 dbgsysBind(int fd, struct sockaddr *name, socklen_t namelen) {
155     return bind(fd, name, namelen);
156 }
157 
158 uint32_t
dbgsysInetAddr(const char * cp)159 dbgsysInetAddr(const char* cp) {
160     return (uint32_t)inet_addr(cp);
161 }
162 
163 uint32_t
dbgsysHostToNetworkLong(uint32_t hostlong)164 dbgsysHostToNetworkLong(uint32_t hostlong) {
165     return htonl(hostlong);
166 }
167 
168 unsigned short
dbgsysNetworkToHostShort(unsigned short netshort)169 dbgsysNetworkToHostShort(unsigned short netshort) {
170     return ntohs(netshort);
171 }
172 
173 int
dbgsysGetSocketName(int fd,struct sockaddr * name,socklen_t * namelen)174 dbgsysGetSocketName(int fd, struct sockaddr *name, socklen_t *namelen) {
175     return getsockname(fd, name, namelen);
176 }
177 
178 uint32_t
dbgsysNetworkToHostLong(uint32_t netlong)179 dbgsysNetworkToHostLong(uint32_t netlong) {
180     return ntohl(netlong);
181 }
182 
183 
184 int
dbgsysSetSocketOption(int fd,jint cmd,jboolean on,jvalue value)185 dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
186 {
187     if (cmd == TCP_NODELAY) {
188         struct protoent *proto = getprotobyname("TCP");
189         int tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto);
190         uint32_t onl = (uint32_t)on;
191 
192         if (setsockopt(fd, tcp_level, TCP_NODELAY,
193                        (char *)&onl, sizeof(uint32_t)) < 0) {
194                 return SYS_ERR;
195         }
196     } else if (cmd == SO_LINGER) {
197         struct linger arg;
198         arg.l_onoff = on;
199 
200         if(on) {
201             arg.l_linger = (unsigned short)value.i;
202             if(setsockopt(fd, SOL_SOCKET, SO_LINGER,
203                           (char*)&arg, sizeof(arg)) < 0) {
204                 return SYS_ERR;
205             }
206         } else {
207             if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
208                            (char*)&arg, sizeof(arg)) < 0) {
209                 return SYS_ERR;
210             }
211         }
212     } else if (cmd == SO_SNDBUF) {
213         jint buflen = value.i;
214         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
215                        (char *)&buflen, sizeof(buflen)) < 0) {
216             return SYS_ERR;
217         }
218     } else if (cmd == SO_REUSEADDR) {
219         int oni = (int)on;
220         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
221                        (char *)&oni, sizeof(oni)) < 0) {
222             return SYS_ERR;
223 
224         }
225     } else {
226         return SYS_ERR;
227     }
228     return SYS_OK;
229 }
230 
231 int
dbgsysConfigureBlocking(int fd,jboolean blocking)232 dbgsysConfigureBlocking(int fd, jboolean blocking) {
233     int flags = fcntl(fd, F_GETFL);
234 
235     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK)) {
236         return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
237     }
238     if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK)) {
239         return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
240     }
241     return 0;
242 }
243 
244 int
dbgsysPoll(int fd,jboolean rd,jboolean wr,long timeout)245 dbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {
246     struct pollfd fds[1];
247     int rv;
248 
249     fds[0].fd = fd;
250     fds[0].events = 0;
251     if (rd) {
252         fds[0].events |= POLLIN;
253     }
254     if (wr) {
255         fds[0].events |= POLLOUT;
256     }
257     fds[0].revents = 0;
258 
259     rv = poll(&fds[0], 1, timeout);
260     if (rv >= 0) {
261         rv = 0;
262         if (fds[0].revents & POLLIN) {
263             rv |= DBG_POLLIN;
264         }
265         if (fds[0].revents & POLLOUT) {
266             rv |= DBG_POLLOUT;
267         }
268     }
269     return rv;
270 }
271 
272 int
dbgsysGetLastIOError(char * buf,jint size)273 dbgsysGetLastIOError(char *buf, jint size) {
274     char *msg = strerror(errno);
275     strncpy(buf, msg, size-1);
276     buf[size-1] = '\0';
277     return 0;
278 }
279 
280 #ifdef __solaris__
281 int
dbgsysTlsAlloc()282 dbgsysTlsAlloc() {
283     thread_key_t tk;
284     if (thr_keycreate(&tk, NULL)) {
285         perror("thr_keycreate");
286         exit(-1);
287     }
288     return (int)tk;
289 }
290 
291 void
dbgsysTlsFree(int index)292 dbgsysTlsFree(int index) {
293    /* no-op */
294 }
295 
296 void
dbgsysTlsPut(int index,void * value)297 dbgsysTlsPut(int index, void *value) {
298     thr_setspecific((thread_key_t)index, value) ;
299 }
300 
301 void *
dbgsysTlsGet(int index)302 dbgsysTlsGet(int index) {
303     void* r = NULL;
304     thr_getspecific((thread_key_t)index, &r);
305     return r;
306 }
307 
308 #else
309 int
dbgsysTlsAlloc()310 dbgsysTlsAlloc() {
311     pthread_key_t key;
312     if (pthread_key_create(&key, NULL)) {
313         perror("pthread_key_create");
314         exit(-1);
315     }
316     return (int)key;
317 }
318 
319 void
dbgsysTlsFree(int index)320 dbgsysTlsFree(int index) {
321     pthread_key_delete((pthread_key_t)index);
322 }
323 
324 void
dbgsysTlsPut(int index,void * value)325 dbgsysTlsPut(int index, void *value) {
326     pthread_setspecific((pthread_key_t)index, value) ;
327 }
328 
329 void *
dbgsysTlsGet(int index)330 dbgsysTlsGet(int index) {
331     return pthread_getspecific((pthread_key_t)index);
332 }
333 
334 #endif
335 
336 long
dbgsysCurrentTimeMillis()337 dbgsysCurrentTimeMillis() {
338     struct timeval t;
339     gettimeofday(&t, 0);
340     return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
341 }
342