151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <errno.h>
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <string.h>
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <sys/types.h>
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <sys/socket.h>
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <netinet/tcp.h>        /* Defines TCP_NODELAY, needed for 2.6 */
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <netinet/in.h>
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <net/if.h>
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <netdb.h>
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <stdlib.h>
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <dlfcn.h>
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <limits.h>
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <sys/param.h>
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef MAXINT
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define MAXINT INT_MAX
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
42f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski#ifdef __BIONIC__
43f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski#include <linux/ipv6_route.h>
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <sys/sockio.h>
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <stropts.h>
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <inet/nd.h>
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <arpa/inet.h>
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <net/route.h>
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <sys/utsname.h>
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef IPV6_FLOWINFO_SEND
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define IPV6_FLOWINFO_SEND      33
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jni_util.h"
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jvm.h"
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "net_util.h"
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "java_net_SocketOptions.h"
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* needed from libsocket on Solaris 8 */
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskigetaddrinfo_f getaddrinfo_ptr = NULL;
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskifreeaddrinfo_f freeaddrinfo_ptr = NULL;
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskigai_strerror_f gai_strerror_ptr = NULL;
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskigetnameinfo_f getnameinfo_ptr = NULL;
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * EXCLBIND socket options only on Solaris
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(__solaris__) && !defined(TCP_EXCLBIND)
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define TCP_EXCLBIND            0x21
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(__solaris__) && !defined(UDP_EXCLBIND)
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define UDP_EXCLBIND            0x0101
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid setDefaultScopeID(JNIEnv *env, struct sockaddr *him)
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef MACOSX
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static jclass ni_class = NULL;
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static jfieldID ni_defaultIndexID;
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ni_class == NULL) {
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CHECK_NULL(c);
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        c = (*env)->NewGlobalRef(env, c);
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CHECK_NULL(c);
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ni_defaultIndexID = (*env)->GetStaticFieldID(
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            env, c, "defaultIndex", "I");
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ni_class = c;
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int defaultIndex;
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him;
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0)) {
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        defaultIndex = (*env)->GetStaticIntField(env, ni_class,
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                 ni_defaultIndexID);
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        sin6->sin6_scope_id = defaultIndex;
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint getDefaultScopeID(JNIEnv *env) {
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static jclass ni_class = NULL;
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static jfieldID ni_defaultIndexID;
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ni_class == NULL) {
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
115f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski        if (c == NULL) return 0;
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        c = (*env)->NewGlobalRef(env, c);
117f7ab2bc37debba91864bfec6572a3e7bbe994c58Piotr Jastrzebski        if (c == NULL) return 0;
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ni_defaultIndexID = (*env)->GetStaticFieldID(
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            env, c, "defaultIndex", "I");
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ni_class = c;
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int defaultIndex = 0;
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    defaultIndex = (*env)->GetStaticIntField(env, ni_class,
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                 ni_defaultIndexID);
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return defaultIndex;
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int init_tcp_max_buf, init_udp_max_buf;
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int tcp_max_buf;
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int udp_max_buf;
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int useExclBind = 0;
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get the specified parameter from the specified driver. The value
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the parameter is assumed to be an 'int'. If the parameter
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cannot be obtained return -1
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskigetParam(char *driver, char *param)
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct strioctl stri;
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char buf [64];
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int s;
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int value;
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    s = open (driver, O_RDWR);
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (s < 0) {
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -1;
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    strncpy (buf, param, sizeof(buf));
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    stri.ic_cmd = ND_GET;
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    stri.ic_timout = 0;
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    stri.ic_dp = buf;
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    stri.ic_len = sizeof(buf);
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ioctl (s, I_STR, &stri) < 0) {
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        value = -1;
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else {
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        value = atoi(buf);
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    close (s);
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return value;
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for Solaris versions that do not support the ioctl() in getParam().
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Ugly, but only called once (for each sotype).
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
170eb984abe3282ad17cfdea4fdaab96f3029113cb5Yi Kong * As an optimization, we make a guess using the default values for Solaris
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * assuming they haven't been modified with ndd.
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define MAX_TCP_GUESS 1024 * 1024
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define MAX_UDP_GUESS 2 * 1024 * 1024
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int findMaxBuf(int fd, int opt, int sotype) {
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int a = 0;
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int b = MAXINT;
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int initial_guess;
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int limit = -1;
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (sotype == SOCK_DGRAM) {
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initial_guess = MAX_UDP_GUESS;
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else {
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initial_guess = MAX_TCP_GUESS;
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initial_guess++;
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FAIL_IF_NOT_ENOBUFS;
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return initial_guess - 1;
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        a = initial_guess;
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else {
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FAIL_IF_NOT_ENOBUFS;
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        b = initial_guess - 1;
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    do {
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int mid = a + (b-a)/2;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            limit = mid;
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            a = mid + 1;
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FAIL_IF_NOT_ENOBUFS;
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            b = mid - 1;
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } while (b >= a);
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return limit;
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int vinit = 0;
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int kernelV24 = 0;
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int vinit24 = 0;
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint kernelIsV24 () {
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (!vinit24) {
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct utsname sysinfo;
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (uname(&sysinfo) == 0) {
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            sysinfo.release[3] = '\0';
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (strcmp(sysinfo.release, "2.4") == 0) {
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                kernelV24 = JNI_TRUE;
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        vinit24 = 1;
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return kernelV24;
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint getScopeID (struct sockaddr *him) {
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return hext->sin6_scope_id;
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint cmpScopeID (unsigned int scope, struct sockaddr *him) {
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return hext->sin6_scope_id == scope;
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint getScopeID (struct sockaddr *him) {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return him6->sin6_scope_id;
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint cmpScopeID (unsigned int scope, struct sockaddr *him) {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return him6->sin6_scope_id == scope;
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   const char *defaultDetail) {
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char errmsg[255];
2666786911a58e65bad88d08a0d1f8d32ab067edaa9George Burgess IV    snprintf(errmsg, sizeof(errmsg), "errno: %d, error: %s\n", errno,
2676786911a58e65bad88d08a0d1f8d32ab067edaa9George Burgess IV             defaultDetail);
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    JNU_ThrowByNameWithLastError(env, name, errmsg);
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_ThrowCurrent(JNIEnv *env, char *msg) {
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    NET_ThrowNew(env, errno, msg);
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char fullMsg[512];
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (!msg) {
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        msg = "no further information";
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    switch(errorNumber) {
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    case EBADF:
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        break;
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    case EINTR:
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        break;
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    default:
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        errno = errorNumber;
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        break;
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskijfieldID
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_GetFileDescriptorID(JNIEnv *env)
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    CHECK_NULL_RETURN(cls, NULL);
303ba7cc9f5357c323a1006119a20ce025fd4c57fd2Piotr Jastrzebski    return (*env)->GetFieldID(env, cls, "descriptor", "I");
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(DONT_ENABLE_IPV6)
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskijint  IPv6_supported()
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return JNI_FALSE;
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else /* !DONT_ENABLE_IPV6 */
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskijint  IPv6_supported()
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef AF_INET6
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return JNI_FALSE;
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int fd;
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void *ipv6_fn;
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    SOCKADDR sa;
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    socklen_t sa_len = sizeof(sa);
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
326ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    // This one below is problematic, will fail without proper permissions
327ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    // and report no ipv6 for some and ipv6 for others.
328ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    //fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;
329ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    //if (fd < 0) {
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *  TODO: We really cant tell since it may be an unrelated error
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         *  for now we will assume that AF_INET6 is not available
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
334ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    //    return JNI_FALSE;
335ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    //}
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If fd 0 is a socket it means we've been launched from inetd or
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * xinetd. If it's a socket then check the family - if it's an
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * IPv4 socket then we need to disable IPv6.
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
342ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    /*if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) {
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct sockaddr *saP = (struct sockaddr *)&sa;
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (saP->sa_family != AF_INET6) {
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return JNI_FALSE;
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
347ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak      }*/
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Linux - check if any interface has an IPv6 address.
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Don't need to parse the line - we just need an indication.
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
354ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    /*    {
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FILE *fP = fopen("/proc/net/if_inet6", "r");
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char buf[255];
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char *bufP;
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fP == NULL) {
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            close(fd);
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return JNI_FALSE;
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bufP = fgets(buf, sizeof(buf), fP);
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        fclose(fP);
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bufP == NULL) {
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            close(fd);
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return JNI_FALSE;
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
369ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        }*/
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * On Solaris 8 it's possible to create INET6 sockets even
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * though IPv6 is not enabled on all interfaces. Thus we
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * query the number of IPv6 addresses to verify that IPv6
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * has been configured on at least one interface.
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * On Linux it doesn't matter - if IPv6 is built-in the
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * kernel then IPv6 addresses will be bound automatically
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to all interfaces.
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef SIOCGLIFNUM
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct lifnum numifs;
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numifs.lifn_family = AF_INET6;
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numifs.lifn_flags = 0;
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /**
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * SIOCGLIFNUM failed - assume IPv6 not configured
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
394a87f559f13ebd0861c0dfbb95b51e76311c94473Yi Kong            untagSocket(env, fd);
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            close(fd);
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return JNI_FALSE;
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /**
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * If no IPv6 addresses then return false. If count > 0
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * it's possible that all IPv6 addresses are "down" but
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * that's okay as they may be brought "up" while the
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * VM is running.
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (numifs.lifn_count == 0) {
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            close(fd);
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return JNI_FALSE;
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* SIOCGLIFNUM not defined in build environment ??? */
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    close(fd);
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return JNI_FALSE;
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* __solaris */
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  OK we may have the stack available in the kernel,
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *  we should also check if the APIs are available.
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
4219b7a4b3eb9a9a1d0a25416bd914cdd46109146c5Przemyslaw Szczepaniak
422ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ipv6_fn == NULL ) {
424ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        // close(fd);
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return JNI_FALSE;
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * We've got the library, let's get the pointers to some
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * IPV6 specific functions. We have to do that because, at least
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * on Solaris we may build on a system without IPV6 networking
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * libraries, therefore we can't have a hard link to these
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * functions.
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    getaddrinfo_ptr = (getaddrinfo_f)
436ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    freeaddrinfo_ptr = (freeaddrinfo_f)
439ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    gai_strerror_ptr = (gai_strerror_f)
442ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    getnameinfo_ptr = (getnameinfo_f)
445ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak        JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* We need all 3 of them */
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        getaddrinfo_ptr = NULL;
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
452ae218d9bdc8395ac0ed9278c86cff597915c2a7bPrzemyslaw Szczepaniak    //close(fd);
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return JNI_TRUE;
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* AF_INET6 */
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* DONT_ENABLE_IPV6 */
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                           const char* hostname,
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                           int gai_error)
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int size;
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char *buf;
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    const char *format = "%s: %s";
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    const char *error_string =
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (error_string == NULL)
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        error_string = "unknown error";
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    buf = (char *) malloc(size);
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (buf) {
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jstring s;
4746786911a58e65bad88d08a0d1f8d32ab067edaa9George Burgess IV        snprintf(buf, size, format, hostname, error_string);
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        s = JNU_NewStringPlatform(env, buf);
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (s != NULL) {
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jobject x = JNU_NewObjectByName(env,
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            "java/net/UnknownHostException",
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            "(Ljava/lang/String;)V", s);
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (x != NULL)
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (*env)->Throw(env, x);
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        free(buf);
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_AllocSockaddr(struct sockaddr **him, int *len) {
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ipv6_available()) {
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        *him = (struct sockaddr*)him6;
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        *len = sizeof(struct sockaddr_in6);
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* AF_INET6 */
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *him = (struct sockaddr*)him4;
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *len = sizeof(struct sockaddr_in);
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5033442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong#if 0
5043442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong// Android-changed: Stripped out unused code. http://b/33250070
5053442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong// #if defined(__linux__) && defined(AF_INET6)
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* following code creates a list of addresses from the kernel
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * routing table that are routed via the loopback address.
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * We check all destination addresses against this table
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and override the scope_id field to use the relevant value for "lo"
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in order to work-around the Linux bug that prevents packets destined
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * for certain local addresses from being sent via a physical interface.
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistruct loopback_route {
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct in6_addr addr; /* destination address */
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int plen; /* prefix length */
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski};
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic struct loopback_route *loRoutes = 0;
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int nRoutes = 0; /* number of routes */
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int loRoutes_size = 16; /* initial size */
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int lo_scope_id = 0;
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic void initLoopbackRoutes();
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid printAddr (struct in6_addr *addr) {
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int i;
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for (i=0; i<16; i++) {
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        printf ("%02x", addr->s6_addr[i]);
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    printf ("\n");
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic void initLoopbackRoutes() {
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    FILE *f;
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char srcp[8][5];
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char hopp[8][5];
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int dest_plen, src_plen, use, refcnt, metric;
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    unsigned long flags;
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char dest_str[40];
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct in6_addr dest_addr;
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char device[16];
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (loRoutes != 0) {
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        free (loRoutes);
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (loRoutes == 0) {
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return;
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Scan /proc/net/ipv6_route looking for a matching
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * route.
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ;
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     "%4s%4s%4s%4s%4s%4s%4s%4s "
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     "%08x %08x %08x %08lx %8s",
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     &dest_plen,
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     srcp[0], srcp[1], srcp[2], srcp[3],
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     srcp[4], srcp[5], srcp[6], srcp[7],
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     &src_plen,
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     hopp[0], hopp[1], hopp[2], hopp[3],
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     hopp[4], hopp[5], hopp[6], hopp[7],
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     &metric, &use, &refcnt, &flags, device) == 31) {
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Some routes should be ignored
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ( (dest_plen < 0 || dest_plen > 128)  ||
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             (src_plen != 0) ||
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             (flags & (RTF_POLICY | RTF_FLOW)) ||
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             ((flags & RTF_REJECT) && dest_plen == 0) ) {
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            continue;
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /*
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         * Convert the destination address
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         */
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[4] = ':';
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[9] = ':';
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[14] = ':';
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[19] = ':';
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[24] = ':';
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[29] = ':';
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[34] = ':';
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        dest_str[39] = '\0';
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* not an Ipv6 address */
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            continue;
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (strcmp(device, "lo") != 0) {
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* Not a loopback route */
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            continue;
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (nRoutes == loRoutes_size) {
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                loRoutes = realloc (loRoutes, loRoutes_size *
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                sizeof (struct loopback_route) * 2);
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (loRoutes == 0) {
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return ;
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                loRoutes_size *= 2;
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            loRoutes[nRoutes].plen = dest_plen;
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            nRoutes ++;
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    fclose (f);
61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* now find the scope_id for "lo" */
62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char devname[21];
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char addr6p[8][5];
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int plen, scope, dad_status, if_idx;
62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                  &if_idx, &plen, &scope, &dad_status, devname) == 13) {
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (strcmp(devname, "lo") == 0) {
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    /*
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     * Found - so just return the index
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     */
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fclose(f);
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    lo_scope_id = if_idx;
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            fclose(f);
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Following is used for binding to local addresses. Equivalent
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to code above, for bind().
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistruct localinterface {
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int index;
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char localaddr [16];
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski};
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic struct localinterface *localifs = 0;
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int localifsSize = 0;    /* size of array */
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic int nifs = 0;            /* number of entries used in array */
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* not thread safe: make sure called once from one thread */
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskistatic void initLocalIfs () {
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    FILE *f;
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    unsigned char staddr [16];
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char ifname [33];
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    struct localinterface *lif=0;
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int index, x1, x2, x3;
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ;
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                &u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                &index, &x1, &x2, &x3, ifname) == 21) {
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[0] = (unsigned char)u0;
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[1] = (unsigned char)u1;
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[2] = (unsigned char)u2;
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[3] = (unsigned char)u3;
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[4] = (unsigned char)u4;
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[5] = (unsigned char)u5;
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[6] = (unsigned char)u6;
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[7] = (unsigned char)u7;
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[8] = (unsigned char)u8;
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[9] = (unsigned char)u9;
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[10] = (unsigned char)ua;
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[11] = (unsigned char)ub;
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[12] = (unsigned char)uc;
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[13] = (unsigned char)ud;
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[14] = (unsigned char)ue;
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        staddr[15] = (unsigned char)uf;
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        nifs ++;
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (nifs > localifsSize) {
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            localifs = (struct localinterface *) realloc (
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        localifs, sizeof (struct localinterface)* (localifsSize+5));
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (localifs == 0) {
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                nifs = 0;
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                fclose (f);
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return;
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lif = localifs + localifsSize;
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            localifsSize += 5;
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lif ++;
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        memcpy (lif->localaddr, staddr, 16);
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        lif->index = index;
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    fclose (f);
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid initLocalAddrTable () {
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    initLoopbackRoutes();
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    initLocalIfs();
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid initLocalAddrTable () {}
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid parseExclusiveBindProperty(JNIEnv *env) {
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jstring s, flagSet;
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jclass iCls;
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jmethodID mid;
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    CHECK_NULL(s);
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    iCls = (*env)->FindClass(env, "java/lang/System");
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    CHECK_NULL(iCls);
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                "(Ljava/lang/String;)Ljava/lang/String;");
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    CHECK_NULL(mid);
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (flagSet != NULL) {
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        useExclBind = 1;
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* In the case of an IPv4 Inetaddress this method will return an
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski*/
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiJNIEXPORT int JNICALL
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          int *len, jboolean v4MappedAddress) {
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jint family;
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    family = getInetAddress_family(env, iaObj);
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* needs work. 1. family 2. clean up him6 etc deallocate memory */
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jbyteArray ipaddress;
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jbyte caddr[16];
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jint address;
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (family == IPv4) { /* will convert to IPv4-mapped address */
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            memset((char *) caddr, 0, 16);
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            address = getInetAddress_addr(env, iaObj);
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (address == INADDR_ANY) {
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* we would always prefer IPv6 wildcard address
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   caddr[10] = 0xff;
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   caddr[11] = 0xff; */
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[10] = 0xff;
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[11] = 0xff;
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[12] = ((address >> 24) & 0xff);
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[13] = ((address >> 16) & 0xff);
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[14] = ((address >> 8) & 0xff);
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                caddr[15] = (address & 0xff);
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
77762e0b4793b755083e94aac458111ca347314adddYi Kong            getInet6Address_ipaddress(env, iaObj, (char *)caddr);
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        him6->sin6_port = htons(port);
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        him6->sin6_family = AF_INET6;
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        *len = sizeof(struct sockaddr_in6) ;
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski// XXXBSD: should we do something with scope id here ? see below linux comment
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* MMM: Come back to this! */
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
79037980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath        // Android-changed: Don't try and figure out scope_ids for link local
79137980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath        // addresses. Use them only if they're set in java (say, if the Inet6Address
79237980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath        // was constructed with a specific scope_id or NetworkInterface).
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (family != IPv4) {
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ia6_scopeidID) {
79562e0b4793b755083e94aac458111ca347314adddYi Kong                int scope_id = getInet6Address_scopeid(env, iaObj);
79637980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath                if (scope_id > 0) {
79737980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath                    him6->sin6_scope_id = scope_id;
79837980c1a826a1eb83b2c825d533c70c7d041e054Narayan Kamath                }
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* AF_INET6 */
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            struct sockaddr_in *him4 = (struct sockaddr_in*)him;
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jint address;
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (family == IPv6) {
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski              JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski              return -1;
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            memset((char *) him4, 0, sizeof(struct sockaddr_in));
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            address = getInetAddress_addr(env, iaObj);
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            him4->sin_port = htons((short) port);
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            him4->sin_addr.s_addr = (uint32_t) htonl(address);
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            him4->sin_family = AF_INET;
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *len = sizeof(struct sockaddr_in);
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return 0;
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskivoid
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (him->sa_family == AF_INET6) {
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* AF_INET6 */
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiJNIEXPORT jint JNICALL
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_GetPortFromSockaddr(struct sockaddr *him) {
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (him->sa_family == AF_INET6) {
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ntohs(((struct sockaddr_in6*)him)->sin6_port);
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif /* AF_INET6 */
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return ntohs(((struct sockaddr_in*)him)->sin_port);
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_IsIPv4Mapped(jbyte* caddr) {
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int i;
84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for (i = 0; i < 10; i++) {
84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (caddr[i] != 0x00) {
84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0; /* false */
84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 1; /* true */
85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return 0; /* false */
85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_IPv4MappedToIPv4(jbyte* caddr) {
86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        | (caddr[15] & 0xff);
86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int i;
86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for (i = 0; i < 16; i++) {
86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (caddr1[i] != caddr2[i]) {
86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0; /* false */
87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return 1;
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskijboolean NET_addrtransAvailable() {
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return (jboolean)(getaddrinfo_ptr != NULL);
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint NET_IsZeroAddr(jbyte* caddr) {
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int i;
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for (i = 0; i < 16; i++) {
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (caddr[i] != 0) {
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return 1;
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Map the Java level socket option to the platform specific
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * level and option name.
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_MapSocketOption(jint cmd, int *level, int *optname) {
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static struct {
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jint cmd;
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int level;
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int optname;
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } const opts[] = {
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_TCP_NODELAY,           IPPROTO_TCP,    TCP_NODELAY },
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_OOBINLINE,          SOL_SOCKET,     SO_OOBINLINE },
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_LINGER,             SOL_SOCKET,     SO_LINGER },
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_SNDBUF,             SOL_SOCKET,     SO_SNDBUF },
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_RCVBUF,             SOL_SOCKET,     SO_RCVBUF },
90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_KEEPALIVE,          SOL_SOCKET,     SO_KEEPALIVE },
90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_REUSEADDR,          SOL_SOCKET,     SO_REUSEADDR },
90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_SO_BROADCAST,          SOL_SOCKET,     SO_BROADCAST },
90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_IP_TOS,                IPPROTO_IP,     IP_TOS },
90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_IP_MULTICAST_IF2,      IPPROTO_IP,     IP_MULTICAST_IF },
91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        { java_net_SocketOptions_IP_MULTICAST_LOOP,     IPPROTO_IP,     IP_MULTICAST_LOOP },
91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int i;
91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef AF_INET6
91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ipv6_available()) {
91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (cmd) {
919780a0e6392567eb5d1c3425043b092d29590976bYi Kong            // Different multicast options if IPv6 is enabled
92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case java_net_SocketOptions_IP_MULTICAST_IF:
92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case java_net_SocketOptions_IP_MULTICAST_IF2:
92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *level = IPPROTO_IPV6;
92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *optname = IPV6_MULTICAST_IF;
92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0;
92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case java_net_SocketOptions_IP_MULTICAST_LOOP:
92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *level = IPPROTO_IPV6;
92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *optname = IPV6_MULTICAST_LOOP;
92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0;
930780a0e6392567eb5d1c3425043b092d29590976bYi Kong#if (defined(__solaris__) || defined(MACOSX))
931780a0e6392567eb5d1c3425043b092d29590976bYi Kong            // Map IP_TOS request to IPV6_TCLASS
932780a0e6392567eb5d1c3425043b092d29590976bYi Kong            case java_net_SocketOptions_IP_TOS:
933780a0e6392567eb5d1c3425043b092d29590976bYi Kong                *level = IPPROTO_IPV6;
934780a0e6392567eb5d1c3425043b092d29590976bYi Kong                *optname = IPV6_TCLASS;
935780a0e6392567eb5d1c3425043b092d29590976bYi Kong                return 0;
936780a0e6392567eb5d1c3425043b092d29590976bYi Kong#endif
93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Map the Java level option to the native level
94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cmd == opts[i].cmd) {
94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *level = opts[i].level;
94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *optname = opts[i].optname;
94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* not found */
95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return -1;
95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Wrapper for getsockopt system routine - does any necessary
958eb984abe3282ad17cfdea4fdaab96f3029113cb5Yi Kong * pre/post processing to deal with OS specific oddities :-
95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed
96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to compensate for an incorrect value returned by the kernel.
96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_GetSockOpt(int fd, int level, int opt, void *result,
96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               int *len)
96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int rv;
96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    rv = getsockopt(fd, level, opt, result, len);
97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        socklen_t socklen = *len;
97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        rv = getsockopt(fd, level, opt, result, &socklen);
97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        *len = socklen;
97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (rv < 0) {
98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return rv;
98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This
98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stems from additional socket structures in the send
98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and receive buffers.
98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                  || (opt == SO_RCVBUF))) {
99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = *((int *)result);
99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        n /= 2;
99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        *((int *)result) = n;
99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* Workaround for Mac OS treating linger value as
99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *  signed integer
99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef MACOSX
100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == SOL_SOCKET && opt == SO_LINGER) {
100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct linger* to_cast = (struct linger*)result;
100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        to_cast->l_linger = (unsigned short)to_cast->l_linger;
100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return rv;
100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Wrapper for setsockopt system routine - performs any
101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * necessary pre/post processing to deal with OS specific
101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * issue :-
101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * On Solaris need to limit the suggested value for SO_SNDBUF
101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and SO_RCVBUF to the kernel configured limit
101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For IP_TOS socket option need to mask off bits as this
101851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * aren't automatically masked by the kernel and results in
1019780a0e6392567eb5d1c3425043b092d29590976bYi Kong * an error.
102051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
102151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_SetSockOpt(int fd, int level, int  opt, const void *arg,
102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               int len)
102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef IPTOS_TOS_MASK
102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define IPTOS_TOS_MASK 0x1e
102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef IPTOS_PREC_MASK
102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#define IPTOS_PREC_MASK 0xe0
103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(_ALLBSD_SOURCE)
103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(KIPC_MAXSOCKBUF)
103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int mib[3];
103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    size_t rlen;
103651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
103751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
103851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int *bufsize;
103951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __APPLE__
104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static int maxsockbuf = -1;
104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static long maxsockbuf = -1;
104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * IPPROTO/IP_TOS :-
1049780a0e6392567eb5d1c3425043b092d29590976bYi Kong     * 1. IPv6 on Solaris/Mac OS:
1050780a0e6392567eb5d1c3425043b092d29590976bYi Kong     *    Set the TOS OR Traffic Class value to cater for
1051780a0e6392567eb5d1c3425043b092d29590976bYi Kong     *    IPv6 and IPv4 scenarios.
105251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * 2. IPv6 on Linux: By default Linux ignores flowinfo
105351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *    field so enable IPV6_FLOWINFO_SEND so that flowinfo
1054780a0e6392567eb5d1c3425043b092d29590976bYi Kong     *    will be examined. We also set the IPv4 TOS option in this case.
105551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * 3. IPv4: set socket option based on ToS and Precedence
105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *    fields (otherwise get invalid argument)
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == IPPROTO_IP && opt == IP_TOS) {
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int *iptos;
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(AF_INET6) && defined(__linux__)
106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ipv6_available()) {
106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int optval = 1;
1064780a0e6392567eb5d1c3425043b092d29590976bYi Kong            if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
1065780a0e6392567eb5d1c3425043b092d29590976bYi Kong                           (void *)&optval, sizeof(optval)) < 0) {
1066780a0e6392567eb5d1c3425043b092d29590976bYi Kong                return -1;
1067780a0e6392567eb5d1c3425043b092d29590976bYi Kong            }
1068780a0e6392567eb5d1c3425043b092d29590976bYi Kong           /*
1069780a0e6392567eb5d1c3425043b092d29590976bYi Kong            * Let's also set the IPV6_TCLASS flag.
1070780a0e6392567eb5d1c3425043b092d29590976bYi Kong            * Linux appears to allow both IP_TOS and IPV6_TCLASS to be set
1071780a0e6392567eb5d1c3425043b092d29590976bYi Kong            * This helps in mixed environments where IPv4 and IPv6 sockets
1072780a0e6392567eb5d1c3425043b092d29590976bYi Kong            * are connecting.
1073780a0e6392567eb5d1c3425043b092d29590976bYi Kong            */
1074780a0e6392567eb5d1c3425043b092d29590976bYi Kong           if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
1075780a0e6392567eb5d1c3425043b092d29590976bYi Kong                           arg, len) < 0) {
1076780a0e6392567eb5d1c3425043b092d29590976bYi Kong                return -1;
1077780a0e6392567eb5d1c3425043b092d29590976bYi Kong            }
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        iptos = (int *)arg;
1082780a0e6392567eb5d1c3425043b092d29590976bYi Kong        // Android-changed: This is out-dated RFC 1349 scheme. Modern Linux uses
1083780a0e6392567eb5d1c3425043b092d29590976bYi Kong        // Diffsev/ECN, and this mask is no longer relavant.
1084780a0e6392567eb5d1c3425043b092d29590976bYi Kong        // *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the value when it exceeds the system limit.
109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __solaris__
109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == SOL_SOCKET) {
109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int sotype=0, arglen;
109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int *bufsize, maxbuf;
109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int ret;
109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* Attempt with the original size */
109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ret = setsockopt(fd, level, opt, arg, len);
110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return ret;
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* Exceeded system limit so clamp and retry */
110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            arglen = sizeof(sotype);
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           &arglen) < 0) {
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * We try to get tcp_maxbuf (and udp_max_buf) using
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * an ioctl() that isn't available on all versions of Solaris.
111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * If that fails, we use the search algorithm in findMaxBuf()
111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf");
111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (tcp_max_buf == -1) {
111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (tcp_max_buf == -1) {
112151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return -1;
112251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
112351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
112451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                init_tcp_max_buf = 1;
112551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
112651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                udp_max_buf = getParam("/dev/udp", "udp_max_buf");
112751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (udp_max_buf == -1) {
112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
112951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (udp_max_buf == -1) {
113051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return -1;
113151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
113351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                init_udp_max_buf = 1;
113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bufsize = (int *)arg;
113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (*bufsize > maxbuf) {
113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *bufsize = maxbuf;
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
114551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
114651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * On Linux the receive buffer is used for both socket
114751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * structures and the the packet payload. The implication
114851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is that if SO_RCVBUF is too small then small packets
1149780a0e6392567eb5d1c3425043b092d29590976bYi Kong     * must be discarded.
115051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
115251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == SOL_SOCKET && opt == SO_RCVBUF) {
115351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int *bufsize = (int *)arg;
115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (*bufsize < 1024) {
115551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            *bufsize = 1024;
115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(_ALLBSD_SOURCE)
116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * an ENOBUFS error.
116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == SOL_SOCKET) {
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef KIPC_MAXSOCKBUF
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (maxsockbuf == -1) {
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               mib[0] = CTL_KERN;
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               mib[1] = KERN_IPC;
117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               mib[2] = KIPC_MAXSOCKBUF;
117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               rlen = sizeof(maxsockbuf);
117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   maxsockbuf = 1024;
117651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if 1
117851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
117951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                  problem.  It should be removed when kern.ipc.maxsockbuf
118051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                  will be real value. */
118151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               maxsockbuf = (maxsockbuf/5)*4;
118251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
118351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           }
118451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#elif defined(__OpenBSD__)
118551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           maxsockbuf = SB_MAX;
118651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
118751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           maxsockbuf = 64 * 1024;      /* XXX: NetBSD */
118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
118951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           bufsize = (int *)arg;
119151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           if (*bufsize > maxsockbuf) {
119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               *bufsize = maxsockbuf;
119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           }
119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           if (opt == SO_RCVBUF && *bufsize < 1024) {
119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                *bufsize = 1024;
119751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski           }
119851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
120051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
120151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * On Solaris, SO_REUSEADDR will allow multiple datagram
120451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * sockets to bind to the same port.  The network jck tests
120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * for this "feature", so we need to emulate it by turning on
120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * SO_REUSEPORT as well for that combination.
120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int sotype;
121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        socklen_t arglen;
121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        arglen = sizeof(sotype);
121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (sotype == SOCK_DGRAM) {
1218780a0e6392567eb5d1c3425043b092d29590976bYi Kong            setsockopt(fd, level, SO_REUSEPORT, arg, len);
121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return setsockopt(fd, level, opt, arg, len);
122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Wrapper for bind system call - performs any necessary pre/post
122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * processing to deal with OS specific issues :-
123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Linux allows a socket to bind to 127.0.0.255 which must be
123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * caught.
123351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
123451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * On Solaris with IPv6 enabled we must use an exclusive
123551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bind to guaranteed a unique port number across the IPv4 and
123651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * IPv6 port spaces.
123751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
123851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
123951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiint
124051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_Bind(int fd, struct sockaddr *him, int len)
124151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
124251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(__solaris__) && defined(AF_INET6)
124351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int level = -1;
124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int exclbind = -1;
124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int rv;
124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifdef __linux__
124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ## get bugId for this issue - goes back to 1.2.2 port ##
125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ## When IPv6 is enabled this will be an IPv4-mapped
125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * ## with family set to AF_INET6
125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (him->sa_family == AF_INET) {
125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        struct sockaddr_in *sa = (struct sockaddr_in *)him;
125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            errno = EADDRNOTAVAIL;
125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(__solaris__) && defined(AF_INET6)
126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /*
126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Solaris has seperate IPv4 and IPv6 port spaces so we
126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * use an exclusive bind when SO_REUSEADDR is not used to
126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * give the illusion of a unified port space.
126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This also avoids problems with IPv6 sockets connecting
126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to IPv4 mapped addresses whereby the socket conversion
127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * results in a late bind that fails because the
127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * corresponding IPv4 port is in use.
127251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
127351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (ipv6_available()) {
127451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int arg, len;
127551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
127651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        len = sizeof(arg);
127751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
127851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       (char *)&arg, &len) == 0) {
127951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (useExclBind || arg == 0) {
128051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /*
128151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
128251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * property is true so enable TCP_EXCLBIND or
128351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 * UDP_EXCLBIND
128451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                 */
128551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                len = sizeof(arg);
128651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
128751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               &len) == 0) {
128851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (arg == SOCK_STREAM) {
128951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        level = IPPROTO_TCP;
129051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        exclbind = TCP_EXCLBIND;
129151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
129251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        level = IPPROTO_UDP;
129351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        exclbind = UDP_EXCLBIND;
129451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
129551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
129651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
129751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                arg = 1;
129851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                setsockopt(fd, level, exclbind, (char *)&arg,
129951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           sizeof(arg));
130051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
130151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
130251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
130351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
130451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
130551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
130651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    rv = bind(fd, him, len);
130751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
130851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#if defined(__solaris__) && defined(AF_INET6)
130951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (rv < 0) {
131051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int en = errno;
131151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* Restore *_EXCLBIND if the bind fails */
131251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (exclbind != -1) {
131351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int arg = 0;
131451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            setsockopt(fd, level, exclbind, (char *)&arg,
131551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                       sizeof(arg));
131651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
131751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        errno = en;
131851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
131951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
132051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
132151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return rv;
132251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Wrapper for select/poll with timeout on a single file descriptor.
132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * flags (defined in net_util_md.h can be any combination of
132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The function will return when either the socket is ready for one
1331780a0e6392567eb5d1c3425043b092d29590976bYi Kong * of the specified operations or the timeout expired.
133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It returns the time left from the timeout (possibly 0), or -1 if it expired.
133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskijint
133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiNET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski{
133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jlong prevTime = JVM_CurrentTimeMillis(env, 0);
134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jint read_rv;
134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    while (1) {
134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        jlong newTime;
134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#ifndef USE_SELECT
134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          struct pollfd pfd;
134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          pfd.fd = fd;
134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          pfd.events = 0;
134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_READ)
135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pfd.events |= POLLIN;
135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_WRITE)
135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pfd.events |= POLLOUT;
135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_CONNECT)
135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pfd.events |= POLLOUT;
135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          errno = 0;
135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          read_rv = NET_Poll(&pfd, 1, timeout);
135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#else
136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          fd_set rd, wr, ex;
136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          struct timeval t;
136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          t.tv_sec = timeout / 1000;
136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          t.tv_usec = (timeout % 1000) * 1000;
136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          FD_ZERO(&rd);
136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          FD_ZERO(&wr);
136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          FD_ZERO(&ex);
137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_READ) {
137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FD_SET(fd, &rd);
137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          }
137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_WRITE) {
137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FD_SET(fd, &wr);
137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          }
137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          if (flags & NET_WAIT_CONNECT) {
137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FD_SET(fd, &wr);
137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            FD_SET(fd, &ex);
137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          }
138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          errno = 0;
138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#endif
138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        newTime = JVM_CurrentTimeMillis(env, 0);
138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        timeout -= (newTime - prevTime);
138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (timeout <= 0) {
138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          return read_rv > 0 ? 0 : -1;
139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
1391d0860af7cc7e4d5c29fcccc97c66121b7c8cd226Przemyslaw Szczepaniak        prevTime = newTime;
139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (read_rv > 0) {
139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski          break;
139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      } /* while */
139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return timeout;
140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
140255cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong
14033442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong#if 0
14043442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong// Stripped out unused code.
140555cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong// http://b/27301951
140655cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong__attribute__((destructor))
140755cf88a557325b05e27443c6ce28ed4d652bf471Yi Kongstatic void netUtilCleanUp() {
140855cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong    if (loRoutes != 0) free(loRoutes);
140955cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong    if (localifs != 0) free(localifs);
141055cf88a557325b05e27443c6ce28ed4d652bf471Yi Kong}
14113442abd5bcb4d4d0bfdcc08bf660cbf61ae82bf8Yi Kong#endif
1412