123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819 |
- /* cpnet.c -
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
- This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- GNU Classpath is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
- #include "config.h"
- #include <jni.h>
- #include <assert.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <netdb.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #if defined(HAVE_SYS_IOCTL_H)
- #define BSD_COMP /* Get FIONREAD on Solaris2 */
- #include <sys/ioctl.h>
- #endif
- #if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */
- #include <sys/filio.h>
- #endif
- #include "cpnet.h"
- #define SOCKET_DEFAULT_TIMEOUT -1 /* milliseconds */
- static int socketTimeouts[FD_SETSIZE];
- static jint waitForWritable(jint fd)
- {
- struct timeval tv;
- fd_set writeset;
- int ret;
-
-
- FD_ZERO(&writeset);
- FD_SET(fd, &writeset);
- if (socketTimeouts[fd] > 0)
- {
- tv.tv_sec = socketTimeouts[fd] / 1000;
- tv.tv_usec = (socketTimeouts[fd] % 1000) * 1000;
- ret = select(fd+1, NULL, &writeset, NULL, &tv);
- }
- else
- ret = select(fd+1, NULL, &writeset, NULL, NULL);
- return (ret <= 0) ? -1 : 0;
- }
- static jint waitForReadable(jint fd)
- {
- struct timeval tv;
- fd_set readset;
- int ret;
- FD_ZERO(&readset);
- FD_SET(fd, &readset);
- if (socketTimeouts[fd] > 0)
- {
- tv.tv_sec = socketTimeouts[fd] / 1000;
- tv.tv_usec = (socketTimeouts[fd] % 1000) * 1000;
- ret = select(fd+1, &readset, NULL, NULL, &tv);
- }
- else
- ret = select(fd+1, &readset, NULL, NULL, NULL);
- return (ret <= 0) ? -1 : 0;
- }
- jint cpnet_openSocketStream(JNIEnv *env UNUSED, jint *fd, jint family)
- {
- *fd = socket(family, SOCK_STREAM, 0);
- if (*fd == -1)
- return errno;
- fcntl(*fd, F_SETFD, FD_CLOEXEC);
- assert(*fd < FD_SETSIZE);
- socketTimeouts[*fd] = SOCKET_DEFAULT_TIMEOUT;
- return 0;
- }
- jint cpnet_openSocketDatagram(JNIEnv *env UNUSED, jint *fd, jint family)
- {
- *fd = socket(family, SOCK_DGRAM, 0);
- if (*fd == -1)
- return errno;
- fcntl(*fd, F_SETFD, FD_CLOEXEC);
- assert(*fd < FD_SETSIZE);
- socketTimeouts[*fd] = SOCKET_DEFAULT_TIMEOUT;
- return 0;
- }
- jint cpnet_shutdown (JNIEnv *env UNUSED, jint fd, jbyte flag)
- {
- int ret;
- int shut_flag = 0;
- if (flag == CPNET_SHUTDOWN_READ)
- shut_flag = SHUT_RD;
- else if (flag == CPNET_SHUTDOWN_WRITE)
- shut_flag = SHUT_WR;
- ret = shutdown (fd, shut_flag);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_close(JNIEnv *env UNUSED, jint fd)
- {
- if (close (fd) != 0)
- return errno;
- return 0;
- }
- jint cpnet_listen(JNIEnv *env UNUSED, jint fd, jint queuelen)
- {
- if (listen (fd, queuelen) != 0)
- return errno;
- return 0;
- }
- jint cpnet_accept(JNIEnv *env UNUSED, jint fd, jint *newfd)
- {
- if (waitForReadable (fd) < 0)
- return ETIMEDOUT;
- *newfd = accept(fd, NULL, 0);
- if (*newfd != 0)
- return errno;
- return 0;
- }
- jint cpnet_bind(JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
- {
- int ret;
- ret = bind(fd, (struct sockaddr *)addr->data, addr->len);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_connect(JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
- {
- int ret;
- /* TODO: implement socket time out */
- ret = connect(fd, (struct sockaddr *)addr->data, addr->len);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getLocalAddr(JNIEnv *env, jint fd, cpnet_address **addr)
- {
- socklen_t slen = 1024;
- int ret;
- *addr = JCL_malloc(env, slen);
- slen -= sizeof(jint);
- ret = getsockname(fd, (struct sockaddr *)(*addr)->data, &slen );
- if (ret != 0)
- {
- int err = errno;
- JCL_free(env, *addr);
- return err;
- }
- (*addr)->len = slen;
-
- return 0;
- }
- jint cpnet_getRemoteAddr(JNIEnv *env, jint fd, cpnet_address **addr)
- {
- socklen_t slen = 1024;
- int ret;
- *addr = JCL_malloc(env, slen);
- slen -= sizeof(jint);
- ret = getpeername(fd, (struct sockaddr *)(*addr)->data, &slen );
- if (ret != 0)
- {
- int err = errno;
- JCL_free(env, *addr);
- return err;
- }
- (*addr)->len = slen;
-
- return 0;
- }
- jint cpnet_setBroadcast(JNIEnv *env UNUSED, jint fd, jint flag)
- {
- int ret;
- ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));
- if (ret != 0)
- return errno;
- return 0;
- }
- #if defined (HAVE_MSG_NOSIGNAL)
- #elif defined (HAVE_SO_NOSIGPIPE)
- static int setsockopt_NOSIGPIPE (int fd)
- {
- int setToTrue = 1;
- return setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &setToTrue, sizeof(setToTrue));
- }
- #endif
- jint cpnet_send (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, jint *bytes_sent)
- {
- ssize_t ret;
- if (waitForWritable(fd) < 0)
- return ETIMEDOUT;
- #if defined (HAVE_MSG_NOSIGNAL)
- ret = send(fd, data, len, MSG_NOSIGNAL);
- #elif defined (HAVE_SO_NOSIGPIPE)
- ret = setsockopt_NOSIGPIPE(fd);
- if (ret == 0) ret = send(fd, data, len, 0);
- #else
- /* We want SIGPIPE to be omitted. But this configuration does not have an
- * option for that.
- */
- ret = send(fd, data, len, 0);
- #endif
- if (ret < 0)
- return errno;
- *bytes_sent = ret;
- return 0;
- }
- jint cpnet_sendTo (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, cpnet_address *addr, jint *bytes_sent)
- {
- ssize_t ret;
- if (waitForWritable(fd) < 0)
- return ETIMEDOUT;
- #if defined (HAVE_MSG_NOSIGNAL)
- ret = sendto(fd, data, len, MSG_NOSIGNAL, (struct sockaddr *)addr->data,
- addr->len);
- #elif defined (HAVE_SO_NOSIGPIPE)
- ret = setsockopt_NOSIGPIPE(fd);
- if (ret == 0)
- {
- ret = sendto(fd, data, len, 0, (struct sockaddr *)addr->data,
- addr->len);
- }
- #else
- /* We want SIGPIPE to be omitted. But this configuration does not have an
- * option for that.
- */
- ret = sendto(fd, data, len, 0, (struct sockaddr *)addr->data,
- addr->len);
- #endif
- if (ret < 0)
- return errno;
- *bytes_sent = ret;
- return 0;
- }
- jint cpnet_recv (JNIEnv *env UNUSED, jint fd, jbyte *data, jint len, jint *bytes_recv)
- {
- ssize_t ret;
- if (waitForReadable(fd) < 0)
- return ETIMEDOUT;
- ret = recv(fd, data, len, 0);
- if (ret < 0)
- return errno;
- *bytes_recv = ret;
- return 0;
- }
- jint cpnet_recvFrom (JNIEnv *env, jint fd, jbyte *data, jint len, cpnet_address **addr, jint *bytes_recv)
- {
- socklen_t slen = 1024;
- ssize_t ret;
- if (waitForReadable(fd) < 0)
- return ETIMEDOUT;
- *addr = JCL_malloc(env, slen);
- slen -= sizeof(jint);
- ret = recvfrom(fd, data, len, 0, (struct sockaddr *) (*addr)->data, &slen);
- if (ret < 0)
- {
- int err = errno;
- JCL_free(env, *addr);
- return err;
- }
- (*addr)->len = slen;
- *bytes_recv = ret;
- return 0;
- }
- jint cpnet_setSocketTCPNoDelay (JNIEnv *env UNUSED, jint fd, jint nodelay)
- {
- socklen_t len = sizeof(jint);
- int ret;
- ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, len);
- if (ret < 0)
- return errno;
- return 0;
- }
- jint cpnet_getSocketTCPNoDelay (JNIEnv *env UNUSED, jint fd, jint *nodelay)
- {
- socklen_t len = sizeof(jint);
- int ret;
- ret = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, nodelay, &len);
- if (ret < 0)
- return errno;
- return 0;
- }
- jint cpnet_setLinger (JNIEnv *env UNUSED, jint fd, jint flag, jint value)
- {
- socklen_t len = sizeof(struct linger);
- int ret;
- struct linger __linger;
- if (flag)
- {
- __linger.l_onoff = 0;
- }
- else
- {
- __linger.l_linger = value;
- __linger.l_onoff = 1;
- }
- ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &__linger, len);
- if (ret < 0)
- return errno;
- return 0;
- }
- jint cpnet_getLinger (JNIEnv *env UNUSED, jint fd, jint *flag, jint *value)
- {
- socklen_t slen = sizeof(struct linger);
- struct linger __linger;
- int ret;
- ret = getsockopt(fd, SOL_SOCKET, SO_LINGER, &__linger, &slen);
- if (ret != 0)
- return errno;
- *flag = __linger.l_onoff;
- *value = __linger.l_linger;
- return ret;
- }
- jint cpnet_setSocketTimeout (JNIEnv *env UNUSED, jint fd, jint value)
- {
- socketTimeouts[fd] = value;
- return 0;
- }
- jint cpnet_getSocketTimeout (JNIEnv *env UNUSED, jint fd, jint *value)
- {
- *value = socketTimeouts[fd];
- return 0;
- }
- jint cpnet_setSendBuf (JNIEnv *env UNUSED, jint fd, jint value)
- {
- int ret;
- ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getSendBuf (JNIEnv *env UNUSED, jint fd, jint *value)
- {
- int ret;
- socklen_t slen = sizeof(*value);
- ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, value, &slen);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_setRecvBuf (JNIEnv *env UNUSED, jint fd, jint value)
- {
- int ret;
- ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getRecvBuf (JNIEnv *env UNUSED, jint fd, jint *value)
- {
- int ret;
- socklen_t slen = sizeof(*value);
- ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, value, &slen);
- if (ret != 0)
- return errno;
-
- return 0;
- }
- jint cpnet_setTTL (JNIEnv *env UNUSED, jint fd, jint value)
- {
- int ret;
- ret = setsockopt(fd, IPPROTO_IP, IP_TTL, &value, sizeof(value));
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getTTL (JNIEnv *env UNUSED, jint fd, jint *value)
- {
- int ret;
- socklen_t slen = sizeof(*value);
- ret = getsockopt(fd, IPPROTO_IP, IP_TTL, value, &slen);
- if (ret != 0)
- return errno;
-
- return 0;
- }
- jint cpnet_setMulticastIF (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
- {
- int ret;
- ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (struct sockaddr *)addr->data, addr->len);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getMulticastIF (JNIEnv *env, jint fd, cpnet_address **addr)
- {
- socklen_t slen = 1024;
- int ret;
- *addr = JCL_malloc(env, slen);
- slen -= sizeof(jint);
- ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (struct sockaddr *)(*addr)->data, &slen);
- (*addr)->len = slen;
- if (ret != 0)
- return errno;
-
- return 0;
- }
- jint cpnet_setReuseAddress (JNIEnv *env UNUSED, jint fd, jint reuse)
- {
- int ret;
- ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getReuseAddress (JNIEnv *env UNUSED, jint fd, jint *reuse)
- {
- int ret;
- socklen_t slen = sizeof(*reuse);
- ret = getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reuse, &slen);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_setKeepAlive (JNIEnv *env UNUSED, jint fd, jint keep)
- {
- int ret;
- ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep, sizeof(keep));
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getKeepAlive (JNIEnv *env UNUSED, jint fd, jint *keep)
- {
- int ret;
- socklen_t slen = sizeof(*keep);
- ret = getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, keep, &slen);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_addMembership (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
- {
- struct ip_mreq req;
- int ret;
- struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr->data;
-
- memset(&req, 0, sizeof(req));
- req.imr_multiaddr = sockaddr->sin_addr;
- req.imr_interface.s_addr = INADDR_ANY;
- ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req));
- if (ret != 0)
- return errno;
-
- return 0;
- }
- jint cpnet_dropMembership (JNIEnv *env UNUSED, jint fd, cpnet_address *addr)
- {
- struct ip_mreq req;
- int ret;
- struct sockaddr_in *sockaddr = (struct sockaddr_in *)addr->data;
-
- memset(&req, 0, sizeof(req));
- req.imr_multiaddr = sockaddr->sin_addr;
- req.imr_interface.s_addr = INADDR_ANY;
- ret = setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &req, sizeof(req));
- if (ret != 0)
- return errno;
-
- return 0;
- }
- jint cpnet_getAvailableBytes (JNIEnv *env UNUSED, jint fd, jint *availableBytes)
- {
- int ret;
- ret = ioctl(fd, FIONREAD, availableBytes);
- if (ret != 0)
- return errno;
- return 0;
- }
- jint cpnet_getHostname (JNIEnv *env UNUSED, char *hostname, jint hostname_len)
- {
- int ret;
- ret = gethostname(hostname, hostname_len);
- if (ret != 0)
- return errno;
- hostname[hostname_len-1] = 0;
- return 0;
- }
- jint cpnet_getHostByName (JNIEnv *env, const char *hostname, cpnet_address ***addresses, jint *addresses_count)
- {
- struct hostent hret;
- struct hostent *result;
- jint buflen = 1024;
- int herr = 0;
- int ret = 0;
- int counter = 0;
- cpnet_address **addr_arr;
- int i;
- char *buf;
- do
- {
- buf = (char *)JCL_malloc(env, buflen);
- #ifdef HAVE_GETHOSTBYNAME_R
- # if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
- ret = gethostbyname_r (hostname, &hret, buf, buflen, &result, &herr);
- # elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
- result = gethostbyname_r(hostname, &hret, buf, buflen, &herr);
- # elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
- # error IMPLEMENT ME!
- # else
- # error unknown number of arguments for gethostbyname_r
- # endif
- #else
- hret.h_addr_list = NULL;
- hret.h_addrtype = 0;
- result = gethostbyname (hostname);
- if (result == NULL)
- return -errno;
- memcpy (&hret, result, sizeof (struct hostent));
- #endif
- if (ret != 0 || result == NULL)
- {
- if (herr == ERANGE)
- {
- buflen *= 2;
- JCL_free(env, buf);
- continue;
- }
- JCL_free(env, buf);
- return -herr;
- }
- break;
- }
- while (1);
-
- while (hret.h_addr_list[counter] != NULL)
- counter++;
- *addresses_count = counter;
- addr_arr = *addresses = JCL_malloc(env, sizeof(cpnet_address *) * counter);
- switch (hret.h_addrtype)
- {
- case AF_INET:
- for (i = 0; i < counter; i++)
- {
- addr_arr[i] = cpnet_newIPV4Address(env);
- cpnet_bytesToIPV4Address(addr_arr[i], (jbyte *)hret.h_addr_list[i]);
- }
- break;
- #ifdef HAVE_INET6
- case AF_INET6:
- for (i = 0; i < counter; i++)
- {
- addr_arr[i] = cpnet_newIPV6Address(env);
- cpnet_bytesToIPV6Address(addr_arr[i], (jbyte *)hret.h_addr_list[i]);
- }
- break;
- #endif
- default:
- *addresses_count = 0;
- JCL_free(env, addr_arr);
- break;
- }
- JCL_free(env, buf);
- return 0;
- }
- jint cpnet_getHostByAddr (JNIEnv *env UNUSED, cpnet_address *addr, char *hostname, jint hostname_len)
- {
- union
- {
- struct sockaddr_in *addr_v4;
- struct sockaddr_in6 *addr_v6;
- char *data;
- } haddr;
- void *raw_addr;
- int addr_type;
- struct hostent *ret;
- int addr_len;
- haddr.data = addr->data;
-
- if (haddr.addr_v4->sin_family == AF_INET)
- {
- raw_addr = &haddr.addr_v4->sin_addr;
- addr_len = sizeof(haddr.addr_v4->sin_addr);
- addr_type = AF_INET;
- }
- #ifdef HAVE_INET6
- else if (haddr.addr_v6->sin6_family == AF_INET6)
- {
- raw_addr = &haddr.addr_v6->sin6_addr;
- addr_type = AF_INET6;
- addr_len = sizeof(haddr.addr_v6->sin6_addr);
- }
- #endif
- else
- return EINVAL;
- /* Here we do not have any thread safe call. VM implementors will have to
- * do a big lock. Or it should be put on the Classpath VM interface.
- */
- ret = gethostbyaddr(raw_addr, addr_len, addr_type);
- if (ret == NULL)
- {
- /* The trouble here is how to distinguish the two cases ? */
- if (h_errno != 0)
- return h_errno;
- else
- return errno;
- }
- strncpy(hostname, ret->h_name, hostname_len);
- return 0;
- }
- jint cpnet_aton (JNIEnv *env, const char *hostname, cpnet_address **addr)
- {
- jbyte *bytes = NULL;
- #if defined(HAVE_INET_PTON) && defined(HAVE_INET6)
- jbyte inet6_addr[16];
- #endif
- #ifdef HAVE_INET_ATON
- struct in_addr laddr;
- if (inet_aton (hostname, &laddr))
- {
- bytes = (jbyte *) &laddr;
- }
- #elif defined(HAVE_INET_ADDR)
- #if ! HAVE_IN_ADDR_T
- typedef jint in_addr_t;
- #endif
- in_addr_t laddr = inet_addr (hostname);
- if (laddr != (in_addr_t)(-1))
- {
- bytes = (jbyte *) &laddr;
- }
- #endif
- if (bytes)
- {
- *addr = cpnet_newIPV4Address(env);
- cpnet_bytesToIPV4Address(*addr, bytes);
- return 0;
- }
- #if defined(HAVE_INET_PTON) && defined(HAVE_INET6)
- if (inet_pton (AF_INET6, hostname, inet6_addr) > 0)
- {
- *addr = cpnet_newIPV6Address(env);
- cpnet_bytesToIPV6Address(*addr, inet6_addr);
- return 0;
- }
- #endif
- *addr = NULL;
- return 0;
- }
- void cpnet_freeAddresses(JNIEnv * env, cpnet_address **addr, jint addresses_count)
- {
- jint i;
- for (i = 0; i < addresses_count; i++)
- cpnet_freeAddress(env, addr[i]);
- }
|