Merge "Remove java.nio.channels.* classes without test coverage."
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index bbe2345..5f9cceb 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -87,6 +87,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-all
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_REQUIRED_MODULES := tzdata
@@ -101,6 +102,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-oj
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-all
@@ -117,6 +119,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-libart
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-all
@@ -135,6 +138,7 @@
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_DEX_PREOPT := false
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-oj-testdex
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-all
@@ -151,6 +155,7 @@
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_DEX_PREOPT := false
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-libart-testdex
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-all
@@ -218,6 +223,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-all-hostdex
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_REQUIRED_MODULES := tzdata-host
@@ -232,6 +238,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-oj-hostdex
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/ojluni/NOTICE
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -248,6 +255,7 @@
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-libart-hostdex
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_JAVA_LIBRARIES := core-oj-hostdex
diff --git a/java_tests_blacklist b/java_tests_blacklist
index 97782ea..c0fbc88 100644
--- a/java_tests_blacklist
+++ b/java_tests_blacklist
@@ -1,7 +1,5 @@
 luni/src/test/java/tests/security/cert/X509CRLSelector2Test.java
 luni/src/test/java/tests/security/cert/X509CertSelectorTest.java
-luni/src/test/java/libcore/net/url/UrlUtilsTest.java
 luni/src/test/java/libcore/java/util/zip/Zip64Test.java
 luni/src/test/java/libcore/java/util/zip/Zip64FileTest.java
-luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
 luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
diff --git a/luni/src/main/native/NetworkUtilities.cpp b/luni/src/main/native/NetworkUtilities.cpp
index e357b4a..b285a01 100644
--- a/luni/src/main/native/NetworkUtilities.cpp
+++ b/luni/src/main/native/NetworkUtilities.cpp
@@ -116,8 +116,11 @@
     }
 
     // Get the byte array that stores the IP address bytes in the InetAddress.
-    static jmethodID bytesMid = env->GetMethodID(JniConstants::inetAddressClass, "getAddressInternal", "()[B");
+    static jmethodID bytesMid = env->GetMethodID(JniConstants::inetAddressClass, "getAddress", "()[B");
     ScopedLocalRef<jbyteArray> addressBytes(env, reinterpret_cast<jbyteArray>(env->CallObjectMethod(inetAddress, bytesMid)));
+    if (env->ExceptionCheck()) {
+        return false;
+    }
     if (addressBytes.get() == NULL) {
         jniThrowNullPointerException(env, NULL);
         return false;
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index d2c4058..552c2a1 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -49,7 +49,7 @@
     fis.close();
 
     ServerSocket s = new ServerSocket();
-    assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl().getFileDescriptor()).st_mode));
+    assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl().getFD$()).st_mode));
     s.close();
   }
 
diff --git a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
index adaa931..3e82690 100644
--- a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
+++ b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
@@ -37,7 +37,7 @@
     fis.close();
 
     ServerSocket s = new ServerSocket();
-    assertTrue(s.getImpl().getFileDescriptor().isSocket$());
+    assertTrue(s.getImpl().getFD$().isSocket$());
     s.close();
   }
 }
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index ef3a228..73cb7ac 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -31,6 +31,9 @@
 import java.util.Set;
 import libcore.io.IoUtils;
 
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 public class NetworkInterfaceTest extends TestCase {
     // http://code.google.com/p/android/issues/detail?id=13784
     private final static int ARPHRD_ETHER = 1; // from if_arp.h
@@ -143,13 +146,9 @@
         }
     }
 
-    // Returns true if interface by name ifName is Ethernet
-    private boolean isEthernet(String ifName) throws Exception {
-        String s = IoUtils.readFileAsString("/sys/class/net/" + ifName + "/type").trim();
-        if (s.startsWith("0x")) {
-            return (Integer.parseInt(s.substring(2), 16) == ARPHRD_ETHER);
-        } else {
-            return (Integer.parseInt(s) == ARPHRD_ETHER);
-        }
+    // Is ifName a name of a Ethernet device?
+    private static Pattern ethernetNamePattern = Pattern.compile("^(eth|wlan)[0-9]+$");
+    private static boolean isEthernet(String ifName) throws Exception {
+        return ethernetNamePattern.matcher(ifName).matches();
     }
 }
diff --git a/luni/src/test/java/libcore/java/sql/OldPreparedStatementTest.java b/luni/src/test/java/libcore/java/sql/OldPreparedStatementTest.java
index 8fd8665..9c99e62 100755
--- a/luni/src/test/java/libcore/java/sql/OldPreparedStatementTest.java
+++ b/luni/src/test/java/libcore/java/sql/OldPreparedStatementTest.java
@@ -272,8 +272,7 @@
         String[] queries2 = {
                 "update zoo set name='Masha', family='cat' where id=;",
                 "insert into hutch (id, animal_id, address) values (1, ?,'Birds-house, 1');",
-                "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');",
-                "create view address as select address from hutch where animal_id=?"};
+                "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');"};
 
         for (int i = 0; i < queries2.length; i++) {
             PreparedStatement ps = null;
@@ -324,41 +323,40 @@
 
     // TODO Crashes VM. Fix later.
     public void testExecuteUpdate() throws SQLException {
-          String[] queries1 = { "insert into hutch (id, animal_id, address) values (1, ?, 'Birds-house, 1');",
-                              "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');",
-                              "create view address as select address from hutch where animal_id=2" };
+        String[] queries1 = { "insert into hutch (id, animal_id, address) values (1, ?, 'Birds-house, 1');",
+                "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');"};
 
-          for (int i = 0; i < queries1.length; i++) {
-              PreparedStatement ps = null;
-              try {
-                  ps = conn.prepareStatement(queries1[i]);
-                  ps.executeUpdate();
-                  fail("SQLException is not thrown for query: " + queries1[i]);
-          } catch(SQLException sqle) {
-              // expected
-          } finally {
-              try {
-                  ps.close();
-              } catch(Exception ee) {}
-          }
-      }
+        for (int i = 0; i < queries1.length; i++) {
+            PreparedStatement ps = null;
+            try {
+                ps = conn.prepareStatement(queries1[i]);
+                ps.executeUpdate();
+                fail("SQLException is not thrown for query: " + queries1[i]);
+            } catch(SQLException sqle) {
+                // expected
+            } finally {
+                try {
+                    ps.close();
+                } catch(Exception ee) {}
+            }
+        }
 
-          String query = "update zoo set name='Masha', family='cat' where id=?;";
-          PreparedStatement ps = null;
-          try {
-              ps = conn.prepareStatement(query);
-              ps.setInt(1, 2);
-              int updateCount = ps.executeUpdate();
-              assertEquals(1, updateCount);
-              ps.setInt(1, 1);
-              int updateCount1 = ps.executeUpdate();
-              assertEquals(1, updateCount1);
-          } finally {
-              try {
-                  ps.close();
-              } catch(Exception ee) {}
-          }
-      }
+        String query = "update zoo set name='Masha', family='cat' where id=?;";
+        PreparedStatement ps = null;
+        try {
+            ps = conn.prepareStatement(query);
+            ps.setInt(1, 2);
+            int updateCount = ps.executeUpdate();
+            assertEquals(1, updateCount);
+            ps.setInt(1, 1);
+            int updateCount1 = ps.executeUpdate();
+            assertEquals(1, updateCount1);
+        } finally {
+            try {
+                ps.close();
+            } catch(Exception ee) {}
+        }
+    }
 
     /**
      * TODO Doesn't pass. according to spec, it is possible to invoke the
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java b/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
index c7667b9..bf10c3e 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipEntryTest.java
@@ -145,23 +145,28 @@
     zipFile.close();
   }
 
-  public void testMaxLengthExtra_zip64() throws Exception {
-    // Not quite the max length (65535), but large enough that there's no space
-    // for the zip64 extended info header.
-    byte[] maxLengthExtra = new byte[65530];
 
-    File f = createTemporaryZipFile();
-    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f)),
-            true /* forceZip64 */);
-    ZipEntry ze = new ZipEntry("x");
-
-    ze.setExtra(maxLengthExtra);
-    try {
-      out.putNextEntry(ze);
-      fail();
-    } catch (ZipException expected) {
-    }
-  }
+  // TODO: This test does not compile because we need to add a ZipOutputStream constructor
+  // that forces zip64. This also needs followup changes in ZipInputStream et al. to assume zip64
+  // if the header says so, and to not depend purely on the entry length.
+  //
+  // public void testMaxLengthExtra_zip64() throws Exception {
+  //   // Not quite the max length (65535), but large enough that there's no space
+  //   // for the zip64 extended info header.
+  //   byte[] maxLengthExtra = new byte[65530];
+  //
+  //   File f = createTemporaryZipFile();
+  //   ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(f)),
+  //           true /* forceZip64 */);
+  //   ZipEntry ze = new ZipEntry("x");
+  //
+  //   ze.setExtra(maxLengthExtra);
+  //   try {
+  //     out.putNextEntry(ze);
+  //     fail();
+  //   } catch (ZipException expected) {
+  //   }
+  // }
 
 
   public void testTooLongComment() throws Exception {
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
index 24820ed..4918fdc 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
@@ -22,46 +22,78 @@
 
 public class AlgorithmParametersTestDSA extends AlgorithmParametersTest {
 
+    /*
+     * Parameters generated with OpenSSL:
+     * openssl dsaparam -genkey 1024 -C
+     */
     private static final byte[] P = new byte[] {
-            (byte) 0x00, (byte) 0xB9, (byte) 0x53, (byte) 0xA4, (byte) 0xBB,
-            (byte) 0xC8, (byte) 0xFD, (byte) 0x94, (byte) 0x4B, (byte) 0xC0,
-            (byte) 0xD4, (byte) 0x6B, (byte) 0xA9, (byte) 0xAB, (byte) 0x5A,
-            (byte) 0x1E, (byte) 0x85, (byte) 0x7E, (byte) 0x87, (byte) 0x38,
-            (byte) 0x79, (byte) 0x1C, (byte) 0xBF, (byte) 0xCF, (byte) 0x32,
-            (byte) 0x5A, (byte) 0x45, (byte) 0xF8, (byte) 0xE4, (byte) 0x08,
-            (byte) 0x28, (byte) 0xA4, (byte) 0x12, (byte) 0x8A, (byte) 0x9D,
-            (byte) 0x06, (byte) 0x53, (byte) 0x1C, (byte) 0xAA, (byte) 0x6A,
-            (byte) 0x21, (byte) 0xC1, (byte) 0x95, (byte) 0xF8, (byte) 0xAA,
-            (byte) 0xB2, (byte) 0xB8, (byte) 0x43, (byte) 0x38, (byte) 0x86,
-            (byte) 0x15, (byte) 0x94, (byte) 0xCF, (byte) 0x40, (byte) 0xA5,
-            (byte) 0x0D, (byte) 0xF3, (byte) 0x9A, (byte) 0x49, (byte) 0x12,
-            (byte) 0x72, (byte) 0x64, (byte) 0x11, (byte) 0xDD, (byte) 0x85};
+            (byte) 0xE6, (byte) 0x41, (byte) 0x58, (byte) 0x77, (byte) 0x76,
+            (byte) 0x5A, (byte) 0x4A, (byte) 0x53, (byte) 0xF1, (byte) 0xD6,
+            (byte) 0xC8, (byte) 0x7D, (byte) 0x67, (byte) 0x1F, (byte) 0x2F,
+            (byte) 0xFA, (byte) 0xDE, (byte) 0xB7, (byte) 0xAA, (byte) 0xCD,
+            (byte) 0xD7, (byte) 0x5D, (byte) 0xD0, (byte) 0xE9, (byte) 0xB1,
+            (byte) 0xDA, (byte) 0xFE, (byte) 0x42, (byte) 0xBE, (byte) 0xCC,
+            (byte) 0x42, (byte) 0x52, (byte) 0x2E, (byte) 0x01, (byte) 0xD2,
+            (byte) 0x16, (byte) 0xB1, (byte) 0x5B, (byte) 0xC4, (byte) 0x42,
+            (byte) 0xF9, (byte) 0x55, (byte) 0x0F, (byte) 0xE2, (byte) 0xD5,
+            (byte) 0x01, (byte) 0xD2, (byte) 0x7E, (byte) 0x22, (byte) 0xF6,
+            (byte) 0xC1, (byte) 0xFE, (byte) 0x5C, (byte) 0x6A, (byte) 0xCF,
+            (byte) 0x82, (byte) 0x1B, (byte) 0x5C, (byte) 0x46, (byte) 0x66,
+            (byte) 0x8B, (byte) 0xAF, (byte) 0xDF, (byte) 0x44, (byte) 0xE2,
+            (byte) 0x0E, (byte) 0xA3, (byte) 0x58, (byte) 0xF7, (byte) 0xA3,
+            (byte) 0x24, (byte) 0xE3, (byte) 0x84, (byte) 0xA6, (byte) 0x16,
+            (byte) 0xE0, (byte) 0xCA, (byte) 0x72, (byte) 0x55, (byte) 0x07,
+            (byte) 0xA0, (byte) 0x99, (byte) 0x7B, (byte) 0xF8, (byte) 0xB1,
+            (byte) 0x5A, (byte) 0x84, (byte) 0x36, (byte) 0x5A, (byte) 0xC8,
+            (byte) 0x6A, (byte) 0xFE, (byte) 0xA6, (byte) 0xB4, (byte) 0x1B,
+            (byte) 0x3A, (byte) 0x0A, (byte) 0x00, (byte) 0x6B, (byte) 0x72,
+            (byte) 0xDC, (byte) 0x0C, (byte) 0xD1, (byte) 0x09, (byte) 0x25,
+            (byte) 0x11, (byte) 0x68, (byte) 0x6B, (byte) 0x75, (byte) 0xDE,
+            (byte) 0x2C, (byte) 0x1A, (byte) 0xC2, (byte) 0x3A, (byte) 0xCB,
+            (byte) 0xA0, (byte) 0x17, (byte) 0xCA, (byte) 0x2D, (byte) 0xEE,
+            (byte) 0xA2, (byte) 0x5A, (byte) 0x9D, (byte) 0x1F, (byte) 0x33,
+            (byte) 0x1B, (byte) 0x07, (byte) 0x6D,
+    };
     private static final byte[] Q = new byte[] {
-            (byte) 0x00, (byte) 0xF8, (byte) 0x51, (byte) 0x6A, (byte) 0x92,
-            (byte) 0xCB, (byte) 0x47, (byte) 0x95, (byte) 0x18, (byte) 0x1F,
-            (byte) 0x7E, (byte) 0xD8, (byte) 0x71, (byte) 0x05, (byte) 0xB6,
-            (byte) 0x26, (byte) 0x4D, (byte) 0x52, (byte) 0x94, (byte) 0xFA,
-            (byte) 0x5D};
+            (byte) 0x9B, (byte) 0x39, (byte) 0xD0, (byte) 0x02, (byte) 0x0F,
+            (byte) 0xE9, (byte) 0x96, (byte) 0x16, (byte) 0xC5, (byte) 0x25,
+            (byte) 0xF7, (byte) 0x94, (byte) 0xA9, (byte) 0x2C, (byte) 0xD0,
+            (byte) 0x25, (byte) 0x5B, (byte) 0x6E, (byte) 0xE0, (byte) 0x8F,
+    };
     private static final byte[] G = new byte[] {
-            (byte) 0x2B, (byte) 0xF5, (byte) 0x91, (byte) 0x47, (byte) 0xC8,
-            (byte) 0xF1, (byte) 0x79, (byte) 0x75, (byte) 0x2A, (byte) 0x8E,
-            (byte) 0x40, (byte) 0x7E, (byte) 0xF5, (byte) 0xA5, (byte) 0x14,
-            (byte) 0x98, (byte) 0x97, (byte) 0xE8, (byte) 0xC5, (byte) 0x5E,
-            (byte) 0x7A, (byte) 0x39, (byte) 0xFE, (byte) 0x3B, (byte) 0x68,
-            (byte) 0x06, (byte) 0x85, (byte) 0xD4, (byte) 0xDC, (byte) 0xA5,
-            (byte) 0xF1, (byte) 0xC1, (byte) 0x82, (byte) 0x45, (byte) 0x98,
-            (byte) 0xD3, (byte) 0x06, (byte) 0xE2, (byte) 0x4A, (byte) 0x45,
-            (byte) 0xD7, (byte) 0xF5, (byte) 0x57, (byte) 0x18, (byte) 0x55,
-            (byte) 0x05, (byte) 0xD4, (byte) 0x74, (byte) 0x6A, (byte) 0x9E,
-            (byte) 0x2D, (byte) 0x42, (byte) 0xDF, (byte) 0xC2, (byte) 0x88,
-            (byte) 0x95, (byte) 0x97, (byte) 0xA8, (byte) 0x7D, (byte) 0x11,
-            (byte) 0x55, (byte) 0x9C, (byte) 0x7C, (byte) 0x9F};
+            (byte) 0x5E, (byte) 0x9C, (byte) 0x95, (byte) 0x5F, (byte) 0x7E,
+            (byte) 0x91, (byte) 0x47, (byte) 0x4D, (byte) 0x68, (byte) 0xA4,
+            (byte) 0x1C, (byte) 0x44, (byte) 0x3B, (byte) 0xEC, (byte) 0x0A,
+            (byte) 0x7E, (byte) 0x59, (byte) 0x54, (byte) 0xF7, (byte) 0xEF,
+            (byte) 0x42, (byte) 0xFB, (byte) 0x63, (byte) 0x95, (byte) 0x08,
+            (byte) 0x2F, (byte) 0x4A, (byte) 0xD3, (byte) 0xBC, (byte) 0x79,
+            (byte) 0x9D, (byte) 0xBA, (byte) 0xD8, (byte) 0x8A, (byte) 0x83,
+            (byte) 0x84, (byte) 0xAE, (byte) 0x5B, (byte) 0x26, (byte) 0x80,
+            (byte) 0xB3, (byte) 0xFB, (byte) 0x9C, (byte) 0xA3, (byte) 0xCF,
+            (byte) 0xF4, (byte) 0x0A, (byte) 0xD5, (byte) 0xB6, (byte) 0x65,
+            (byte) 0x65, (byte) 0x1A, (byte) 0x4F, (byte) 0xC0, (byte) 0x86,
+            (byte) 0x3B, (byte) 0xE6, (byte) 0xFB, (byte) 0x4E, (byte) 0x9E,
+            (byte) 0x49, (byte) 0x0A, (byte) 0x8C, (byte) 0x77, (byte) 0x2D,
+            (byte) 0x93, (byte) 0x0B, (byte) 0xCA, (byte) 0x81, (byte) 0x07,
+            (byte) 0x09, (byte) 0xC4, (byte) 0x71, (byte) 0xFD, (byte) 0xC8,
+            (byte) 0xC7, (byte) 0xD1, (byte) 0xA3, (byte) 0xD0, (byte) 0xBB,
+            (byte) 0x7D, (byte) 0x92, (byte) 0x74, (byte) 0x8B, (byte) 0x3B,
+            (byte) 0x2A, (byte) 0x45, (byte) 0x1F, (byte) 0x5D, (byte) 0x85,
+            (byte) 0x90, (byte) 0xE3, (byte) 0xFB, (byte) 0x0E, (byte) 0x16,
+            (byte) 0xBA, (byte) 0x8A, (byte) 0xDE, (byte) 0x10, (byte) 0x0F,
+            (byte) 0xE0, (byte) 0x0F, (byte) 0x37, (byte) 0xA7, (byte) 0xC1,
+            (byte) 0xDC, (byte) 0xBC, (byte) 0x00, (byte) 0xB8, (byte) 0x24,
+            (byte) 0x0F, (byte) 0xF6, (byte) 0x5F, (byte) 0xB1, (byte) 0xA8,
+            (byte) 0x9A, (byte) 0xDB, (byte) 0x9F, (byte) 0x36, (byte) 0x54,
+            (byte) 0x45, (byte) 0xBD, (byte) 0xC0, (byte) 0xE8, (byte) 0x27,
+            (byte) 0x82, (byte) 0xC9, (byte) 0x75,
+    };
 
 
     public AlgorithmParametersTestDSA() {
         super("DSA", new AlgorithmParameterSignatureHelper<DSAParameterSpec>(
                 "DSA", DSAParameterSpec.class), new DSAParameterSpec(
-                new BigInteger(P), new BigInteger(Q), new BigInteger(G)));
+                new BigInteger(1, P), new BigInteger(1, Q), new BigInteger(1, G)));
     }
 
 }
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index 4635ae5..f296bf8 100755
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -106,6 +106,22 @@
     public final static PrintStream err;
 
     /**
+     * Dedicated lock for GC / Finalization logic.
+     */
+    private static final Object LOCK = new Object();
+
+    /**
+     * Whether or not we need to do a GC before running the finalizers.
+     */
+    private static boolean runGC;
+
+    /**
+     * If we just ran finalization, we might want to do a GC to free the finalized objects.
+     * This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc().
+     */
+    private static boolean justRanFinalization;
+
+    /**
      * Reassigns the "standard" input stream.
      *
      * <p>First, if there is a security manager, its <code>checkPermission</code>
@@ -1497,7 +1513,18 @@
      * @see     java.lang.Runtime#gc()
      */
     public static void gc() {
-        Runtime.getRuntime().gc();
+        boolean shouldRunGC;
+        synchronized (LOCK) {
+            shouldRunGC = justRanFinalization;
+            if (shouldRunGC) {
+                justRanFinalization = false;
+            } else {
+                runGC = true;
+            }
+        }
+        if (shouldRunGC) {
+            Runtime.getRuntime().gc();
+        }
     }
 
     /**
@@ -1519,7 +1546,18 @@
      * @see     java.lang.Runtime#runFinalization()
      */
     public static void runFinalization() {
+        boolean shouldRunGC;
+        synchronized (LOCK) {
+            shouldRunGC = runGC;
+            runGC = false;
+        }
+        if (shouldRunGC) {
+            Runtime.getRuntime().gc();
+        }
         Runtime.getRuntime().runFinalization();
+        synchronized (LOCK) {
+            justRanFinalization = true;
+        }
     }
 
     /**
diff --git a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
index e7ad94c..8133554 100755
--- a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
@@ -304,8 +304,11 @@
                  throw new SocketException("bad argument for IP_MULTICAST_IF");
              break;
          case IP_MULTICAST_IF2:
-             if (o == null || !(o instanceof NetworkInterface))
+             if (o == null || !(o instanceof Integer || o instanceof NetworkInterface))
                  throw new SocketException("bad argument for IP_MULTICAST_IF2");
+             if (o instanceof NetworkInterface) {
+                 o = new Integer(((NetworkInterface)o).getIndex());
+             }
              break;
          case IP_MULTICAST_LOOP:
              if (o == null || !(o instanceof Boolean))
@@ -349,6 +352,10 @@
             case SO_REUSEADDR:
             case SO_BROADCAST:
                 result = socketGetOption(optID);
+
+                if (optID == IP_MULTICAST_IF) {
+                    return getNIFirstAddress((Integer)result);
+                }
                 break;
 
             default:
@@ -358,6 +365,20 @@
         return result;
     }
 
+    /** Return the first address bound to NetworkInterface with given ID.
+     * In case of niIndex == 0 or no address return anyLocalAddress
+     */
+    static InetAddress getNIFirstAddress(int niIndex) throws SocketException {
+        if (niIndex > 0) {
+            NetworkInterface networkInterface = NetworkInterface.getByIndex(niIndex);
+            Enumeration<InetAddress> addressesEnum = networkInterface.getInetAddresses();
+            if (addressesEnum.hasMoreElements()) {
+                return addressesEnum.nextElement();
+            }
+        }
+        return InetAddress.anyLocalAddress();
+    }
+
     protected abstract void datagramSocketCreate() throws SocketException;
     protected abstract void datagramSocketClose();
     protected abstract void socketSetOption(int opt, Object val)
diff --git a/ojluni/src/main/java/java/net/Inet4Address.java b/ojluni/src/main/java/java/net/Inet4Address.java
index 11ee7c7..57da1c4 100755
--- a/ojluni/src/main/java/java/net/Inet4Address.java
+++ b/ojluni/src/main/java/java/net/Inet4Address.java
@@ -332,11 +332,6 @@
         return addr;
     }
 
-    @Override
-    public byte[] getAddressInternal() {
-        return getAddress();
-    }
-
     /**
      * Returns the IP address string in textual presentation form.
      *
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index 67487ff..ca19211 100755
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -622,11 +622,6 @@
         return ipaddress.clone();
     }
 
-    @Override
-    public byte[] getAddressInternal() {
-        return ipaddress;
-    }
-
     /**
      * Returns the numeric scopeId, if this instance is associated with
      * an interface. If no scoped_id is set, the returned value is zero.
diff --git a/ojluni/src/main/java/java/net/InetAddress.java b/ojluni/src/main/java/java/net/InetAddress.java
index 019c4ac..d8057ff 100755
--- a/ojluni/src/main/java/java/net/InetAddress.java
+++ b/ojluni/src/main/java/java/net/InetAddress.java
@@ -577,16 +577,6 @@
     }
 
     /**
-     * Called from native code. Same as {@code getAddress}, but for internal users.
-     *
-     * @return
-     */
-    public byte[] getAddressInternal() {
-        return null;
-    }
-
-
-    /**
      * Returns the IP address string in textual presentation.
      *
      * @return  the raw IP address in a string format.
@@ -1005,4 +995,4 @@
     String getHostName(boolean check) {
         throw new UnsupportedOperationException();
     }
-}
\ No newline at end of file
+}
diff --git a/ojluni/src/main/java/java/net/MulticastSocket.java b/ojluni/src/main/java/java/net/MulticastSocket.java
index 28bc58e..f39d3e9 100755
--- a/ojluni/src/main/java/java/net/MulticastSocket.java
+++ b/ojluni/src/main/java/java/net/MulticastSocket.java
@@ -563,14 +563,14 @@
      * @since 1.4
      */
     public NetworkInterface getNetworkInterface() throws SocketException {
-        NetworkInterface ni
-            = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
-        if (ni.getIndex() == 0) {
+        Integer niIndex
+            = (Integer)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2);
+        if (niIndex == 0) {
             InetAddress[] addrs = new InetAddress[1];
             addrs[0] = InetAddress.anyLocalAddress();
             return new NetworkInterface(addrs[0].getHostName(), 0, addrs);
         } else {
-            return ni;
+            return NetworkInterface.getByIndex(niIndex);
         }
     }
 
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index b641b5c..1f5825f 100755
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -49,6 +49,7 @@
     private NetworkInterface childs[];
     private NetworkInterface parent = null;
     private boolean virtual = false;
+    private byte[] hardwareAddr;
     private static final NetworkInterface defaultInterface;
     private static final int defaultIndex; /* index of defaultInterface */
 
@@ -431,23 +432,7 @@
      * @since 1.6
      */
     public byte[] getHardwareAddress() throws SocketException {
-        SecurityManager sec = System.getSecurityManager();
-        if (sec != null) {
-            try {
-                sec.checkPermission(new NetPermission("getNetworkInformation"));
-            } catch (SecurityException e) {
-                if (!getInetAddresses().hasMoreElements()) {
-                    // don't have connect permission to any local address
-                    return null;
-                }
-            }
-        }
-        for (InetAddress addr : addrs) {
-            if (addr instanceof Inet4Address) {
-                return getMacAddr0(((Inet4Address)addr).getAddress(), name, index);
-            }
-        }
-        return getMacAddr0(null, name, index);
+        return (hardwareAddr != null) ? hardwareAddr.clone() : null;
     }
 
     /**
@@ -482,7 +467,6 @@
     private native static boolean isLoopback0(String name, int ind) throws SocketException;
     private native static boolean supportsMulticast0(String name, int ind) throws SocketException;
     private native static boolean isP2P0(String name, int ind) throws SocketException;
-    private native static byte[] getMacAddr0(byte[] inAddr, String name, int ind) throws SocketException;
     private native static int getMTU0(String name, int ind) throws SocketException;
 
     /**
diff --git a/ojluni/src/main/java/java/net/SocketImpl.java b/ojluni/src/main/java/java/net/SocketImpl.java
index 18044ab..d2123e2 100755
--- a/ojluni/src/main/java/java/net/SocketImpl.java
+++ b/ojluni/src/main/java/java/net/SocketImpl.java
@@ -222,7 +222,14 @@
      * @return  the value of this socket's <code>fd</code> field.
      * @see     java.net.SocketImpl#fd
      */
-    public FileDescriptor getFileDescriptor() {
+    protected FileDescriptor getFileDescriptor() {
+        return fd;
+    }
+
+    /**
+     * @hide used by java.nio tests
+     */
+    public FileDescriptor getFD$() {
         return fd;
     }
 
diff --git a/ojluni/src/main/native/NetworkInterface.c b/ojluni/src/main/native/NetworkInterface.c
index 83ab1b8..0c98458 100755
--- a/ojluni/src/main/native/NetworkInterface.c
+++ b/ojluni/src/main/native/NetworkInterface.c
@@ -37,37 +37,13 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
+#include <linux/if_packet.h>
 
-#ifdef __solaris__
-#include <sys/dlpi.h>
-#include <fcntl.h>
-#include <stropts.h>
-#include <sys/sockio.h>
-#endif
-
-#ifdef __linux__
 #include <sys/ioctl.h>
 //#include <bits/ioctls.h>
 #include <sys/utsname.h>
 #include <stdio.h>
-#endif
-
-#ifdef __linux__
-#define _PATH_PROCNET_IFINET6           "/proc/net/if_inet6"
-#endif
-
-#if defined(_ALLBSD_SOURCE)
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/sockio.h>
-#if defined(__APPLE__)
-#include <net/ethernet.h>
-#include <net/if_var.h>
-#include <net/if_dl.h>
-#include <netinet/in_var.h>
 #include <ifaddrs.h>
-#endif
-#endif
 
 #include "jvm.h"
 #include "jni_util.h"
@@ -89,6 +65,9 @@
     char *name;
     int index;
     char virtual;
+
+    uint8_t hwAddrLen;
+    uint8_t *hwAddr;
     netaddr *addr;
     struct _netif *childs;
     struct _netif *next;
@@ -112,6 +91,7 @@
 jfieldID ni_childsID;
 jfieldID ni_parentID;
 jfieldID ni_defaultIndexID;
+jfieldID ni_hardwareAddrID;
 jmethodID ni_ctrID;
 
 static jclass ni_iacls;
@@ -131,39 +111,18 @@
 static int     getFlags0(JNIEnv *env, jstring  ifname);
 
 static netif  *enumInterfaces(JNIEnv *env);
-static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
 
-#ifdef AF_INET6
-static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
-#endif
-
-static netif  *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static netif  *addif(JNIEnv *env, int sock, struct ifaddrs *ifa, netif *ifs);
 static void    freeif(netif *ifs);
 
 static int     openSocket(JNIEnv *env, int proto);
 static int     openSocketWithFallback(JNIEnv *env, const char *ifname);
 
-
-static struct  sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
-static short   getSubnet(JNIEnv *env, int sock, const char *ifname);
 static int     getIndex(int sock, const char *ifname);
 
 static int     getFlags(int sock, const char *ifname, int *flags);
-static int     getMacAddress(JNIEnv *env, int sock,  const char* ifname, const struct in_addr* addr, unsigned char *buf);
 static int     getMTU(JNIEnv *env, int sock, const char *ifname);
 
-
-
-#ifdef __solaris__
-static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
-static int    getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
-
-#ifndef SIOCGLIFHWADDR
-#define SIOCGLIFHWADDR  _IOWR('i', 192, struct lifreq)
-#endif
-
-#endif
-
 /******************* Java entry points *****************************/
 
 /*
@@ -183,6 +142,7 @@
     ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
     ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
     ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
+    ni_hardwareAddrID = (*env)->GetFieldID(env, ni_class, "hardwareAddr", "[B");
     ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
 
     ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
@@ -298,11 +258,7 @@
 
     netif *ifs, *curr;
 
-#ifdef AF_INET6
     int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
-#else
-    int family =  AF_INET;
-#endif
 
     jobject obj = NULL;
     jboolean match = JNI_FALSE;
@@ -332,7 +288,6 @@
                     }
                 }
 
-#ifdef AF_INET6
                 if (family == AF_INET6) {
                     jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
                     jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
@@ -352,8 +307,6 @@
                         break;
                     }
                 }
-#endif
-
             }
 
             if (match) {
@@ -477,57 +430,6 @@
 }
 
 /*
- * Class:     java_net_NetworkInterface
- * Method:    getMacAddr0
- * Signature: ([bLjava/lang/String;I)[b
- */
-JNIEXPORT jbyteArray JNICALL NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
-  jint addr;
-  jbyte caddr[4];
-  struct in_addr iaddr;
-  jbyteArray ret = NULL;
-  unsigned char mac[16];
-  int len;
-  int sock;
-  jboolean isCopy;
-  const char* name_utf;
-
-  name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
-
-  if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
-    (*env)->ReleaseStringUTFChars(env, name, name_utf);
-    return JNI_FALSE;
-  }
-
-
-  if (!IS_NULL(addrArray)) {
-    (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-    addr = ((caddr[0]<<24) & 0xff000000);
-    addr |= ((caddr[1] <<16) & 0xff0000);
-    addr |= ((caddr[2] <<8) & 0xff00);
-    addr |= (caddr[3] & 0xff);
-    iaddr.s_addr = htonl(addr);
-    len = getMacAddress(env, sock, name_utf, &iaddr, mac);
-  } else {
-    len = getMacAddress(env, sock, name_utf,NULL, mac);
-  }
-  if (len > 0) {
-    ret = (*env)->NewByteArray(env, len);
-    if (IS_NULL(ret)) {
-      /* we may have memory to free at the end of this */
-      goto fexit;
-    }
-    (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
-  }
-fexit:
-  /* release the UTF string and interface list */
-  (*env)->ReleaseStringUTFChars(env, name, name_utf);
-
-  close(sock);
-  return ret;
-}
-
-/*
  * Class:       java_net_NetworkInterface
  * Method:      getMTU0
  * Signature:   ([bLjava/lang/String;I)I
@@ -619,6 +521,18 @@
   (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
 
   /*
+   * Set the hardware address
+   */
+  if (ifs->hwAddrLen > 0 && ifs->hwAddr != NULL) {
+    jbyteArray hardwareAddr = (*env)->NewByteArray(env, ifs->hwAddrLen);
+    if (hardwareAddr == NULL) {
+      return NULL;
+    }
+    (*env)->SetByteArrayRegion(env, hardwareAddr, 0, ifs->hwAddrLen, (jbyte *)ifs->hwAddr);
+    (*env)->SetObjectField(env, netifObj, ni_hardwareAddrID, hardwareAddr);
+  }
+
+  /*
    * Count the number of address on this interface
    */
   addr_count = 0;
@@ -661,14 +575,13 @@
           if (ia2Obj) {
             setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
             (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
-            (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
           }
         }
+        (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
         (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
       }
     }
 
-#ifdef AF_INET6
     if (addrP->family == AF_INET6) {
       int scope=0;
       iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
@@ -696,7 +609,6 @@
         (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
       }
     }
-#endif
 
     if (iaObj == NULL) {
       return NULL;
@@ -745,56 +657,54 @@
 }
 
 /*
+ * Determines the mask length for IPV4/v6 addresses.
+ */
+static
+int mask_address_to_mask_length(uint8_t *val, int size) {
+  int byte, bit, plen = 0;
+
+  for (byte = 0; byte < size && val[byte] == 0xff; byte++) {
+    plen += 8;
+  }
+  if (byte < size) {
+    for (bit = 7; bit > 0; bit--) {
+      if (val[byte] & (1 << bit)) plen++;
+    }
+  }
+  return plen;
+}
+
+/*
  * Enumerates all interfaces
  */
 static netif *enumInterfaces(JNIEnv *env) {
-  netif *ifs;
-  int sock;
+  netif *ifs = NULL;
+  struct ifaddrs *ifa, *origifa;
 
-  /*
-   * Enumerate IPv4 addresses
-   */
-
-  sock = openSocket(env, AF_INET);
+  int sock = openSocket(env, AF_INET);
   if (sock < 0 && (*env)->ExceptionOccurred(env)) {
     return NULL;
   }
 
-  ifs = enumIPv4Interfaces(env, sock, NULL);
-  close(sock);
-
-  if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
+  if (getifaddrs(&origifa) != 0) {
+    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+                                 "getifaddrs() function failed");
     return NULL;
   }
 
-  /* return partial list if exception occure in the middle of process ???*/
-
-  /*
-   * If IPv6 is available then enumerate IPv6 addresses.
-   */
-#ifdef AF_INET6
-
-  /* User can disable ipv6 expicitly by -Djava.net.preferIPv4Stack=true,
-   * so we have to call ipv6_available()
-   */
-  if (ipv6_available()) {
-
-    sock =  openSocket(env, AF_INET6);
-    if (sock < 0 && (*env)->ExceptionOccurred(env)) {
-      freeif(ifs);
-      return NULL;
+  for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
+    if (ifa->ifa_addr != NULL) {
+      switch (ifa->ifa_addr->sa_family) {
+        case AF_PACKET:
+        case AF_INET:
+        case AF_INET6:
+          ifs = addif(env, sock, ifa, ifs);
+          break;
+      }
     }
-
-    ifs = enumIPv6Interfaces(env, sock, ifs);
-    close(sock);
-
-    if ((*env)->ExceptionOccurred(env)) {
-      freeif(ifs);
-      return NULL;
-    }
-
   }
-#endif
+
+  close(sock);
 
   return ifs;
 }
@@ -831,26 +741,25 @@
       freeif(currif->childs);
     }
 
+    /*
+     * Remove mac address
+     */
+    if (currif->hwAddr != NULL) {
+      free(currif->hwAddr);
+    }
+
     ifs = currif->next;
     free(currif);
     currif = ifs;
   }
 }
 
-netif *addif(JNIEnv *env, int sock, const char * if_name,
-             netif *ifs, struct sockaddr* ifr_addrP, int family,
-             short prefix)
+netif *addif(JNIEnv *env, int sock, struct ifaddrs *ifa, netif *ifs)
 {
   netif *currif = ifs, *parent;
-  netaddr *addrP;
+  netaddr *addrP = NULL;
 
-#ifdef LIFNAMSIZ
-  int ifnam_size = LIFNAMSIZ;
-  char name[LIFNAMSIZ], vname[LIFNAMSIZ];
-#else
-  int ifnam_size = IFNAMSIZ;
   char name[IFNAMSIZ], vname[IFNAMSIZ];
-#endif
 
   char  *name_colonP;
   int mask;
@@ -865,39 +774,58 @@
    * currently doesn't have any concept of physical vs.
    * logical interfaces.
    */
-  strncpy(name, if_name, ifnam_size);
-  name[ifnam_size - 1] = '\0';
+  strncpy(name, ifa->ifa_name, sizeof(name));
+  name[sizeof(name) - 1] = '\0';
   *vname = 0;
 
   /*
    * Create and populate the netaddr node. If allocation fails
    * return an un-updated list.
    */
-  /*Allocate for addr and brdcast at once*/
+  switch(ifa->ifa_addr->sa_family) {
+    case AF_INET:
+      addr_size = sizeof(struct sockaddr_in);
+      break;
+    case AF_INET6:
+      addr_size = sizeof(struct sockaddr_in6);
+      break;
+    case AF_PACKET:
+      // Don't add an address entry, will extract data to netif struct
+      addr_size = 0;
+      break;
+    default:
+      return NULL;
+  }
 
-#ifdef AF_INET6
-  addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
-#else
-  addr_size = sizeof(struct sockaddr_in);
-#endif
+  if (addr_size > 0) {
+    /*Allocate for addr and brdcast at once*/
+    CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
+    addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+    memcpy(addrP->addr, ifa->ifa_addr, addr_size);
 
-  CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
-  addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
-  memcpy(addrP->addr, ifr_addrP, addr_size);
+    addrP->family = ifa->ifa_addr->sa_family;
+    addrP->next = 0;
 
-  addrP->family = family;
-  addrP->brdcast = NULL;
-  addrP->mask = prefix;
-  addrP->next = 0;
-  if (family == AF_INET) {
-    /*
-     * Deal with brodcast addr & subnet mask
-     */
-    struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
-    addrP->brdcast = getBroadcast(env, sock, name,  brdcast_to );
+    if (ifa->ifa_broadaddr && (ifa->ifa_flags & IFF_BROADCAST)) {
+      struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
+      addrP->brdcast = brdcast_to;
+      memcpy(brdcast_to, ifa->ifa_broadaddr, sizeof(struct sockaddr));
+    } else {
+      addrP->brdcast = NULL;
+    }
 
-    if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
-      addrP->mask = mask;
+    if (ifa->ifa_netmask) {
+      if (ifa->ifa_netmask->sa_family == AF_INET) {
+        addrP->mask = mask_address_to_mask_length(
+            (uint8_t*)&(((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr),
+            sizeof(struct in_addr));
+      } else if (ifa->ifa_netmask->sa_family == AF_INET6) {
+        addrP->mask = mask_address_to_mask_length(
+            (uint8_t*)&((struct sockaddr_in6*)ifa->ifa_netmask)->sin6_addr,
+            sizeof(struct in6_addr));
+      }
+    } else {
+      addrP->mask = 0;
     }
   }
 
@@ -943,23 +871,51 @@
    * insert it onto the list.
    */
   if (currif == NULL) {
-    CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
+    CHECKED_MALLOC3(currif, netif *, sizeof(netif) + sizeof(name));
     currif->name = (char *) currif+sizeof(netif);
-    strncpy(currif->name, name, ifnam_size);
-    currif->name[ifnam_size - 1] = '\0';
+    strncpy(currif->name, name, sizeof(name));
+    currif->name[sizeof(name) - 1] = '\0';
     currif->index = getIndex(sock, name);
     currif->addr = NULL;
     currif->childs = NULL;
     currif->virtual = isVirtual;
+    currif->hwAddrLen = 0;
+    currif->hwAddr = NULL;
     currif->next = ifs;
     ifs = currif;
   }
 
   /*
+   * Insert the mac address on the interface
+   */
+  if (ifa->ifa_addr->sa_family == AF_PACKET) {
+    struct sockaddr_ll *s = (struct sockaddr_ll*)ifa->ifa_addr;
+
+    if (s->sll_halen > 0) {
+      /*
+       * All bytes to 0 means no hardware address.
+       */
+      int i;
+      for (i = 0;i < s->sll_halen; ++i) {
+        if (s->sll_addr[i] != 0) {
+          break;
+        }
+      }
+      if (i != s->sll_halen && currif->hwAddr == NULL) {
+        CHECKED_MALLOC3(currif->hwAddr, uint8_t *, s->sll_halen);
+        memcpy(currif->hwAddr, s->sll_addr, s->sll_halen);
+        currif->hwAddrLen = s->sll_halen;
+      }
+    }
+  }
+
+  /*
    * Finally insert the address on the interface
    */
-  addrP->next = currif->addr;
-  currif->addr = addrP;
+  if (addrP != NULL) {
+    addrP->next = currif->addr;
+    currif->addr = addrP;
+  }
 
   parent = currif;
 
@@ -979,10 +935,10 @@
     }
 
     if (currif == NULL) {
-      CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
+      CHECKED_MALLOC3(currif, netif *, sizeof(netif) + sizeof(name));
       currif->name = (char *) currif + sizeof(netif);
-      strncpy(currif->name, vname, ifnam_size);
-      currif->name[ifnam_size - 1] = '\0';
+      strncpy(currif->name, vname, sizeof(name));
+      currif->name[sizeof(name) - 1] = '\0';
       currif->index = getIndex(sock, vname);
       currif->addr = NULL;
       /* Need to duplicate the addr entry? */
@@ -1033,12 +989,11 @@
 
 
 /** Linux **/
-#ifdef __linux__
+
 /* Open socket for further ioct calls, try v4 socket first and
  * if it falls return v6 socket
  */
 
-#ifdef AF_INET6
 static int openSocketWithFallback(JNIEnv *env, const char *ifname){
   int sock;
   struct ifreq if2;
@@ -1062,114 +1017,6 @@
   return sock;
 }
 
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
-  return openSocket(env,AF_INET);
-}
-#endif
-
-static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  struct ifconf ifc;
-  struct ifreq *ifreqP;
-  char *buf;
-  int numifs;
-  unsigned i;
-
-
-  /* need to do a dummy SIOCGIFCONF to determine the buffer size.
-   * SIOCGIFCOUNT doesn't work
-   */
-  ifc.ifc_buf = NULL;
-  if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
-    return ifs;
-  }
-
-  CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
-
-  ifc.ifc_buf = buf;
-  if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
-    (void) free(buf);
-    return ifs;
-  }
-
-  /*
-   * Iterate through each interface
-   */
-  ifreqP = ifc.ifc_req;
-  for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
-    /*
-     * Add to the list
-     */
-    ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
-
-    /*
-     * If an exception occurred then free the list
-     */
-    if ((*env)->ExceptionOccurred(env)) {
-      free(buf);
-      freeif(ifs);
-      return NULL;
-    }
-  }
-
-  /*
-   * Free socket and buffer
-   */
-  free(buf);
-  return ifs;
-}
-
-
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-
-#ifdef AF_INET6
-static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  FILE *f;
-  char addr6[40], devname[21];
-  char addr6p[8][5];
-  int plen, scope, dad_status, if_idx;
-  uint8_t ipv6addr[16];
-
-  if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
-    while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
-                  addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
-                  &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
-
-      struct netif *ifs_ptr = NULL;
-      struct netif *last_ptr = NULL;
-      struct sockaddr_in6 addr;
-
-      sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
-              addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
-      inet_pton(AF_INET6, addr6, ipv6addr);
-
-      memset(&addr, 0, sizeof(struct sockaddr_in6));
-      memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
-
-      addr.sin6_scope_id = if_idx;
-
-      ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
-
-
-      /*
-       * If an exception occurred then return the list as is.
-       */
-      if ((*env)->ExceptionOccurred(env)) {
-        fclose(f);
-        return ifs;
-      }
-    }
-    fclose(f);
-  }
-  return ifs;
-}
-#endif
-
-
 static int getIndex(int sock, const char *name){
   /*
    * Try to get the interface index
@@ -1185,93 +1032,6 @@
   return if2.ifr_ifindex;
 }
 
-/**
- * Returns the IPv4 broadcast address of a named interface, if it exists.
- * Returns 0 if it doesn't have one.
- */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
-  struct sockaddr *ret = NULL;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2)  < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGIFFLAGS failed");
-    return ret;
-  }
-
-  if (if2.ifr_flags & IFF_BROADCAST) {
-    /* It does, let's retrieve it*/
-    if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
-      return ret;
-    }
-
-    ret = brdcast_store;
-    memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
-
-  return ret;
-}
-
-/**
- * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
- * interface, if it has one, otherwise return -1.
- */
-static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
-  unsigned int mask;
-  short ret;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
-    return -1;
-  }
-
-  mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
-  ret = 0;
-  while (mask) {
-    mask <<= 1;
-    ret++;
-  }
-
-  return ret;
-}
-
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
- * return puts the data in buf, and returns the length, in byte, of the
- * MAC address. Returns -1 if there is no hardware address on that interface.
- */
-static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
-  static struct ifreq ifr;
-  int i;
-
-  strcpy(ifr.ifr_name, ifname);
-  if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
-    return -1;
-  }
-
-  memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
-
-  /*
-   * All bytes to 0 means no hardware address.
-   */
-
-  for (i = 0; i < IFHWADDRLEN; i++) {
-    if (buf[i] != 0)
-      return IFHWADDRLEN;
-  }
-
-  return -1;
-}
-
 static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
   struct ifreq if2;
 
@@ -1304,707 +1064,8 @@
   return 0;
 }
 
-#endif
-
-/** Solaris **/
-#ifdef __solaris__
-/* Open socket for further ioct calls, try v4 socket first and
- * if it falls return v6 socket
- */
-
-#ifdef AF_INET6
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
-  int sock, alreadyV6 = 0;
-  struct lifreq if2;
-
-  if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-    if (errno == EPROTONOSUPPORT){
-      if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-        return -1;
-      }
-
-      alreadyV6=1;
-    }
-    else{ // errno is not NOSUPPORT
-      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
-      return -1;
-    }
-  }
-
-  /**
-   * Solaris requires that we have IPv6 socket to query an
-   * interface without IPv4 address - check it here
-   * POSIX 1 require the kernell to return ENOTTY if the call is
-   * unappropriate for device e.g. NETMASK for device having IPv6
-   * only address but not all devices follows the standart so
-   * fallback on any error.  It's not an ecology friendly but more
-   * reliable.
-   */
-
-  if (! alreadyV6 ){
-    memset((char *) &if2, 0, sizeof(if2));
-    strcpy(if2.lifr_name, ifname);
-    if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
-      close(sock);
-      if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-        return -1;
-      }
-    }
-  }
-
-  return sock;
-}
-
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
-  return openSocket(env,AF_INET);
-}
-#endif
-
-/*
- * Enumerates and returns all IPv4 interfaces
- * (linux verison)
- */
-
-static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  return enumIPvXInterfaces(env,sock, ifs, AF_INET);
-}
-
-#ifdef AF_INET6
-static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
-}
-#endif
-
-/*
-   Enumerates and returns all interfaces on Solaris
-   use the same code for IPv4 and IPv6
-   */
-static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
-  struct lifconf ifc;
-  struct lifreq *ifr;
-  int n;
-  char *buf;
-  struct lifnum numifs;
-  unsigned bufsize;
-
-  /*
-   * Get the interface count
-   */
-  numifs.lifn_family = family;
-  numifs.lifn_flags = 0;
-  if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
-    return ifs;
-  }
-
-  /*
-   *  Enumerate the interface configurations
-   */
-  bufsize = numifs.lifn_count * sizeof (struct lifreq);
-  CHECKED_MALLOC3(buf, char *, bufsize);
-
-  ifc.lifc_family = family;
-  ifc.lifc_flags = 0;
-  ifc.lifc_len = bufsize;
-  ifc.lifc_buf = buf;
-  if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
-    free(buf);
-    return ifs;
-  }
-
-  /*
-   * Iterate through each interface
-   */
-  ifr = ifc.lifc_req;
-  for (n=0; n<numifs.lifn_count; n++, ifr++) {
-    int index = -1;
-    struct lifreq if2;
-
-    /*
-     * Ignore either IPv4 or IPv6 addresses
-     */
-    if (ifr->lifr_addr.ss_family != family) {
-      continue;
-    }
-
-#ifdef AF_INET6
-    if (ifr->lifr_addr.ss_family == AF_INET6) {
-      struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
-      s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
-    }
-#endif
-
-    /* add to the list */
-    ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
-
-    /*
-     * If an exception occurred we return immediately
-     */
-    if ((*env)->ExceptionOccurred(env)) {
-      free(buf);
-      return ifs;
-    }
-
-  }
-
-  free(buf);
-  return ifs;
-}
-
-static int getIndex(int sock, const char *name){
-  /*
-   * Try to get the interface index
-   * (Not supported on Solaris 2.6 or 7)
-   */
-  struct lifreq if2;
-  strcpy(if2.lifr_name, name);
-
-  if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
-    return -1;
-  }
-
-  return if2.lifr_index;
-}
-
-/**
- * Returns the IPv4 broadcast address of a named interface, if it exists.
- * Returns 0 if it doesn't have one.
- */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
-  struct sockaddr *ret = NULL;
-  struct lifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.lifr_name, ifname);
-
-  /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2)  < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL  SIOCGLIFFLAGS failed");
-    return ret;
-  }
-
-  if (if2.lifr_flags & IFF_BROADCAST) {
-    /* It does, let's retrieve it*/
-    if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
-      return ret;
-    }
-
-    ret = brdcast_store;
-    memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
-  }
-
-  return ret;
-}
-
-/**
- * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
- * interface, if it has one, otherwise return -1.
- */
-static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
-  unsigned int mask;
-  short ret;
-  struct lifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.lifr_name, ifname);
-
-  if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
-    return -1;
-  }
-
-  mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
-  ret = 0;
-
-  while (mask) {
-    mask <<= 1;
-    ret++;
-  }
-
-  return ret;
-}
-
-
-
-#define DEV_PREFIX  "/dev/"
-
-/**
- * Solaris specific DLPI code to get hardware address from a device.
- * Unfortunately, at least up to Solaris X, you have to have special
- * privileges (i.e. be root).
- */
-static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
-  char style1dev[MAXPATHLEN];
-  int fd;
-  dl_phys_addr_req_t dlpareq;
-  dl_phys_addr_ack_t *dlpaack;
-  struct strbuf msg;
-  char buf[128];
-  int flags = 0;
-
-  /**
-   * Device is in /dev
-   * e.g.: /dev/bge0
-   */
-  strcpy(style1dev, DEV_PREFIX);
-  strcat(style1dev, ifname);
-  if ((fd = open(style1dev, O_RDWR)) < 0) {
-    /*
-     * Can't open it. We probably are missing the privilege.
-     * We'll have to try something else
-     */
-    return 0;
-  }
-
-  dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
-  dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
-
-  msg.buf = (char *)&dlpareq;
-  msg.len = DL_PHYS_ADDR_REQ_SIZE;
-
-  if (putmsg(fd, &msg, NULL, 0) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
-    return -1;
-  }
-
-  dlpaack = (dl_phys_addr_ack_t *)buf;
-
-  msg.buf = (char *)buf;
-  msg.len = 0;
-  msg.maxlen = sizeof (buf);
-  if (getmsg(fd, &msg, NULL, &flags) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
-    return -1;
-  }
-
-  if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
-    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
-    return -1;
-  }
-
-  memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
-  return dlpaack->dl_addr_length;
-}
-
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
- * return puts the data in buf, and returns the length, in byte, of the
- * MAC address. Returns -1 if there is no hardware address on that interface.
- */
-static int getMacAddress(JNIEnv *env, int sock, const char *ifname,  const struct in_addr* addr, unsigned char *buf) {
-  struct arpreq arpreq;
-  struct sockaddr_in* sin;
-  struct sockaddr_in ipAddr;
-  int len, i;
-  struct lifreq lif;
-
-  /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
-   * try the old way.
-   */
-  memset(&lif, 0, sizeof(lif));
-  strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
-
-  if (ioctl(sock, SIOCGLIFHWADDR, &lif) != -1) {
-    struct sockaddr_dl *sp;
-    sp = (struct sockaddr_dl *)&lif.lifr_addr;
-    memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
-    return sp->sdl_alen;
-  }
-
-  /**
-   * On Solaris we have to use DLPI, but it will only work if we have
-   * privileged access (i.e. root). If that fails, we try a lookup
-   * in the ARP table, which requires an IPv4 address.
-   */
-  if ((len = getMacFromDevice(env, ifname, buf))  == 0) {
-    /*DLPI failed - trying to do arp lookup*/
-
-    if (addr == NULL) {
-      /**
-       * No IPv4 address for that interface, so can't do an ARP lookup.
-       */
-      return -1;
-    }
-
-    len = 6; //???
-
-    sin = (struct sockaddr_in *) &arpreq.arp_pa;
-    memset((char *) &arpreq, 0, sizeof(struct arpreq));
-    ipAddr.sin_port = 0;
-    ipAddr.sin_family = AF_INET;
-    memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
-    memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
-    arpreq.arp_flags= ATF_PUBL;
-
-    if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
-      return -1;
-    }
-
-    memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
-  }
-
-  /*
-   * All bytes to 0 means no hardware address.
-   */
-
-  for (i = 0; i < len; i++) {
-    if (buf[i] != 0)
-      return len;
-  }
-
-  return -1;
-}
-
-static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
-  struct lifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.lifr_name, ifname);
-
-  if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
-    return -1;
-  }
-
-  return  if2.lifr_mtu;
-}
-
-
-static int getFlags(int sock, const char *ifname, int *flags) {
-  struct   lifreq lifr;
-  memset((caddr_t)&lifr, 0, sizeof(lifr));
-  strcpy((caddr_t)&(lifr.lifr_name), ifname);
-
-  if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
-    return -1;
-  }
-
-  *flags = lifr.lifr_flags;
-  return 0;
-}
-
-
-#endif
-
-
-/** BSD **/
-#ifdef _ALLBSD_SOURCE
-/* Open socket for further ioct calls, try v4 socket first and
- * if it falls return v6 socket
- */
-
-#ifdef AF_INET6
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
-  int sock;
-  struct ifreq if2;
-
-  if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-    if (errno == EPROTONOSUPPORT){
-      if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
-        NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
-        return -1;
-      }
-    }
-    else{ // errno is not NOSUPPORT
-      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
-      return -1;
-    }
-  }
-
-  return sock;
-}
-
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname){
-  return openSocket(env,AF_INET);
-}
-#endif
-
-/*
- * Enumerates and returns all IPv4 interfaces
- */
-static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  struct ifaddrs *ifa, *origifa;
-
-  if (getifaddrs(&origifa) != 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                                 "getifaddrs() function failed");
-    return ifs;
-  }
-
-  for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
-
-    /*
-     * Skip non-AF_INET entries.
-     */
-    if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
-      continue;
-
-    /*
-     * Add to the list.
-     */
-    ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
-
-    /*
-     * If an exception occurred then free the list.
-     */
-    if ((*env)->ExceptionOccurred(env)) {
-      freeifaddrs(origifa);
-      freeif(ifs);
-      return NULL;
-    }
-  }
-
-  /*
-   * Free socket and buffer
-   */
-  freeifaddrs(origifa);
-  return ifs;
-}
-
-
-/*
- * Enumerates and returns all IPv6 interfaces on Linux
- */
-
-#ifdef AF_INET6
-/*
- * Determines the prefix on BSD for IPv6 interfaces.
- */
-static
-int prefix(void *val, int size) {
-  u_char *name = (u_char *)val;
-  int byte, bit, plen = 0;
-
-  for (byte = 0; byte < size; byte++, plen += 8)
-    if (name[byte] != 0xff)
-      break;
-  if (byte == size)
-    return (plen);
-  for (bit = 7; bit != 0; bit--, plen++)
-    if (!(name[byte] & (1 << bit)))
-      break;
-  for (; bit != 0; bit--)
-    if (name[byte] & (1 << bit))
-      return (0);
-  byte++;
-  for (; byte < size; byte++)
-    if (name[byte])
-      return (0);
-  return (plen);
-}
-
-/*
- * Enumerates and returns all IPv6 interfaces on BSD
- */
-static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
-  struct ifaddrs *ifa, *origifa;
-  struct sockaddr_in6 *sin6;
-  struct in6_ifreq ifr6;
-
-  if (getifaddrs(&origifa) != 0) {
-    NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                                 "getifaddrs() function failed");
-    return ifs;
-  }
-
-  for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
-
-    /*
-     * Skip non-AF_INET6 entries.
-     */
-    if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
-      continue;
-
-    memset(&ifr6, 0, sizeof(ifr6));
-    strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
-    memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
-
-    if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
-      NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
-                                   "ioctl SIOCGIFNETMASK_IN6 failed");
-      freeifaddrs(origifa);
-      freeif(ifs);
-      return NULL;
-    }
-
-    /* Add to the list.  */
-    sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
-    ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
-                prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
-
-    /* If an exception occurred then free the list.  */
-    if ((*env)->ExceptionOccurred(env)) {
-      freeifaddrs(origifa);
-      freeif(ifs);
-      return NULL;
-    }
-  }
-
-  /*
-   * Free socket and ifaddrs buffer
-   */
-  freeifaddrs(origifa);
-  return ifs;
-}
-#endif
-
-static int getIndex(int sock, const char *name){
-#ifdef __FreeBSD__
-  /*
-   * Try to get the interface index
-   * (Not supported on Solaris 2.6 or 7)
-   */
-  struct ifreq if2;
-  strcpy(if2.ifr_name, name);
-
-  if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
-    return -1;
-  }
-
-  return if2.ifr_index;
-#else
-  /*
-   * Try to get the interface index using BSD specific if_nametoindex
-   */
-  int index = if_nametoindex(name);
-  return (index == 0) ? -1 : index;
-#endif
-}
-
-/**
- * Returns the IPv4 broadcast address of a named interface, if it exists.
- * Returns 0 if it doesn't have one.
- */
-static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
-  struct sockaddr *ret = NULL;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  /* Let's make sure the interface does have a broadcast address */
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
-    return ret;
-  }
-
-  if (if2.ifr_flags & IFF_BROADCAST) {
-    /* It does, let's retrieve it*/
-    if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
-      return ret;
-    }
-
-    ret = brdcast_store;
-    memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
-  }
-
-  return ret;
-}
-
-/**
- * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
- * interface, if it has one, otherwise return -1.
- */
-static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
-  unsigned int mask;
-  short ret;
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
-    return -1;
-  }
-
-  mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
-  ret = 0;
-  while (mask) {
-    mask <<= 1;
-    ret++;
-  }
-
-  return ret;
-}
-
-/**
- * Get the Hardware address (usually MAC address) for the named interface.
- * return puts the data in buf, and returns the length, in byte, of the
- * MAC address. Returns -1 if there is no hardware address on that interface.
- */
-static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
-  struct ifaddrs *ifa0, *ifa;
-  struct sockaddr *saddr;
-  int i;
-
-  /* Grab the interface list */
-  if (!getifaddrs(&ifa0)) {
-    /* Cycle through the interfaces */
-    for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
-      saddr = ifa->ifa_addr;
-      /* Link layer contains the MAC address */
-      if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
-        struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
-        /* Check the address is the correct length */
-        if (sadl->sdl_alen == ETHER_ADDR_LEN) {
-          memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
-          freeifaddrs(ifa0);
-          return ETHER_ADDR_LEN;
-        }
-      }
-    }
-    freeifaddrs(ifa0);
-  }
-
-  return -1;
-}
-
-static int getMTU(JNIEnv *env, int sock,  const char *ifname) {
-  struct ifreq if2;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
-    NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
-    return -1;
-  }
-
-  return  if2.ifr_mtu;
-}
-
-static int getFlags(int sock, const char *ifname, int *flags) {
-  struct ifreq if2;
-  int ret = -1;
-
-  memset((char *) &if2, 0, sizeof(if2));
-  strcpy(if2.ifr_name, ifname);
-
-  if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
-    return -1;
-  }
-
-  if (sizeof(if2.ifr_flags) == sizeof(short)) {
-    *flags = (if2.ifr_flags & 0xffff);
-  } else {
-    *flags = if2.ifr_flags;
-  }
-  return 0;
-}
-
-#endif
-
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(NetworkInterface, getMTU0, "(Ljava/lang/String;I)I"),
-  NATIVE_METHOD(NetworkInterface, getMacAddr0, "([BLjava/lang/String;I)[B"),
   NATIVE_METHOD(NetworkInterface, supportsMulticast0, "(Ljava/lang/String;I)Z"),
   NATIVE_METHOD(NetworkInterface, isLoopback0, "(Ljava/lang/String;I)Z"),
   NATIVE_METHOD(NetworkInterface, isP2P0, "(Ljava/lang/String;I)Z"),
diff --git a/ojluni/src/main/native/PlainDatagramSocketImpl.c b/ojluni/src/main/native/PlainDatagramSocketImpl.c
index f64d269..f4857df 100755
--- a/ojluni/src/main/native/PlainDatagramSocketImpl.c
+++ b/ojluni/src/main/native/PlainDatagramSocketImpl.c
@@ -58,7 +58,6 @@
 
 #include "java_net_SocketOptions.h"
 #include "java_net_PlainDatagramSocketImpl.h"
-#include "java_net_NetworkInterface.h"
 #include "JNIHelp.h"
 
 #define NATIVE_METHOD(className, functionName, signature) \
@@ -1065,55 +1064,19 @@
 
 
 /*
- * Set outgoing multicast interface designated by a NetworkInterface.
+ * Set outgoing multicast interface designated by a NetworkInterface index.
  * Throw exception if failed.
  *
  * Android changed: return 0 on success, negative on failure.
+ * Android changed: Interface index (not NetworkInterface) as the parameter
  */
-static int mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject value) {
-    static jfieldID ni_addrsID;
-    struct in_addr in;
-    jobjectArray addrArray;
-    jsize len;
-    jobject addr;
-    int i;
-
-    if (ni_addrsID == NULL ) {
-        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
-        // Android-changed: return -1 if null.
-        CHECK_NULL_RETURN(c, -1);
-        ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
-                                        "[Ljava/net/InetAddress;");
-        // Android-changed: return -1 if null.
-        CHECK_NULL_RETURN(ni_addrsID, -1);
-    }
-
-    addrArray = (*env)->GetObjectField(env, value, ni_addrsID);
-    len = (*env)->GetArrayLength(env, addrArray);
-
-    /*
-     * Check that there is at least one address bound to this
-     * interface.
-     */
-    if (len < 1) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-            "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
-        return -1;
-    }
-
-    /*
-     * We need an ipv4 address here
-     */
-    for (i = 0; i < len; i++) {
-        addr = (*env)->GetObjectArrayElement(env, addrArray, i);
-        if (getInetAddress_family(env, addr) == IPv4) {
-            in.s_addr = htonl(getInetAddress_addr(env, addr));
-            break;
-        }
-    }
+static int mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jint ifindex) {
+    struct ip_mreqn req;
+    memset(&req, 0, sizeof(req));
+    req.imr_ifindex = ifindex;
 
     if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                       (const char*)&in, sizeof(in)) < 0) {
+                       (const char*)&req, sizeof(req)) < 0) {
         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                        "Error setting socket option");
         return -1;
@@ -1125,23 +1088,12 @@
 /*
  * Set outgoing multicast interface designated by a NetworkInterface.
  * Throw exception if failed.
+ * Android changed: Interface index (not NetworkInterface) as the parameter
  */
-#ifdef AF_INET6
-static void mcast_set_if_by_if_v6(JNIEnv *env, jobject this, int fd, jobject value) {
-    static jfieldID ni_indexID;
-    int index;
-
-    if (ni_indexID == NULL) {
-        jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
-        CHECK_NULL(c);
-        ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
-        CHECK_NULL(ni_indexID);
-    }
-    index = (*env)->GetIntField(env, value, ni_indexID);
-
+static void mcast_set_if_by_if_v6(JNIEnv *env, jobject this, int fd, jint ifindex) {
     if (JVM_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
-                       (const char*)&index, sizeof(index)) < 0) {
-        if (errno == EINVAL && index > 0) {
+                       (const char*)&ifindex, sizeof(ifindex)) < 0) {
+        if (errno == EINVAL && ifindex > 0) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                 "IPV6_MULTICAST_IF failed (interface has IPv4 "
                 "address only?)");
@@ -1151,9 +1103,7 @@
         }
         return;
     }
-
 }
-#endif /* AF_INET6 */
 
 /*
  * Set outgoing multicast interface designated by an InetAddress.
@@ -1180,18 +1130,29 @@
  * Set outgoing multicast interface designated by an InetAddress.
  * Throw exception if failed.
  */
-#ifdef AF_INET6
 static void mcast_set_if_by_addr_v6(JNIEnv *env, jobject this, int fd, jobject value) {
     static jclass ni_class;
+    static jmethodID ni_getByInetAddress;
+    static jmethodID ni_getIndex;
     if (ni_class == NULL) {
         jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
         CHECK_NULL(c);
         ni_class = (*env)->NewGlobalRef(env, c);
         CHECK_NULL(ni_class);
+        ni_getByInetAddress = (*env)->GetStaticMethodID(
+            env, ni_class, "getByInetAddress", "(Ljava/net/InetAddress;)Ljava/net/NetworkInterface;");
+        CHECK_NULL(ni_getByInetAddress);
+        ni_getIndex = (*env)->GetMethodID(
+            env, ni_class, "getIndex", "()I");
+        CHECK_NULL(ni_getIndex);
     }
 
-    value = NetworkInterface_getByInetAddress0(env, ni_class, value);
-    if (value == NULL) {
+    /*
+     * Get the NetworkInterface by inetAddress
+     */
+    jobject ni_value = (*env)->CallStaticObjectMethod(
+        env, ni_class, ni_getByInetAddress, value);
+    if (ni_value == NULL) {
         if (!(*env)->ExceptionOccurred(env)) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                  "bad argument for IP_MULTICAST_IF"
@@ -1200,9 +1161,16 @@
         return;
     }
 
-    mcast_set_if_by_if_v6(env, this, fd, value);
+    /*
+     * Get the NetworkInterface index
+     */
+    jint ifindex = (*env)->CallIntMethod(env, ni_value, ni_getIndex);
+    if ((*env)->ExceptionOccurred(env)) {
+        return;
+    }
+
+    mcast_set_if_by_if_v6(env, this, fd, ifindex);
 }
-#endif
 
 /*
  * Sets the multicast interface.
@@ -1238,8 +1206,6 @@
         /*
          * value is an InetAddress.
          */
-#ifdef AF_INET6
-#ifdef __linux__
         // Android-changed: Return early if mcast_set_if_by_addr_v4 threw.
         // We don't want to call into the IPV6 code with a pending exception.
         if (mcast_set_if_by_addr_v4(env, this, fd, value)) {
@@ -1248,42 +1214,29 @@
         if (ipv6_available()) {
             mcast_set_if_by_addr_v6(env, this, fd, value);
         }
-#else  /* __linux__ not defined */
-        if (ipv6_available()) {
-            mcast_set_if_by_addr_v6(env, this, fd, value);
-        } else {
-            mcast_set_if_by_addr_v4(env, this, fd, value);
-        }
-#endif  /* __linux__ */
-#else
-        mcast_set_if_by_addr_v4(env, this, fd, value);
-#endif  /* AF_INET6 */
     }
 
     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
-        /*
-         * value is a NetworkInterface.
+      /*
+         * value is a Integer (Android-changed, openJdk uses NetworkInterface)
          */
-#ifdef AF_INET6
-#ifdef __linux__
+        static jfieldID integer_valueID;
+        if (integer_valueID == NULL) {
+            jclass c = (*env)->FindClass(env, "java/lang/Integer");
+            CHECK_NULL(c);
+            integer_valueID = (*env)->GetFieldID(env, c, "value", "I");
+            CHECK_NULL(integer_valueID);
+        }
+        int index = (*env)->GetIntField(env, value, integer_valueID);
+
         // Android-changed: Return early if mcast_set_if_by_addr_v4 threw.
         // We don't want to call into the IPV6 code with a pending exception.
-        if (mcast_set_if_by_if_v4(env, this, fd, value)) {
+        if (mcast_set_if_by_if_v4(env, this, fd, index)) {
             return;
         }
         if (ipv6_available()) {
-            mcast_set_if_by_if_v6(env, this, fd, value);
+            mcast_set_if_by_if_v6(env, this, fd, index);
         }
-#else  /* __linux__ not defined */
-        if (ipv6_available()) {
-            mcast_set_if_by_if_v6(env, this, fd, value);
-        } else {
-            mcast_set_if_by_if_v4(env, this, fd, value);
-        }
-#endif  /* __linux__ */
-#else
-        mcast_set_if_by_if_v4(env, this, fd, value);
-#endif  /* AF_INET6 */
     }
 }
 
@@ -1500,128 +1453,11 @@
  *              return NetworkInterface.
  */
 jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) {
-    jboolean isIPV4 = JNI_TRUE;
-
-#ifdef AF_INET6
-    if (ipv6_available()) {
-        isIPV4 = JNI_FALSE;
-    }
-#endif
-
-    /*
-     * IPv4 implementation
-     */
-    if (isIPV4) {
-        static jclass inet4_class;
-        static jmethodID inet4_ctrID;
-
-        static jclass ni_class;
-        static jmethodID ni_ctrID;
-        static jfieldID ni_indexID;
-        static jfieldID ni_addrsID;
-
-        jobjectArray addrArray;
-        jobject addr;
-        jobject ni;
-
-        struct in_addr in;
-        struct in_addr *inP = &in;
-        int len = sizeof(struct in_addr);
-
-#ifdef __linux__
-        struct ip_mreqn mreqn;
-#endif
-
-        if (JVM_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                           (char *)inP, &len) < 0) {
-            NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                             "Error getting socket option");
-            return NULL;
-        }
-
-        /*
-         * Construct and populate an Inet4Address
-         */
-        if (inet4_class == NULL) {
-            jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
-            CHECK_NULL_RETURN(c, NULL);
-            inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
-            CHECK_NULL_RETURN(inet4_ctrID, NULL);
-            inet4_class = (*env)->NewGlobalRef(env, c);
-            CHECK_NULL_RETURN(inet4_class, NULL);
-        }
-        addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
-        CHECK_NULL_RETURN(addr, NULL);
-
-        setInetAddress_addr(env, addr, ntohl(in.s_addr));
-
-        /*
-         * For IP_MULTICAST_IF return InetAddress
-         */
-        if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
-            return addr;
-        }
-
-        /*
-         * For IP_MULTICAST_IF2 we get the NetworkInterface for
-         * this address and return it
-         */
-        if (ni_class == NULL) {
-            jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
-            CHECK_NULL_RETURN(c, NULL);
-            ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
-            CHECK_NULL_RETURN(ni_ctrID, NULL);
-            ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
-            CHECK_NULL_RETURN(ni_indexID, NULL);
-            ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
-                                            "[Ljava/net/InetAddress;");
-            CHECK_NULL_RETURN(ni_addrsID, NULL);
-            ni_class = (*env)->NewGlobalRef(env, c);
-            CHECK_NULL_RETURN(ni_class, NULL);
-        }
-        ni = NetworkInterface_getByInetAddress0(env, ni_class, addr);
-        if (ni) {
-            return ni;
-        }
-
-        /*
-         * The address doesn't appear to be bound at any known
-         * NetworkInterface. Therefore we construct a NetworkInterface
-         * with this address.
-         */
-        ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-        CHECK_NULL_RETURN(ni, NULL);
-
-        (*env)->SetIntField(env, ni, ni_indexID, -1);
-        addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL);
-        CHECK_NULL_RETURN(addrArray, NULL);
-        (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-        (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        return ni;
-    }
-
-
-#ifdef AF_INET6
-    /*
-     * IPv6 implementation
-     */
-    if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
-        (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
-
-        static jclass ni_class;
-        static jmethodID ni_ctrID;
-        static jfieldID ni_indexID;
-        static jfieldID ni_addrsID;
-        static jclass ia_class;
-        static jmethodID ia_anyLocalAddressID;
-
+    if ((opt == java_net_SocketOptions_IP_MULTICAST_IF2) ||
+        (opt == java_net_SocketOptions_IP_MULTICAST_IF)) {
         int index;
         int len = sizeof(index);
 
-        jobjectArray addrArray;
-        jobject addr;
-        jobject ni;
-
         {
             if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                                (char*)&index, &len) < 0) {
@@ -1631,89 +1467,10 @@
             }
         }
 
-        if (ni_class == NULL) {
-            jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
-            CHECK_NULL_RETURN(c, NULL);
-            ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
-            CHECK_NULL_RETURN(ni_ctrID, NULL);
-            ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
-            CHECK_NULL_RETURN(ni_indexID, NULL);
-            ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
-                                            "[Ljava/net/InetAddress;");
-            CHECK_NULL_RETURN(ni_addrsID, NULL);
-
-            ia_class = (*env)->FindClass(env, "java/net/InetAddress");
-            CHECK_NULL_RETURN(ia_class, NULL);
-            ia_class = (*env)->NewGlobalRef(env, ia_class);
-            CHECK_NULL_RETURN(ia_class, NULL);
-            ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,
-                                                             ia_class,
-                                                             "anyLocalAddress",
-                                                             "()Ljava/net/InetAddress;");
-            CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL);
-            ni_class = (*env)->NewGlobalRef(env, c);
-            CHECK_NULL_RETURN(ni_class, NULL);
-        }
-
-        /*
-         * If multicast to a specific interface then return the
-         * interface (for IF2) or the any address on that interface
-         * (for IF).
-         */
-        if (index > 0) {
-            ni = NetworkInterface_getByIndex0(env, ni_class,
-                                                                   index);
-            if (ni == NULL) {
-                char errmsg[255];
-                sprintf(errmsg,
-                        "IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
-                        index);
-                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
-                return NULL;
-            }
-
-            /*
-             * For IP_MULTICAST_IF2 return the NetworkInterface
-             */
-            if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
-                return ni;
-            }
-
-            /*
-             * For IP_MULTICAST_IF return addrs[0]
-             */
-            addrArray = (*env)->GetObjectField(env, ni, ni_addrsID);
-            if ((*env)->GetArrayLength(env, addrArray) < 1) {
-                JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                    "IPV6_MULTICAST_IF returned interface without IP bindings");
-                return NULL;
-            }
-
-            addr = (*env)->GetObjectArrayElement(env, addrArray, 0);
-            return addr;
-        }
-
-        /*
-         * Multicast to any address - return anyLocalAddress
-         * or a NetworkInterface with addrs[0] set to anyLocalAddress
-         */
-
-        addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID,
-                                              NULL);
-        if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
-            return addr;
-        }
-
-        ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
-        CHECK_NULL_RETURN(ni, NULL);
-        (*env)->SetIntField(env, ni, ni_indexID, -1);
-        addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL);
-        CHECK_NULL_RETURN(addrArray, NULL);
-        (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
-        (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
-        return ni;
+        jobject ifindex = createInteger(env, index);
+        CHECK_NULL_RETURN(ifindex, NULL);
+        return ifindex;
     }
-#endif
     return NULL;
 }