$OpenBSD: patch-jdk_src_solaris_native_java_net_net_util_md_c,v 1.3 2009/05/23 03:03:25 kurt Exp $
--- jdk/src/solaris/native/java/net/net_util_md.c.orig	Fri May  8 03:35:07 2009
+++ jdk/src/solaris/native/java/net/net_util_md.c	Mon May 18 19:41:43 2009
@@ -34,6 +34,15 @@
 #include <stdlib.h>
 #include <dlfcn.h>
 
+#ifdef _ALLBSD_SOURCE
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#endif
+
+#ifdef __OpenBSD__
+#include <sys/socketvar.h>
+#endif
+
 #ifdef __solaris__
 #include <sys/sockio.h>
 #include <stropts.h>
@@ -219,8 +228,16 @@ NET_GetFileDescriptorID(JNIEnv *env)
     return (*env)->GetFieldID(env, cls, "fd", "I");
 }
 
+#if defined(DONT_ENABLE_IPV6)
 jint  IPv6_supported()
 {
+    return JNI_FALSE;
+}
+
+#else /* !DONT_ENABLE_IPV6 */
+
+jint  IPv6_supported()
+{
 #ifndef AF_INET6
     return JNI_FALSE;
 #endif
@@ -355,6 +372,7 @@ jint  IPv6_supported()
     close(fd);
     return JNI_TRUE;
 }
+#endif /* DONT_ENABLE_IPV6 */
 
 void
 NET_AllocSockaddr(struct sockaddr **him, int *len) {
@@ -688,6 +706,10 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, 
         him6->sin6_family = AF_INET6;
         *len = sizeof(struct sockaddr_in6) ;
 
+#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
+// XXXBSD: should we do something with scope id here ? see below linux comment
+#endif
+
         /*
          * On Linux if we are connecting to a link-local address
          * we need to specify the interface in the scope_id (2.4 kernel only)
@@ -1094,7 +1116,6 @@ NET_GetSockOpt(int fd, int level, int opt, void *resul
         *len = socklen;
     }
 #endif
-
     if (rv < 0) {
         return rv;
     }
@@ -1141,6 +1162,24 @@ NET_SetSockOpt(int fd, int level, int  opt, const void
 #define IPTOS_PREC_MASK 0xe0
 #endif
 
+#if defined(_ALLBSD_SOURCE)
+#if defined(KIPC_MAXSOCKBUF)
+    int mib[3];
+    size_t rlen;
+#endif
+
+    int *bufsize;
+
+#ifdef __APPLE__
+    static int maxsockbuf = -1;
+#else
+    static long maxsockbuf = -1;
+#endif
+
+    int addopt;
+    struct linger *ling;
+#endif
+
     /*
      * IPPROTO/IP_TOS :-
      * 1. IPv6 on Solaris: no-op and will be set in flowinfo
@@ -1173,6 +1212,10 @@ NET_SetSockOpt(int fd, int level, int  opt, const void
         *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
     }
 
+#if defined(AF_INET6) && defined(_ALLBSD_SOURCE)
+// XXXBSD: to be implemented ?
+#endif
+
     /*
      * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris need to
      * ensure that value is <= max_buf as otherwise we get
@@ -1181,7 +1224,8 @@ NET_SetSockOpt(int fd, int level, int  opt, const void
 #ifdef __solaris__
     if (level == SOL_SOCKET) {
         if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
-            int sotype, arglen;
+            int sotype;
+            socklen_t arglen;
             int *bufsize, maxbuf;
 
             if (!init_max_buf) {
@@ -1220,6 +1264,84 @@ NET_SetSockOpt(int fd, int level, int  opt, const void
     }
 #endif
 
+#if defined(_ALLBSD_SOURCE)
+    /*
+     * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
+     * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
+     * an ENOBUFS error.
+     */
+    if (level == SOL_SOCKET) {
+        if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
+#ifdef KIPC_MAXSOCKBUF
+            if (maxsockbuf == -1) {
+               mib[0] = CTL_KERN;
+               mib[1] = KERN_IPC;
+               mib[2] = KIPC_MAXSOCKBUF;
+               rlen = sizeof(maxsockbuf);
+               if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
+                   maxsockbuf = 1024;
+
+#if 1
+               /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
+                  problem.  It should be removed when kern.ipc.maxsockbuf
+                  will be real value. */
+               maxsockbuf = (maxsockbuf/5)*4;
+#endif
+           }
+#elif defined(__OpenBSD__)
+	   maxsockbuf = SB_MAX;
+#else
+	   maxsockbuf = 64 * 1024;	/* XXX: NetBSD */
+#endif
+
+           bufsize = (int *)arg;
+           if (*bufsize > maxsockbuf) {
+               *bufsize = maxsockbuf;
+           }
+
+	   if (opt == SO_RCVBUF && *bufsize < 1024) {
+		*bufsize = 1024;
+	   }
+
+        }
+    }
+
+    /*
+     * On Solaris, SO_REUSEADDR will allow multiple datagram
+     * sockets to bind to the same port.  The network jck tests
+     * for this "feature", so we need to emulate it by turning on
+     * SO_REUSEPORT as well for that combination.
+     */
+    if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
+        int sotype;
+        socklen_t arglen;
+
+        arglen = sizeof(sotype);
+        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
+            return -1;
+        }
+
+        if (sotype == SOCK_DGRAM) {
+            addopt = SO_REUSEPORT;
+            setsockopt(fd, level, addopt, arg, len);
+        }
+    }
+
+    /*
+     * Don't allow SO_LINGER value to be too big.
+     * Current max value (240) is empiric value based on tcp_timer.h's
+     * constant TCP_LINGERTIME, which was doubled.
+     *
+     * XXXBSD: maybe we should step it down to 120 ?
+     */
+    if (level == SOL_SOCKET && opt == SO_LINGER) {
+        ling = (struct linger *)arg;
+       if (ling->l_linger > 240 || ling->l_linger < 0) {
+           ling->l_linger = 240;
+       }
+    }
+#endif
+
     return setsockopt(fd, level, opt, arg, len);
 }
 
@@ -1270,7 +1392,8 @@ NET_Bind(int fd, struct sockaddr *him, int len)
      * corresponding IPv4 port is in use.
      */
     if (ipv6_available()) {
-        int arg, len;
+        int arg;
+        socklen_t len;
 
         len = sizeof(arg);
         if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg,
