From lansil@fuzzilicious.fuzzynerd.com  Tue Apr  8 09:22:30 2003
Return-Path: <lansil@fuzzilicious.fuzzynerd.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 408EB37B401
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  8 Apr 2003 09:22:30 -0700 (PDT)
Received: from fuzzilicious.fuzzynerd.com (ip-60-65.academy.rpi.edu [128.113.60.65])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 7527F43FAF
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  8 Apr 2003 09:22:29 -0700 (PDT)
	(envelope-from lansil@fuzzilicious.fuzzynerd.com)
Received: from fuzzilicious.fuzzynerd.com (localhost [127.0.0.1])
	by fuzzilicious.fuzzynerd.com (8.12.9/8.12.8) with ESMTP id h38GKV8i023550
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 8 Apr 2003 12:20:31 -0400 (EDT)
	(envelope-from lansil@fuzzilicious.fuzzynerd.com)
Received: (from lansil@localhost)
	by fuzzilicious.fuzzynerd.com (8.12.9/8.12.8/Submit) id h38GKVSQ023549;
	Tue, 8 Apr 2003 12:20:31 -0400 (EDT)
Message-Id: <200304081620.h38GKVSQ023549@fuzzilicious.fuzzynerd.com>
Date: Tue, 8 Apr 2003 12:20:31 -0400 (EDT)
From: Larry Lansing <lansil@fuzzilicious.fuzzynerd.com>
Reply-To: Larry Lansing <lansil@fuzzilicious.fuzzynerd.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: java/jdk14: broken java.net.NetworkInterface calls (SIOCGIFCONF)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         50729
>Category:       java
>Synopsis:       java/jdk14: broken java.net.NetworkInterface calls (SIOCGIFCONF)
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    phantom
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 08 09:30:16 PDT 2003
>Closed-Date:    Wed Nov 05 12:52:56 PST 2003
>Last-Modified:  Wed Nov 05 12:52:56 PST 2003
>Originator:     Larry Lansing
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
Rensselaer Polytechnic Institute
>Environment:
System: FreeBSD fuzzilicious.fuzzynerd.com 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Tue Apr 1 11:50:43 EST 2003 root@fuzzilicious.fuzzynerd.com:/usr/obj/usr/src/sys/FUZZILICIOUS i386
>Description:
Parts of the java.net.NetworkInterface class are broken, due a
Linux-ism in this class' JNI code.  If nothing else, this causes
java.net.NetworkInterface.getNetworkInterfaces(); to always fail.

Basically, the code is linux-specific in its handling of the
SIOCGIFCONF ioctl.  The SIOCGIFCONF ioctl takes a pointer to a ifconf
struct (ifc).  The struct has two relevant fields: a memory buffer
(ifc->buf), and the size of that buffer (ifc->len).  SIOCGIFCONF fills
ifc->buf with information about all network interfaces, and sets
ifc->len to the amount of memory used in ifc->buf.  Unfortunately, due
to the nature of SIOCGIFCONF, there is no good way of telling how big
a buffer to pass to the ioctl.

On Linux, it looks like if you pass a NULL ifc->buf to SIOCGIFCONF,
the returned ifc->len will be the amount of memory necessary to hold
information about all network interfaces on the machine.  A second
call to SIOCGIFCONF can be made with a correctly-sized buffer.  On
Solaris, SIOCGIFNUM can be used to calculate the size of the buffer to
send to SIOCGIFCONF, instead.  FreeBSD does not support the
SIOCGIFCONF Linux-ism, and does not support SIOCGIFNUM.

>How-To-Repeat:
Try using java.net.NetworkInterface.getNetworkInterfaces();
Alternately, try running FreeNet with this JDK.
>Fix:
Evil Kludge (quick fix): put the enclosed patch file in
/usr/ports/java/jdk14/files, as patch-NetworkInterface.c

The enclosed patch uses a "pretty big" buffer (32k) to make the first
call to the SIOCGIFCONF ioctl, and then resizes it down to only the
amount of memory necessary.  This should make the NetworkInterface
code work fine (although perhaps inefficiently) on any machine with
less than (roughly) 100 network interfaces.  This is the WRONG WAY TO
DO IT, but it makes the JDK14 port more useful, until someone writes a
better patch.  It also allows FreeNet to run under FreeBSD.

A portable (but rather bad) solution is to make repeated calls to the
SIOCGIFCONF ioctl, and grow ifc->buf on each call, until some
algorithm decides that all the interfaces are contained in the
resulting buffer.  The FreeBSD bind source code does this--grep for
SIOCGIFCONF.

I've heard that a better (although BSD-specific) way of doing things
would be to use getifaddrs().  Look at the source code to ifconfig,
for an example of this.  I've found references to FreeBSD sysctl that
should work, too.

Finally, one other potential solution is to add support for the
above-mentioned Linux-ism to the FreeBSD SIOCGIFCONF ioctl.  This
would make FreeBSD more Linux-compatible, but I don't know enough to
claim that this is a "good idea".

--- ../../j2se/src/solaris/native/java/net/NetworkInterface.c.orig   Sat Apr  5 
05:12:44 2003
+++ ../../j2se/src/solaris/native/java/net/NetworkInterface.c   Sat Apr  5 05:12
:36 2003
@@ -488,7 +488,16 @@
     /* need to do a dummy SIOCGIFCONF to determine the buffer size.
      * SIOCGIFCOUNT doesn't work
      */
-    ifc.ifc_buf = NULL;
+    buf = (char *)malloc(32768);
+    if (!buf) {
+        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+        (void) close(sock);
+        return ifs;
+    }
+
+    ifc.ifc_buf = buf;
+    ifc.ifc_len = 32768;
+
     if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
                          "ioctl SIOCGIFCONF failed");
@@ -496,6 +505,7 @@
         return ifs;
     }
     bufsize = ifc.ifc_len;
+    free(buf);
 #else
     if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
         NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
>Release-Note:
>Audit-Trail:

From: Larry Lansing <lansil@fuzzynerd.com>
To: FreeBSD-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: java/50729: java/jdk14: broken java.net.NetworkInterface calls (SIOCGIFCONF)
Date: Tue, 8 Apr 2003 15:11:00 -0400

 Oops.  Forgot to add a "free" to the first call to the SIOCGIFCONF
 ioctl.  Use this patch instead.
 
 +5 points for writing a useful patch in a PR.  -10 points for
 including a memory leak.
 
 --- NetworkInterface.c.orig     Sat Apr  5 12:30:32 2003
 +++ NetworkInterface.c  Tue Apr  8 15:04:32 2003
 @@ -488,14 +488,25 @@
      /* need to do a dummy SIOCGIFCONF to determine the buffer size.
       * SIOCGIFCOUNT doesn't work
       */
 -    ifc.ifc_buf = NULL;
 +    buf = (char *)malloc(32768);
 +    if (!buf) {
 +        JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
 +        (void) close(sock);
 +        return ifs;
 +    }
 +
 +    ifc.ifc_buf = buf;
 +    ifc.ifc_len = 32768;
 +
      if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
          NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
                           "ioctl SIOCGIFCONF failed");
          close(sock);
 +        free(buf);
          return ifs;
      }
      bufsize = ifc.ifc_len;
 +    free(buf);
  #else
      if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
          NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
 
 -- 
 Lawrence S. Lansing
 Project Links Technical Manager
 RPI Math Department
 http://links.math.rpi.edu/
Responsible-Changed-From-To: freebsd-java->phantom 
Responsible-Changed-By: phantom 
Responsible-Changed-When: Sat Jun 14 03:41:59 PDT 2003 
Responsible-Changed-Why:  
My area.  My victim 


http://www.freebsd.org/cgi/query-pr.cgi?pr=50729 
State-Changed-From-To: open->closed 
State-Changed-By: phantom 
State-Changed-When: Wed Nov 5 12:51:33 PST 2003 
State-Changed-Why:  
Fixed in different way (using getifaddrs(3)).  Fixed version was 
released with jdk1.4.1-p4 


http://www.freebsd.org/cgi/query-pr.cgi?pr=50729 
>Unformatted:
