/*
 * Class:     java_net_DualStackPlainDatagramSocketImpl
 * Method:    socketCreate
 * Signature: (Z)I
 */
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate
  (JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) {
    int fd, rv, opt=0, t=TRUE;
    DWORD x1, x2; /* ignored result codes */

    fd = (int) socket(AF_INET6, SOCK_DGRAM, 0);
    if (fd == INVALID_SOCKET) {
        NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
        return -1;
    }

    rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
    if (rv == SOCKET_ERROR) {
        NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
        closesocket(fd);
        return -1;
    }

    SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
    NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));

    /* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which
     * returns connection reset errors on unconnected UDP sockets (as well
     * as connected sockets). The solution is to only enable this feature
     * when the socket is connected.
     */
    t = FALSE;
    WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0);

    return fd;
}
/*
 * Class:     java_net_DualStackPlainSocketImpl
 * Method:    setIntOption
 * Signature: (III)V
 */
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption
  (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value) {

    int level, opt;
    struct linger linger;
    char *parg;
    int arglen;

    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
        JNU_ThrowByNameWithLastError(env,
                                     JNU_JAVANETPKG "SocketException",
                                     "Invalid option");
        return;
    }

    if (opt == java_net_SocketOptions_SO_LINGER) {
        parg = (char *)&linger;
        arglen = sizeof(linger);
        if (value >= 0) {
            linger.l_onoff = 1;
            linger.l_linger = (unsigned short)value;
        } else {
            linger.l_onoff = 0;
            linger.l_linger = 0;
        }
    } else {
        parg = (char *)&value;
        arglen = sizeof(value);
    }

    if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
    }
}
Пример #3
0
JNIEXPORT int JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
                            jboolean reuse)
{
    int fd;

#ifdef AF_INET6
    if (ipv6_available())
	fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
    else
#endif /* AF_INET6 */
	fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);

    if (fd < 0) {
	return handleSocketError(env, errno);
    }
    if (reuse) {
	int arg = 1;
        if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
                           sizeof(arg)) < 0) {
            JNU_ThrowByNameWithLastError(env,
                                         JNU_JAVANETPKG "SocketException",
                                         "sun.nio.ch.Net.setIntOption");
        }
    }
    return fd;
}
Пример #4
0
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
                                  jboolean mayNeedConversion, jint level, jint opt, jint arg)
{
    struct linger linger;
    char *parg;
    int arglen, n;

    if (level == SOL_SOCKET && opt == SO_LINGER) {
        parg = (char *)&linger;
        arglen = sizeof(linger);
        if (arg >= 0) {
            linger.l_onoff = 1;
            linger.l_linger = (unsigned short)arg;
        } else {
            linger.l_onoff = 0;
            linger.l_linger = 0;
        }
    } else {
        parg = (char *)&arg;
        arglen = sizeof(arg);
    }

    if (mayNeedConversion) {
        n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
    } else {
        n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
    }
    if (n < 0)
        handleSocketError(env, WSAGetLastError());
}
Пример #5
0
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
                                  jboolean mayNeedConversion, jint level,
                                  jint opt, jint arg, jboolean isIPv6)
{
    int result;
    struct linger linger;
    u_char carg;
    void *parg;
    socklen_t arglen;
    int n;

    /* Option value is an int except for a few specific cases */

    parg = (void*)&arg;
    arglen = sizeof(arg);

    if (level == IPPROTO_IP &&
        (opt == IP_MULTICAST_TTL || opt == IP_MULTICAST_LOOP)) {
        parg = (void*)&carg;
        arglen = sizeof(carg);
        carg = (u_char)arg;
    }

    if (level == SOL_SOCKET && opt == SO_LINGER) {
        parg = (void *)&linger;
        arglen = sizeof(linger);
        if (arg >= 0) {
            linger.l_onoff = 1;
            linger.l_linger = arg;
        } else {
            linger.l_onoff = 0;
            linger.l_linger = 0;
        }
    }

    if (mayNeedConversion) {
        n = NET_SetSockOpt(fdval(env, fdo), level, opt, parg, arglen);
    } else {
        n = setsockopt(fdval(env, fdo), level, opt, parg, arglen);
    }
    if (n < 0) {
        JNU_ThrowByNameWithLastError(env,
                                     JNU_JAVANETPKG "SocketException",
                                     "sun.nio.ch.Net.setIntOption");
    }
#ifdef __linux__
    if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS && isIPv6) {
        // set the V4 option also
        setsockopt(fdval(env, fdo), IPPROTO_IP, IP_TOS, parg, arglen);
    }
#endif
}
/*
 * Class:     java_net_DualStackPlainDatagramSocketImpl
 * Method:    socketSetIntOption
 * Signature: (III)V
 */
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
  (JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) {
    int level = 0, opt = 0;

    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                     "Invalid option");
        return;
    }

    if (NET_SetSockOpt(fd, level, opt, (char *)&value, sizeof(value)) < 0) {
        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
    }
}
Пример #7
0
JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz,
				  jobject fdo, jint opt, jint arg)
{
    int klevel, kopt;
    int result;
    struct linger linger;
    void *parg;
    int arglen;

    if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
	JNU_ThrowByNameWithLastError(env,
                                     JNU_JAVANETPKG "SocketException",
				     "Unsupported socket option");
	return;
    }

    if (opt == java_net_SocketOptions_SO_LINGER) {
	parg = (void *)&linger;
	arglen = sizeof(linger);
	if (arg >= 0) {
	    linger.l_onoff = 1;
	    linger.l_linger = arg;
	} else {
	    linger.l_onoff = 0;
	    linger.l_linger = 0;
	}
    } else {
	parg = (void *)&arg;
	arglen = sizeof(arg);
    }

    if (NET_SetSockOpt(fdval(env, fdo), klevel, kopt, parg, arglen) < 0) {
	JNU_ThrowByNameWithLastError(env,
				     JNU_JAVANETPKG "SocketException",
				     "sun.nio.ch.Net.setIntOption");
    }
}
Пример #8
0
/*
 * Class:     sun_nio_ch_sctp_SctpNet
 * Method:    getLocalAddresses0
 * Signature: (I)[Ljava/net/SocketAddress;
 */
JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getLocalAddresses0
  (JNIEnv *env, jclass klass, jint fd) {
    void *addr_buf, *laddr;
    struct sockaddr* sap;
    int i, addrCount;
    jobjectArray isaa;

#ifdef __solaris__
    if ((addrCount = nio_sctp_getladdrs(fd, 0, (void **)&addr_buf)) == -1) {
#else /* __linux__ */
    if ((addrCount = nio_sctp_getladdrs(fd, 0, (struct sockaddr **)&addr_buf)) == -1) {
#endif
        handleSocketError(env, errno);
        return NULL;
    }

    if (addrCount < 1)
        return NULL;

    if (isaCls == 0) {
        initializeISA(env);
        CHECK_NULL_RETURN(isaCls, NULL);
    }

    isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
    if (isaa == NULL) {
        nio_sctp_freeladdrs(addr_buf);
        return NULL;
    }

    laddr = addr_buf;
    for (i=0; i<addrCount; i++) {
        int port = 0;
        jobject isa = NULL, ia;
        sap = (struct sockaddr*)addr_buf;
        ia = NET_SockaddrToInetAddress(env, sap, &port);
        if (ia != NULL)
            isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
        if (isa == NULL)
            break;
        (*env)->SetObjectArrayElement(env, isaa, i, isa);

        if (sap->sa_family == AF_INET)
            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
        else
            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
    }

    nio_sctp_freeladdrs(laddr);
    return isaa;
}

jobjectArray getRemoteAddresses
  (JNIEnv *env, jint fd, sctp_assoc_t id) {
    void *addr_buf, *paddr;
    struct sockaddr* sap;
    int i, addrCount;
    jobjectArray isaa;

#if __solaris__
    if ((addrCount = nio_sctp_getpaddrs(fd, id, (void **)&addr_buf)) == -1) {
#else /* __linux__ */
    if ((addrCount = nio_sctp_getpaddrs(fd, id, (struct sockaddr**)&addr_buf)) == -1) {
#endif
        handleSocketError(env, errno);
        return NULL;
    }

    if (addrCount < 1)
        return NULL;

    if (isaCls == 0) {
        initializeISA(env);
        CHECK_NULL_RETURN(isaCls, NULL);
    }

    isaa = (*env)->NewObjectArray(env, addrCount, isaCls, NULL);
    if (isaa == NULL) {
        nio_sctp_freepaddrs(addr_buf);
        return NULL;
    }

    paddr = addr_buf;
    for (i=0; i<addrCount; i++) {
        jobject ia, isa = NULL;
        int port = 0;
        sap = (struct sockaddr*)addr_buf;
        ia = NET_SockaddrToInetAddress(env, sap, &port);
        if (ia != NULL)
            isa = (*env)->NewObject(env, isaCls, isaCtrID, ia, port);
        if (isa == NULL)
            break;
        (*env)->SetObjectArrayElement(env, isaa, i, isa);

        if (sap->sa_family == AF_INET)
            addr_buf = ((struct sockaddr_in*)addr_buf) + 1;
        else
            addr_buf = ((struct sockaddr_in6*)addr_buf) + 1;
    }

    nio_sctp_freepaddrs(paddr);

    return isaa;
}

 /*
 * Class:     sun_nio_ch_sctp_SctpNet
 * Method:    getRemoteAddresses0
 * Signature: (II)[Ljava/net/SocketAddress;
 */
JNIEXPORT jobjectArray JNICALL Java_sun_nio_ch_sctp_SctpNet_getRemoteAddresses0
  (JNIEnv *env, jclass klass, jint fd, jint assocId) {
    return getRemoteAddresses(env, fd, assocId);
}

/* Map the Java level option to the native level */
int mapSocketOption
  (jint cmd, int *level, int *optname) {
    static struct {
        jint cmd;
        int level;
        int optname;
    } const opts[] = {
        { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_DISABLE_FRAGMENTS,   IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS },
        { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_EXPLICIT_COMPLETE,   IPPROTO_SCTP, SCTP_EXPLICIT_EOR },
        { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_FRAGMENT_INTERLEAVE, IPPROTO_SCTP, SCTP_FRAGMENT_INTERLEAVE },
        { sun_nio_ch_sctp_SctpStdSocketOption_SCTP_NODELAY,             IPPROTO_SCTP, SCTP_NODELAY },
        { sun_nio_ch_sctp_SctpStdSocketOption_SO_SNDBUF,                SOL_SOCKET,   SO_SNDBUF },
        { sun_nio_ch_sctp_SctpStdSocketOption_SO_RCVBUF,                SOL_SOCKET,   SO_RCVBUF },
        { sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER,                SOL_SOCKET,   SO_LINGER } };

    int i;
    for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
        if (cmd == opts[i].cmd) {
            *level = opts[i].level;
            *optname = opts[i].optname;
            return 0;
        }
    }

    /* not found */
    return -1;
}

/*
 * Class:     sun_nio_ch_sctp_SctpNet
 * Method:    setIntOption0
 * Signature: (III)V
 */
JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpNet_setIntOption0
  (JNIEnv *env, jclass klass, jint fd, jint opt, int arg) {
    int klevel, kopt;
    int result;
    struct linger linger;
    void *parg;
    int arglen;

    if (mapSocketOption(opt, &klevel, &kopt) < 0) {
        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                     "Unsupported socket option");
        return;
    }

    if (opt == sun_nio_ch_sctp_SctpStdSocketOption_SO_LINGER) {
        parg = (void *)&linger;
        arglen = sizeof(linger);
        if (arg >= 0) {
            linger.l_onoff = 1;
            linger.l_linger = arg;
        } else {
            linger.l_onoff = 0;
            linger.l_linger = 0;
        }
    } else {
        parg = (void *)&arg;
        arglen = sizeof(arg);
    }

    if (NET_SetSockOpt(fd, klevel, kopt, parg, arglen) < 0) {
        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                     "sun_nio_ch_sctp_SctpNet.setIntOption0");
    }
}