Implement the Java 6 NetworkInterface/InterfaceAddress functionality.

The Java bits are based on harmony's code (though only the bit that pulls
out the sub-interfaces is copied verbatim), but the native side is new
code, continuing our previous plan of (a) doing the least possible work
on the native side and (b) using the BSD getifaddrs(3) interface as our
portability layer.

This patch also updates our NetworkInterfaceTest to be the latest code
from harmony's java6 branch.

We pass all the harmony and jtreg tests, and visual inspection shows that
the untested (and hard to test) bits -- such as prefix length and hardware
address -- are correct.
diff --git a/libcore/luni/src/main/java/java/net/InetAddress.java b/libcore/luni/src/main/java/java/net/InetAddress.java
index ad96ed6..4827e70 100644
--- a/libcore/luni/src/main/java/java/net/InetAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetAddress.java
@@ -27,8 +27,10 @@
 import java.security.AccessController;
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.StringTokenizer;
 
 import org.apache.harmony.luni.net.NetUtil;
@@ -114,40 +116,12 @@
         super();
     }
 
-    // BEGIN android-removed
-    /**
-     * Constructs an {@code InetAddress}, representing the {@code address} and
-     * {@code hostName}.
-     *
-     * @param address
-     *            the network address.
-     */
-    // InetAddress(byte[] address) {
-    //     super();
-    //     this.ipaddress = address;
-    // }
+    // BEGIN android-removed: use Inet4Address/Inet6Address instead, as appropriate.
+    // InetAddress(byte[] address) { ... }
     // END android-removed
 
-    // BEGIN android-removed
-    /**
-     * Constructs an {@code InetAddress}, representing the {@code address} and
-     * {@code hostName}.
-     *
-     * @param address
-     *            the network address.
-     *
-     */
-    // InetAddress(byte[] address, String hostName) {
-    //     super();
-    //     this.ipaddress = address;
-    //     this.hostName = hostName;
-    // }
-    // END android-removed
-
-    // BEGIN android-removed
-    // CacheElement cacheElement() {
-    //     return new CacheElement();
-    // }
+    // BEGIN android-removed: use Inet4Address/Inet6Address instead, as appropriate.
+    // InetAddress(byte[] address, String hostName) { ... }
     // END android-removed
 
     /**
@@ -744,7 +718,7 @@
      * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection
      * on port 7 (Echo) of the remote host is established.
      *
-     * @param netif
+     * @param networkInterface
      *            the network interface on which to connection should be
      *            established.
      * @param ttl
@@ -759,36 +733,16 @@
      * @throws IllegalArgumentException
      *             if ttl or timeout is less than zero.
      */
-    public boolean isReachable(NetworkInterface netif, final int ttl,
+    public boolean isReachable(NetworkInterface networkInterface, final int ttl,
             final int timeout) throws IOException {
-        if (0 > ttl || 0 > timeout) {
+        if (ttl < 0 || timeout < 0) {
             throw new IllegalArgumentException(Msg.getString("K0051")); //$NON-NLS-1$
         }
-        boolean reachable = false;
-        if (null == netif) {
-            // network interface is null, binds to no address
-            // BEGIN android-changed
-            // reachable = NETIMPL.isReachableByICMP(this, null, ttl, timeout);
-            // if (!reachable) {
-                reachable = isReachableByTCP(this, null, timeout);
-            // }
-            // END android-changed
+        if (networkInterface == null) {
+            return isReachableByTCP(this, null, timeout);
         } else {
-            // Not Bind to any address
-            if (null == netif.addresses) {
-                return false;
-            }
-            // binds to all address on this NetworkInterface, tries ICMP ping
-            // first
-            // BEGIN android-changed
-            // reachable = isReachableByICMPUseMultiThread(netif, ttl, timeout);
-            // if (!reachable) {
-                // tries TCP echo if ICMP ping fails
-                reachable = isReachableByMultiThread(netif, ttl, timeout);
-            // }
-            // END adnroid-changed
+            return isReachableByMultiThread(networkInterface, ttl, timeout);
         }
-        return reachable;
     }
 
     /*
@@ -800,16 +754,14 @@
             final int ttl, final int timeout)
     // END android-changed
             throws IOException {
-        if (null == netif.addresses) {
+        List<InetAddress> addresses = Collections.list(netif.getInetAddresses());
+        if (addresses.isEmpty()) {
             return false;
         }
-        Enumeration<InetAddress> addresses = netif.getInetAddresses();
         reached = false;
-        addrCount = netif.addresses.length;
+        addrCount = addresses.size();
         boolean needWait = false;
-        while (addresses.hasMoreElements()) {
-            final InetAddress addr = addresses.nextElement();
-
+        for (final InetAddress addr : addresses) {
             // loopback interface can only reach to local addresses
             if (addr.isLoopbackAddress()) {
                 Enumeration<NetworkInterface> NetworkInterfaces = NetworkInterface
diff --git a/libcore/luni/src/main/java/java/net/InterfaceAddress.java b/libcore/luni/src/main/java/java/net/InterfaceAddress.java
index 7bc3936..2fa99f7 100644
--- a/libcore/luni/src/main/java/java/net/InterfaceAddress.java
+++ b/libcore/luni/src/main/java/java/net/InterfaceAddress.java
@@ -20,22 +20,131 @@
  * Identifies one of a network interface's addresses.
  * These are passed back from the JNI behind NetworkInterface.getNetworkInterfaces.
  * Multiple addresses for the same interface are collected together on the Java side.
+ *
+ * @hide
+ * @since 1.6
  */
-class InterfaceAddress {
-    // An IPv4 or IPv6 address.
-    final InetAddress address;
-
-    // The kernel's interface index for the network interface this address
-    // is currently assigned to. Values start at 1, because 0 means "unknown"
-    // or "any", depending on context.
+public class InterfaceAddress {
+    /**
+     * The kernel's interface index for the network interface this address
+     * is currently assigned to. Values start at 1, because 0 means "unknown"
+     * or "any", depending on context.
+     */
     final int index;
 
-    // The network interface's name. "lo" or "eth0", for example.
+    /**
+     * The network interface's name. "lo" or "eth0", for example.
+     */
     final String name;
 
-    InterfaceAddress(int index, String name, InetAddress address) {
+    /**
+     * An IPv4 or IPv6 address.
+     */
+    final InetAddress address;
+
+    /**
+     * The IPv4 broadcast address, or null for IPv6.
+     */
+    private final InetAddress broadcastAddress;
+
+    private final short prefixLength;
+
+    InterfaceAddress(int index, String name, InetAddress address, InetAddress mask) {
+        assert ((address instanceof Inet4Address) == (mask instanceof Inet4Address));
         this.index = index;
         this.name = name;
         this.address = address;
+        this.broadcastAddress = makeBroadcastAddress(address, mask);
+        this.prefixLength = countPrefixLength(mask);
+    }
+
+    private static InetAddress makeBroadcastAddress(InetAddress address, InetAddress mask) {
+        if (!(address instanceof Inet4Address)) {
+            return null;
+        }
+        byte[] broadcast = new byte[4];
+        byte[] maskBytes = mask.ipaddress;
+        byte[] addrBytes = address.ipaddress;
+        if (maskBytes[0] != 0) {
+            for (int i = 0; i < broadcast.length; ++i) {
+                broadcast[i] = (byte) (addrBytes[i] | ~maskBytes[i]);
+            }
+        }
+        return new Inet4Address(broadcast);
+    }
+
+    private static short countPrefixLength(InetAddress mask) {
+        short count = 0;
+        for (byte b : mask.ipaddress) {
+            for (int i = 0; i < 8; ++i) {
+                if ((b & (1 << i)) != 0) {
+                    ++count;
+                }
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Tests whether this object is equal to another one. Returns true if
+     * the address, broadcast address and prefix length are all equal.
+     *
+     * @param obj the object to be compared.
+     * @return true if 'obj' is equal to this InterfaceAddress, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this){
+            return true;
+        }
+        if (!(obj instanceof InterfaceAddress)) {
+            return false;
+        }
+        InterfaceAddress rhs = (InterfaceAddress) obj;
+        return ((address == null) ? rhs.address == null : address.equals(rhs.address)) &&
+                (rhs.prefixLength == prefixLength) &&
+                ((broadcastAddress == null) ? rhs.broadcastAddress == null : broadcastAddress.equals(rhs.broadcastAddress));
+    }
+
+    @Override
+    public int hashCode() {
+        int hashCode = address == null ? 0 : -address.hashCode();
+        hashCode += broadcastAddress == null ? 0 : broadcastAddress.hashCode();
+        hashCode += prefixLength;
+        return hashCode;
+    }
+
+    /**
+     * Returns a string representation for this interface address.
+     * The string is of the form: InetAddress / prefix length [ broadcast address ].
+     *
+     * @return a string representation of this interface address.
+     */
+    @Override
+    public String toString() {
+        return address + "/" + prefixLength + " [" + broadcastAddress + "]";
+    }
+
+    /**
+     * Returns the InetAddress for this address.
+     */
+    public InetAddress getAddress() {
+        return address;
+    }
+
+    /**
+     * Returns the subnet-directed broadcast address if this is an IPv4 interface, null otherwise.
+     */
+    public InetAddress getBroadcast() {
+        return broadcastAddress;
+    }
+
+    /**
+     * Returns the network prefix length in bits.
+     * (In IPv4 parlance, this is known as the subnet mask,
+     * but this method applies to IPv6 addresses too.)
+     */
+    public short getNetworkPrefixLength() {
+        return prefixLength;
     }
 }
diff --git a/libcore/luni/src/main/java/java/net/NetworkInterface.java b/libcore/luni/src/main/java/java/net/NetworkInterface.java
index 93a30cb..b3e242e 100644
--- a/libcore/luni/src/main/java/java/net/NetworkInterface.java
+++ b/libcore/luni/src/main/java/java/net/NetworkInterface.java
@@ -17,9 +17,12 @@
 
 package java.net;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
@@ -37,49 +40,45 @@
     private static final int CHECK_CONNECT_NO_PORT = -1;
 
     static final int NO_INTERFACE_INDEX = 0;
-
     static final int UNSET_INTERFACE_INDEX = -1;
 
-    private String name;
+    private final String name;
+    private final String displayName;
+    private final List<InterfaceAddress> interfaceAddresses = new LinkedList<InterfaceAddress>();
 
-    private String displayName;
-
-    InetAddress addresses[];
+    private final List<InetAddress> addresses = new LinkedList<InetAddress>();
 
     // The interface index is a positive integer which is non-negative. Where
     // value is zero then we do not have an index for the interface (which
     // occurs in systems which only support IPV4)
     private int interfaceIndex;
 
-    private int hashCode;
+    private NetworkInterface parent = null;
+
+    private final List<NetworkInterface> children = new LinkedList<NetworkInterface>();
 
     // BEGIN android-changed: we pay this extra complexity on the Java side
     // in return for vastly simpler native code.
-    private static native InterfaceAddress[] getInterfaceAddresses() throws SocketException;
+    private static native InterfaceAddress[] getAllInterfaceAddressesImpl() throws SocketException;
 
     private static NetworkInterface[] getNetworkInterfacesImpl() throws SocketException {
         Map<String, NetworkInterface> networkInterfaces = new LinkedHashMap<String, NetworkInterface>();
-        for (InterfaceAddress ia : getInterfaceAddresses()) {
+        for (InterfaceAddress ia : getAllInterfaceAddressesImpl()) {
             if (ia != null) { // The array may contain harmless null elements.
                 String name = ia.name;
                 NetworkInterface ni = networkInterfaces.get(name);
                 if (ni == null) {
                     ni = new NetworkInterface(name, name, new InetAddress[] { ia.address }, ia.index);
+                    ni.interfaceAddresses.add(ia);
                     networkInterfaces.put(name, ni);
                 } else {
-                    ni.addInterfaceAddress(ia.address);
+                    ni.addresses.add(ia.address);
+                    ni.interfaceAddresses.add(ia);
                 }
             }
         }
         return networkInterfaces.values().toArray(new NetworkInterface[networkInterfaces.size()]);
     }
-
-    private void addInterfaceAddress(InetAddress address) {
-        InetAddress[] newAddresses = new InetAddress[addresses.length + 1];
-        System.arraycopy(addresses, 0, newAddresses, 0, addresses.length);
-        newAddresses[addresses.length] = address;
-        addresses = newAddresses;
-    }
     // END android-changed
 
     /**
@@ -96,12 +95,16 @@
      *            an index for the interface. Only set for platforms that
      *            support IPV6.
      */
-    NetworkInterface(String name, String displayName, InetAddress addresses[],
+    NetworkInterface(String name, String displayName, InetAddress[] addresses,
             int interfaceIndex) {
         this.name = name;
         this.displayName = displayName;
-        this.addresses = addresses;
         this.interfaceIndex = interfaceIndex;
+        if (addresses != null) {
+            for (InetAddress address : addresses) {
+                this.addresses.add(address);
+            }
+        }
     }
 
     /**
@@ -122,8 +125,8 @@
      * @return the first address if one exists, otherwise null.
      */
     InetAddress getFirstAddress() {
-        if ((addresses != null) && (addresses.length >= 1)) {
-            return addresses[0];
+        if (addresses.size() >= 1) {
+            return addresses.get(0);
         }
         return null;
     }
@@ -143,63 +146,21 @@
      * @return the address list of the represented network interface.
      */
     public Enumeration<InetAddress> getInetAddresses() {
-        /*
-         * create new vector from which Enumeration to be returned can be
-         * generated set the initial capacity to be the number of addresses for
-         * the network interface which is the maximum required size
-         */
-
-        /*
-         * return an empty enumeration if there are no addresses associated with
-         * the interface
-         */
-        if (addresses == null) {
-            return new Vector<InetAddress>(0).elements();
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null || addresses.isEmpty()) {
+            return Collections.enumeration(addresses);
         }
-
-        /*
-         * for those configuration that support the security manager we only
-         * return addresses for which checkConnect returns true
-         */
-        Vector<InetAddress> accessibleAddresses = new Vector<InetAddress>(
-                addresses.length);
-
-        /*
-         * get the security manager. If one does not exist just return the full
-         * list
-         */
-        SecurityManager security = System.getSecurityManager();
-        if (security == null) {
-            return (new Vector<InetAddress>(Arrays.asList(addresses)))
-                    .elements();
-        }
-
-        /*
-         * ok security manager exists so check each address and return those
-         * that pass
-         */
-        for (InetAddress element : addresses) {
-            if (security != null) {
-                try {
-                    /*
-                     * since we don't have a port in this case we pass in
-                     * NO_PORT
-                     */
-                    security.checkConnect(element.getHostName(),
-                            CHECK_CONNECT_NO_PORT);
-                    accessibleAddresses.add(element);
-                } catch (SecurityException e) {
-                }
+        // TODO: Android should ditch SecurityManager and the associated pollution.
+        List<InetAddress> result = new ArrayList<InetAddress>(addresses.size());
+        for (InetAddress address : addresses) {
+            try {
+                sm.checkConnect(address.getHostName(), CHECK_CONNECT_NO_PORT);
+            } catch (SecurityException e) {
+                continue;
             }
+            result.add(address);
         }
-
-        Enumeration<InetAddress> theAccessibleElements = accessibleAddresses
-                .elements();
-        if (theAccessibleElements.hasMoreElements()) {
-            return accessibleAddresses.elements();
-        }
-
-        return new Vector<InetAddress>(0).elements();
+        return Collections.enumeration(result);
     }
 
     /**
@@ -232,24 +193,13 @@
      * @throws NullPointerException
      *             if the given interface's name is {@code null}.
      */
-    public static NetworkInterface getByName(String interfaceName)
-            throws SocketException {
-
+    public static NetworkInterface getByName(String interfaceName) throws SocketException {
         if (interfaceName == null) {
             throw new NullPointerException(Msg.getString("K0330")); //$NON-NLS-1$
         }
-
-        /*
-         * get the list of interfaces, and then loop through the list to look
-         * for one with a matching name
-         */
-        Enumeration<NetworkInterface> interfaces = getNetworkInterfaces();
-        if (interfaces != null) {
-            while (interfaces.hasMoreElements()) {
-                NetworkInterface netif = interfaces.nextElement();
-                if (netif.getName().equals(interfaceName)) {
-                    return netif;
-                }
+        for (NetworkInterface networkInterface : getNetworkInterfacesList()) {
+            if (networkInterface.name.equals(interfaceName)) {
+                return networkInterface;
             }
         }
         return null;
@@ -268,38 +218,13 @@
      * @throws NullPointerException
      *             if the given interface address is invalid.
      */
-    public static NetworkInterface getByInetAddress(InetAddress address)
-            throws SocketException {
-
+    public static NetworkInterface getByInetAddress(InetAddress address) throws SocketException {
         if (address == null) {
             throw new NullPointerException(Msg.getString("K0331")); //$NON-NLS-1$
         }
-
-        /*
-         * get the list of interfaces, and then loop through the list. For each
-         * interface loop through the associated set of internet addresses and
-         * see if one matches. If so return that network interface
-         */
-        Enumeration<NetworkInterface> interfaces = getNetworkInterfaces();
-        if (interfaces != null) {
-            while (interfaces.hasMoreElements()) {
-                NetworkInterface netif = interfaces.nextElement();
-                /*
-                 * to be compatible use the raw addresses without any security
-                 * filtering
-                 */
-                // Enumeration netifAddresses = netif.getInetAddresses();
-                if ((netif.addresses != null) && (netif.addresses.length != 0)) {
-                    Enumeration<InetAddress> netifAddresses = (new Vector<InetAddress>(
-                            Arrays.asList(netif.addresses))).elements();
-                    if (netifAddresses != null) {
-                        while (netifAddresses.hasMoreElements()) {
-                            if (address.equals(netifAddresses.nextElement())) {
-                                return netif;
-                            }
-                        }
-                    }
-                }
+        for (NetworkInterface networkInterface : getNetworkInterfacesList()) {
+            if (networkInterface.addresses.contains(address)) {
+                return networkInterface;
             }
         }
         return null;
@@ -315,32 +240,53 @@
      *             if an error occurs while getting the network interface
      *             information.
      */
-    public static Enumeration<NetworkInterface> getNetworkInterfaces()
-            throws SocketException {
+    public static Enumeration<NetworkInterface> getNetworkInterfaces() throws SocketException {
+        return Collections.enumeration(getNetworkInterfacesList());
+    }
+
+    private static List<NetworkInterface> getNetworkInterfacesList() throws SocketException {
         NetworkInterface[] interfaces = getNetworkInterfacesImpl();
-        if (interfaces == null) {
-            return null;
-        }
 
         for (NetworkInterface netif : interfaces) {
             // Ensure that current NetworkInterface is bound to at least
             // one InetAddress before processing
-            if (netif.addresses != null) {
-                for (InetAddress addr : netif.addresses) {
-                    if (16 == addr.ipaddress.length) {
-                        if (addr.isLinkLocalAddress()
-                                || addr.isSiteLocalAddress()) {
-                            ((Inet6Address) addr).scopedIf = netif;
-                            ((Inet6Address) addr).ifname = netif.name;
-                            ((Inet6Address) addr).scope_ifname_set = true;
-                        }
+            for (InetAddress addr : netif.addresses) {
+                if (addr.ipaddress.length == 16) {
+                    if (addr.isLinkLocalAddress() || addr.isSiteLocalAddress()) {
+                        ((Inet6Address) addr).scopedIf = netif;
+                        ((Inet6Address) addr).ifname = netif.name;
+                        ((Inet6Address) addr).scope_ifname_set = true;
                     }
                 }
             }
         }
 
-        return (new Vector<NetworkInterface>(Arrays.asList(interfaces)))
-                .elements();
+        List<NetworkInterface> result = new ArrayList<NetworkInterface>();
+        boolean[] peeked = new boolean[interfaces.length];
+        for (int counter = 0; counter < interfaces.length; counter++) {
+            // If this interface has been touched, continue.
+            if (peeked[counter]) {
+                continue;
+            }
+            int counter2 = counter;
+            // Checks whether the following interfaces are children.
+            for (; counter2 < interfaces.length; counter2++) {
+                if (peeked[counter2]) {
+                    continue;
+                }
+                if (interfaces[counter2].name.startsWith(interfaces[counter].name + ":")) {
+                    // Tagged as peeked
+                    peeked[counter2] = true;
+                    interfaces[counter].children.add(interfaces[counter2]);
+                    interfaces[counter2].parent = interfaces[counter];
+                    interfaces[counter].addresses.addAll(interfaces[counter2].addresses);
+                }
+            }
+            // Tagged as peeked
+            result.add(interfaces[counter]);
+            peeked[counter] = true;
+        }
+        return result;
     }
 
     /**
@@ -357,77 +303,27 @@
      */
     @Override
     public boolean equals(Object obj) {
-        // Return true if it is the exact same object.
         if (obj == this) {
             return true;
         }
-
-        // Ensure it is the right type.
         if (!(obj instanceof NetworkInterface)) {
             return false;
         }
-
-        /*
-         * Make sure that some simple checks pass. If the name is not the same
-         * then we are sure it is not the same one. We don't check the hashcode
-         * as it is generated from the name which we check
-         */
-        NetworkInterface netif = (NetworkInterface) obj;
-
-        if (netif.getIndex() != interfaceIndex) {
-            return false;
-        }
-
-        if (!(name.equals("")) && (!netif.getName().equals(name))) { //$NON-NLS-1$
-            return false;
-        }
-
-        if ((name.equals("")) && (!netif.getName().equals(displayName))) { //$NON-NLS-1$
-            return false;
-        }
-
-        // Now check that the collection of internet addresses are equal.
-        Enumeration<InetAddress> netifAddresses = netif.getInetAddresses();
-        Enumeration<InetAddress> localifAddresses = getInetAddresses();
-
-        // Check for both null (same), or one null (not same).
-        if (netifAddresses == null) {
-            return localifAddresses == null;
-        }
-        if (localifAddresses == null) {
-            return false;
-        }
-
-        // Both are not null, check InetAddress elements.
-        while (netifAddresses.hasMoreElements()
-                && localifAddresses.hasMoreElements()) {
-            if (!(localifAddresses.nextElement()).equals(
-                    netifAddresses.nextElement())) {
-                return false;
-            }
-        }
-
-        /*
-         * Now make sure that they had the same number of addresses, if not they
-         * are not the same interface.
-         */
-        return !netifAddresses.hasMoreElements()
-                && !localifAddresses.hasMoreElements();
+        NetworkInterface rhs = (NetworkInterface) obj;
+        // TODO: should the order of the addresses matter (we use List.equals)?
+        return interfaceIndex == rhs.interfaceIndex &&
+                name.equals(rhs.name) && displayName.equals(rhs.displayName) &&
+                addresses.equals(rhs.addresses);
     }
 
     /**
-     * Gets the hashcode for this {@code NetworkInterface} instance. Since the
-     * name should be unique for each network interface the hashcode is
+     * Returns the hash code for this {@code NetworkInterface}. Since the
+     * name should be unique for each network interface the hash code is
      * generated using this name.
-     * 
-     * @return the hashcode value for this {@code NetworkInterface} instance.
      */
     @Override
     public int hashCode() {
-        if (hashCode == 0) {
-            hashCode = name.hashCode();
-        }
-        return hashCode;
+        return name.hashCode();
     }
 
     /**
@@ -464,4 +360,174 @@
         }
         return string.toString();
     }
+
+    /**
+     * Returns a List the InterfaceAddresses for this network interface.
+     * <p>
+     * If there is a security manager, its checkConnect method is called with
+     * the InetAddress for each InterfaceAddress. Only InterfaceAddresses where
+     * the checkConnect doesn't throw a SecurityException will be returned.
+     * 
+     * @return a List of the InterfaceAddresses for this network interface.
+     * @since 1.6
+     * @hide
+     */
+    public List<InterfaceAddress> getInterfaceAddresses() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            return Collections.unmodifiableList(interfaceAddresses);
+        }
+        // TODO: Android should ditch SecurityManager and the associated pollution.
+        List<InterfaceAddress> result = new ArrayList<InterfaceAddress>(interfaceAddresses.size());
+        for (InterfaceAddress ia : interfaceAddresses) {
+            try {
+                sm.checkConnect(ia.getAddress().getHostName(), CHECK_CONNECT_NO_PORT);
+            } catch (SecurityException e) {
+                continue;
+            }
+            result.add(ia);
+        }
+        return result;
+    }
+
+    /**
+     * Returns an {@code Enumeration} of all the sub-interfaces of this network interface.
+     * Sub-interfaces are also known as virtual interfaces.
+     * <p>
+     * For example, {@code eth0:1} would be a sub-interface of {@code eth0}.
+     * 
+     * @return an Enumeration of all the sub-interfaces of this network interface
+     * @since 1.6
+     * @hide
+     */
+    public Enumeration<NetworkInterface> getSubInterfaces() {
+        return Collections.enumeration(children);
+    }
+
+    /**
+     * Returns the parent NetworkInterface of this interface if this is a
+     * sub-interface, or null if it's a physical (non virtual) interface.
+     * 
+     * @return the NetworkInterface this interface is attached to.
+     * @since 1.6
+     * @hide
+     */
+    public NetworkInterface getParent() {
+        return parent;
+    }
+
+    /**
+     * Returns true if this network interface is up.
+     * 
+     * @return true if the interface is up.
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public boolean isUp() throws SocketException {
+        if (addresses.isEmpty()) {
+            return false;
+        }
+        return isUpImpl(name, interfaceIndex);
+    }
+    private static native boolean isUpImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns true if this network interface is a loopback interface.
+     * 
+     * @return true if the interface is a loopback interface.
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public boolean isLoopback() throws SocketException {
+        if (addresses.isEmpty()) {
+            return false;
+        }
+        return isLoopbackImpl(name, interfaceIndex);
+    }
+    private static native boolean isLoopbackImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns true if this network interface is a point-to-point interface.
+     * (For example, a PPP connection using a modem.)
+     * 
+     * @return true if the interface is point-to-point.
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public boolean isPointToPoint() throws SocketException {
+        if (addresses.isEmpty()) {
+            return false;
+        }
+        return isPointToPointImpl(name, interfaceIndex);
+    }
+    private static native boolean isPointToPointImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns true if this network interface supports multicast.
+     * 
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public boolean supportsMulticast() throws SocketException {
+        if (addresses.isEmpty()) {
+            return false;
+        }
+        return supportsMulticastImpl(name, interfaceIndex);
+    }
+    private static native boolean supportsMulticastImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns the hardware address of the interface, if it has one, and the
+     * user has the necessary privileges to access the address.
+     * 
+     * @return a byte array containing the address or null if the address
+     *         doesn't exist or is not accessible.
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public byte[] getHardwareAddress() throws SocketException {
+        if (addresses.isEmpty()) {
+            return new byte[0];
+        }
+        return getHardwareAddressImpl(name, interfaceIndex);
+    }
+    private static native byte[] getHardwareAddressImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns the Maximum Transmission Unit (MTU) of this interface.
+     * 
+     * @return the value of the MTU for the interface.
+     * @throws SocketException if an I/O error occurs.
+     * @since 1.6
+     * @hide
+     */
+    public int getMTU() throws SocketException {
+        if (addresses.isEmpty()) {
+            return 0;
+        }
+        return getMTUImpl(name, interfaceIndex);
+    }
+    private static native int getMTUImpl(String n, int index) throws SocketException;
+
+    /**
+     * Returns true if this interface is a virtual interface (also called
+     * a sub-interface). Virtual interfaces are, on some systems, interfaces
+     * created as a child of a physical interface and given different settings
+     * (like address or MTU). Usually the name of the interface will the name of
+     * the parent followed by a colon (:) and a number identifying the child,
+     * since there can be several virtual interfaces attached to a single
+     * physical interface.
+     * 
+     * @return true if this interface is a virtual interface.
+     * @since 1.6
+     * @hide
+     */
+    public boolean isVirtual() {
+        return parent != null;
+    }
 }
diff --git a/libcore/luni/src/main/native/ifaddrs-android.h b/libcore/luni/src/main/native/ifaddrs-android.h
index 0c3d203..de87b02 100644
--- a/libcore/luni/src/main/native/ifaddrs-android.h
+++ b/libcore/luni/src/main/native/ifaddrs-android.h
@@ -17,8 +17,13 @@
 #ifndef IFADDRS_ANDROID_H_included
 #define IFADDRS_ANDROID_H_included
 
+#include <arpa/inet.h>
 #include <cstring>
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
 #include <new>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <stdio.h>
@@ -43,11 +48,14 @@
     // Interface flags.
     unsigned int ifa_flags;
 
-    // Interface address.
+    // Interface network address.
     sockaddr* ifa_addr;
 
+    // Interface netmask.
+    sockaddr* ifa_netmask;
+
     ifaddrs(ifaddrs* next)
-    : ifa_next(next), ifa_name(NULL), ifa_flags(0), ifa_addr(NULL)
+    : ifa_next(next), ifa_name(NULL), ifa_flags(0), ifa_addr(NULL), ifa_netmask(NULL)
     {
     }
 
@@ -55,6 +63,7 @@
         delete ifa_next;
         delete[] ifa_name;
         delete ifa_addr;
+        delete ifa_netmask;
     }
 
     // Sadly, we can't keep the interface index for portability with BSD.
@@ -91,16 +100,41 @@
     // stitch the two bits together into the sockaddr that's part of
     // our portable interface.
     void setAddress(int family, void* data, size_t byteCount) {
+        // Set the address proper...
         sockaddr_storage* ss = new sockaddr_storage;
-        ss->ss_family = family;
-        if (family == AF_INET) {
-            void* dst = &reinterpret_cast<sockaddr_in*>(ss)->sin_addr;
-            memcpy(dst, data, byteCount);
-        } else if (family == AF_INET6) {
-            void* dst = &reinterpret_cast<sockaddr_in6*>(ss)->sin6_addr;
-            memcpy(dst, data, byteCount);
-        }
+        memset(ss, 0, sizeof(*ss));
         ifa_addr = reinterpret_cast<sockaddr*>(ss);
+        ss->ss_family = family;
+        uint8_t* dst = sockaddrBytes(family, ss);
+        memcpy(dst, data, byteCount);
+    }
+
+    // Netlink gives us the prefix length as a bit count. We need to turn
+    // that into a BSD-compatible netmask represented by a sockaddr*.
+    void setNetmask(int family, size_t prefixLength) {
+        // ...and work out the netmask from the prefix length.
+        sockaddr_storage* ss = new sockaddr_storage;
+        memset(ss, 0, sizeof(*ss));
+        ifa_netmask = reinterpret_cast<sockaddr*>(ss);
+        ss->ss_family = family;
+        uint8_t* dst = sockaddrBytes(family, ss);
+        memset(dst, 0xff, prefixLength / 8);
+        if ((prefixLength % 8) != 0) {
+            dst[prefixLength/8] = (0xff << (8 - (prefixLength % 8)));
+        }
+    }
+
+    // Returns a pointer to the first byte in the address data (which is
+    // stored in network byte order).
+    uint8_t* sockaddrBytes(int family, sockaddr_storage* ss) {
+        if (family == AF_INET) {
+            sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
+            return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
+        } else if (family == AF_INET6) {
+            sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
+            return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
+        }
+        return NULL;
     }
 };
 
@@ -167,6 +201,7 @@
                                     return -1;
                                 }
                                 (*result)->setAddress(family, RTA_DATA(rta), RTA_PAYLOAD(rta));
+                                (*result)->setNetmask(family, address->ifa_prefixlen);
                             }
                         }
                         rta = RTA_NEXT(rta, ifaPayloadLength);
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
index 1a72710..bf2c89d 100644
--- a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
+++ b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
@@ -64,27 +64,34 @@
             jniStrError(errno, buf, sizeof(buf)));
 }
 
-static jobject makeInterfaceAddress(JNIEnv* env, jint interfaceIndex, const char* name, sockaddr_storage* ss) {
+static jobject makeInterfaceAddress(JNIEnv* env, jint interfaceIndex, ifaddrs* ifa) {
     jclass clazz = env->FindClass("java/net/InterfaceAddress");
     if (clazz == NULL) {
         return NULL;
     }
-    jmethodID constructor = env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;Ljava/net/InetAddress;)V");
+    jmethodID constructor = env->GetMethodID(clazz, "<init>",
+            "(ILjava/lang/String;Ljava/net/InetAddress;Ljava/net/InetAddress;)V");
     if (constructor == NULL) {
         return NULL;
     }
-    jobject javaName = env->NewStringUTF(name);
+    jobject javaName = env->NewStringUTF(ifa->ifa_name);
     if (javaName == NULL) {
         return NULL;
     }
-    jobject javaAddress = socketAddressToInetAddress(env, ss);
+    sockaddr_storage* addr = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
+    jobject javaAddress = socketAddressToInetAddress(env, addr);
     if (javaAddress == NULL) {
         return NULL;
     }
-    return env->NewObject(clazz, constructor, interfaceIndex, javaName, javaAddress);
+    sockaddr_storage* mask = reinterpret_cast<sockaddr_storage*>(ifa->ifa_netmask);
+    jobject javaMask = socketAddressToInetAddress(env, mask);
+    if (javaMask == NULL) {
+        return NULL;
+    }
+    return env->NewObject(clazz, constructor, interfaceIndex, javaName, javaAddress, javaMask);
 }
 
-static jobjectArray getInterfaceAddresses(JNIEnv* env, jclass) {
+static jobjectArray getAllInterfaceAddressesImpl(JNIEnv* env, jclass) {
     // Get the list of interface addresses.
     ScopedInterfaceAddresses addresses;
     if (!addresses.init()) {
@@ -128,8 +135,7 @@
             continue;
         }
         // Make a new InterfaceAddress, and insert it into the array.
-        sockaddr_storage* ss = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
-        jobject element = makeInterfaceAddress(env, interfaceIndex, ifa->ifa_name, ss);
+        jobject element = makeInterfaceAddress(env, interfaceIndex, ifa);
         if (element == NULL) {
             return NULL;
         }
@@ -142,9 +148,89 @@
     return result;
 }
 
+static bool doIoctl(JNIEnv* env, jstring name, int request, ifreq& ifr) {
+    // Copy the name into the ifreq structure, if there's room...
+    jsize nameLength = env->GetStringLength(name);
+    if (nameLength >= IFNAMSIZ) {
+        errno = ENAMETOOLONG;
+        jniThrowSocketException(env);
+        return false;
+    }
+    memset(&ifr, 0, sizeof(ifr));
+    env->GetStringUTFRegion(name, 0, nameLength, ifr.ifr_name);
+
+    // ...and do the ioctl.
+    ScopedFd fd(socket(AF_INET, SOCK_DGRAM, 0));
+    if (fd.get() == -1) {
+        jniThrowSocketException(env);
+        return false;
+    }
+    int rc = ioctl(fd.get(), request, &ifr);
+    if (rc == -1) {
+        jniThrowSocketException(env);
+        return false;
+    }
+    return true;
+}
+
+static jboolean hasFlag(JNIEnv* env, jstring name, int flag) {
+    ifreq ifr;
+    doIoctl(env, name, SIOCGIFFLAGS, ifr); // May throw.
+    return (ifr.ifr_flags & flag) != 0;
+}
+
+static jbyteArray getHardwareAddressImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    ifreq ifr;
+    if (!doIoctl(env, name, SIOCGIFHWADDR, ifr)) {
+        return NULL;
+    }
+    jbyte bytes[IFHWADDRLEN];
+    bool isEmpty = true;
+    for (int i = 0; i < IFHWADDRLEN; ++i) {
+        bytes[i] = ifr.ifr_hwaddr.sa_data[i];
+        if (bytes[i] != 0) {
+            isEmpty = false;
+        }
+    }
+    if (isEmpty) {
+        return NULL;
+    }
+    jbyteArray result = env->NewByteArray(IFHWADDRLEN);
+    env->SetByteArrayRegion(result, 0, IFHWADDRLEN, bytes);
+    return result;
+}
+
+static jint getMTUImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    ifreq ifr;
+    doIoctl(env, name, SIOCGIFMTU, ifr); // May throw.
+    return ifr.ifr_mtu;
+}
+
+static jboolean isLoopbackImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    return hasFlag(env, name, IFF_LOOPBACK);
+}
+
+static jboolean isPointToPointImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    return hasFlag(env, name, IFF_POINTOPOINT); // Unix API typo!
+}
+
+static jboolean isUpImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    return hasFlag(env, name, IFF_UP);
+}
+
+static jboolean supportsMulticastImpl(JNIEnv* env, jclass, jstring name, jint index) {
+    return hasFlag(env, name, IFF_MULTICAST);
+}
+
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "getInterfaceAddresses", "()[Ljava/net/InterfaceAddress;", (void*) getInterfaceAddresses },
+    { "getAllInterfaceAddressesImpl", "()[Ljava/net/InterfaceAddress;", (void*) getAllInterfaceAddressesImpl },
+    { "getHardwareAddressImpl", "(Ljava/lang/String;I)[B", (void*) getHardwareAddressImpl },
+    { "getMTUImpl", "(Ljava/lang/String;I)I", (void*) getMTUImpl },
+    { "isLoopbackImpl", "(Ljava/lang/String;I)Z", (void*) isLoopbackImpl },
+    { "isPointToPointImpl", "(Ljava/lang/String;I)Z", (void*) isPointToPointImpl },
+    { "isUpImpl", "(Ljava/lang/String;I)Z", (void*) isUpImpl },
+    { "supportsMulticastImpl", "(Ljava/lang/String;I)Z", (void*) supportsMulticastImpl },
 };
 int register_java_net_NetworkInterface(JNIEnv* env) {
     return jniRegisterNativeMethods(env, "java/net/NetworkInterface",
diff --git a/libcore/luni/src/test/java/tests/api/java/net/NetworkInterfaceTest.java b/libcore/luni/src/test/java/tests/api/java/net/NetworkInterfaceTest.java
index 0272af1..26960c4 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/NetworkInterfaceTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/NetworkInterfaceTest.java
@@ -17,597 +17,545 @@
 
 package tests.api.java.net;
 
-import dalvik.annotation.TestTargetClass; 
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
 import java.net.InetAddress;
+import java.net.InterfaceAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
-import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 
-@TestTargetClass(NetworkInterface.class) 
 public class NetworkInterfaceTest extends junit.framework.TestCase {
 
-    // private member variables used for tests
-    boolean atLeastOneInterface = false;
+	// private member variables used for tests
+    Enumeration<NetworkInterface> theInterfaces = null;
 
-    boolean atLeastTwoInterfaces = false;
+	boolean atLeastOneInterface = false;
 
-    private NetworkInterface networkInterface1 = null;
+	boolean atLeastTwoInterfaces = false;
 
-    private NetworkInterface sameAsNetworkInterface1 = null;
+	private NetworkInterface networkInterface1 = null;
 
-    private NetworkInterface networkInterface2 = null;
+	private NetworkInterface sameAsNetworkInterface1 = null;
 
-    /**
-     * @tests java.net.NetworkInterface#getName()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getName",
-        args = {}
-    )
-    public void test_getName() {
-        if (atLeastOneInterface) {
-            assertNotNull("validate that non null name is returned",
-                    networkInterface1.getName());
-            assertFalse("validate that non-zero length name is generated",
-                    networkInterface1.getName().equals(""));
-        }
-        if (atLeastTwoInterfaces) {
-            assertFalse(
-                    "Validate strings are different for different interfaces",
-                    networkInterface1.getName().equals(
-                            networkInterface2.getName()));
-        }
-    }
+	private NetworkInterface networkInterface2 = null;
 
-    /**
-     * @tests java.net.NetworkInterface#getInetAddresses()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getInetAddresses",
-        args = {}
-    )
-    public void test_getInetAddresses() {
+	/**
+	 * @tests java.net.NetworkInterface#getName()
+	 */
+	public void test_getName() {
+		if (atLeastOneInterface) {
+			assertNotNull("validate that non null name is returned",
+					networkInterface1.getName());
+			assertFalse("validate that non-zero length name is generated",
+					networkInterface1.getName().equals(""));
+		}
+		if (atLeastTwoInterfaces) {
+			assertFalse(
+					"Validate strings are different for different interfaces",
+					networkInterface1.getName().equals(
+							networkInterface2.getName()));
+		}
+	}
 
-        // security manager that allows us to check that we only return the
-        // addresses that we should
-        class mySecurityManager extends SecurityManager {
+	/**
+	 * @tests java.net.NetworkInterface#getInetAddresses()
+	 */
+	public void test_getInetAddresses() throws Exception {
 
-            ArrayList disallowedNames = null;
+		// security manager that allows us to check that we only return the
+		// addresses that we should
+		class mySecurityManager extends SecurityManager {
 
-            public mySecurityManager(ArrayList addresses) {
-                disallowedNames = new ArrayList();
-                for (int i = 0; i < addresses.size(); i++) {
-                    disallowedNames.add(((InetAddress) addresses.get(i))
-                            .getHostName());
-                    disallowedNames.add(((InetAddress) addresses.get(i))
-                            .getHostAddress());
-                }
-            }
+			ArrayList disallowedNames = null;
 
-            public void checkConnect(String host, int port) {
+			public mySecurityManager(ArrayList addresses) {
+				disallowedNames = new ArrayList();
+				for (int i = 0; i < addresses.size(); i++) {
+					disallowedNames.add(((InetAddress) addresses.get(i))
+							.getHostName());
+					disallowedNames.add(((InetAddress) addresses.get(i))
+							.getHostAddress());
+				}
+			}
 
-                if (host == null) {
-                    throw new NullPointerException("host was null)");
-                }
+			public void checkConnect(String host, int port) {
 
-                for (int i = 0; i < disallowedNames.size(); i++) {
-                    if (((String) disallowedNames.get(i)).equals(host)) {
-                        throw new SecurityException("not allowed");
-                    }
-                }
-            }
+				if (host == null) {
+					throw new NullPointerException("host was null)");
+				}
 
-            public void checkPermission(Permission perm) {
-                // allow everything
-            }
-        }
+				for (int i = 0; i < disallowedNames.size(); i++) {
+					if (((String) disallowedNames.get(i)).equals(host)) {
+						throw new SecurityException("not allowed");
+					}
+				}
+			}
 
-        if (atLeastOneInterface) {
+		}
+
+		if (atLeastOneInterface) {
             Enumeration theAddresses = networkInterface1.getInetAddresses();
-            if (theAddresses != null) {
-                while (theAddresses.hasMoreElements()) {
-                    InetAddress theAddress = (InetAddress) theAddresses
-                            .nextElement();
-                    assertTrue("validate that address is not null",
-                            null != theAddress);
-                }
+            while (theAddresses.hasMoreElements()) {
+                InetAddress theAddress = (InetAddress) theAddresses
+                        .nextElement();
+                assertNotNull("validate that address is not null", theAddress);
             }
         }
 
-        if (atLeastTwoInterfaces) {
-            Enumeration theAddresses = networkInterface2.getInetAddresses();
-            if (theAddresses != null) {
-                while (theAddresses.hasMoreElements()) {
-                    InetAddress theAddress = (InetAddress) theAddresses
+		if (atLeastTwoInterfaces) {
+			Enumeration theAddresses = networkInterface2.getInetAddresses();
+			while (theAddresses.hasMoreElements()) {
+                InetAddress theAddress = (InetAddress) theAddresses
+                        .nextElement();
+                assertNotNull("validate that address is not null", theAddress);
+            }
+		}
+
+		// create the list of ok and not ok addresses to return
+		if (atLeastOneInterface) {
+			ArrayList okAddresses = new ArrayList();
+			Enumeration addresses = networkInterface1.getInetAddresses();
+			int index = 0;
+			ArrayList notOkAddresses = new ArrayList();
+			while (addresses.hasMoreElements()) {
+                InetAddress theAddress = (InetAddress) addresses.nextElement();
+                if (index != 0) {
+                    okAddresses.add(theAddress);
+                } else {
+                    notOkAddresses.add(theAddress);
+                }
+                index++;
+            }
+
+			// do the same for network interface 2 if it exists
+			if (atLeastTwoInterfaces) {
+				addresses = networkInterface2.getInetAddresses();
+				index = 0;
+				while (addresses.hasMoreElements()) {
+					InetAddress theAddress = (InetAddress) addresses
+							.nextElement();
+					if (index != 0) {
+						okAddresses.add(theAddress);
+					} else {
+						notOkAddresses.add(theAddress);
+					}
+					index++;
+				}
+			}
+
+			// set the security manager that will make the first address not
+			// visible
+			System.setSecurityManager(new mySecurityManager(notOkAddresses));
+
+			// validate not ok addresses are not returned
+			for (int i = 0; i < notOkAddresses.size(); i++) {
+				Enumeration reducedAddresses = networkInterface1
+						.getInetAddresses();
+				while (reducedAddresses.hasMoreElements()) {
+                    InetAddress nextAddress = (InetAddress) reducedAddresses
                             .nextElement();
-                    assertTrue("validate that address is not null",
-                            null != theAddress);
+                    assertTrue(
+                            "validate that address without permission is not returned",
+                            !nextAddress.equals(notOkAddresses.get(i)));
                 }
-            }
-        }
-
-        // create the list of ok and not ok addresses to return
-        if (atLeastOneInterface) {
-            ArrayList okAddresses = new ArrayList();
-            Enumeration addresses = networkInterface1.getInetAddresses();
-            int index = 0;
-            ArrayList notOkAddresses = new ArrayList();
-            if (addresses != null) {
-                while (addresses.hasMoreElements()) {
-                    InetAddress theAddress = (InetAddress) addresses
-                            .nextElement();
-                    if (index != 0) {
-                        okAddresses.add(theAddress);
-                    } else {
-                        notOkAddresses.add(theAddress);
-                    }
-                    index++;
-                }
-            }
-
-            // do the same for network interface 2 it it exists
-            if (atLeastTwoInterfaces) {
-                addresses = networkInterface2.getInetAddresses();
-                index = 0;
-                if (addresses != null) {
-                    while (addresses.hasMoreElements()) {
-                        InetAddress theAddress = (InetAddress) addresses
-                                .nextElement();
-                        if (index != 0) {
-                            okAddresses.add(theAddress);
-                        } else {
-                            notOkAddresses.add(theAddress);
-                        }
-                        index++;
-                    }
-                }
-            }
-
-            // set the security manager that will make the first address not
-            // visible
-            System.setSecurityManager(new mySecurityManager(notOkAddresses));
-
-            // validate not ok addresses are not returned
-            for (int i = 0; i < notOkAddresses.size(); i++) {
-                Enumeration reducedAddresses = networkInterface1
-                        .getInetAddresses();
-                if (reducedAddresses != null) {
-                    while (reducedAddresses.hasMoreElements()) {
-                        InetAddress nextAddress = (InetAddress) reducedAddresses
-                                .nextElement();
-                        assertTrue(
-                                "validate that address without permission is not returned",
-                                !nextAddress.equals(notOkAddresses.get(i)));
-                    }
-                }
-                if (atLeastTwoInterfaces) {
+				if (atLeastTwoInterfaces) {
                     reducedAddresses = networkInterface2.getInetAddresses();
-                    if (reducedAddresses != null) {
-                        while (reducedAddresses.hasMoreElements()) {
-                            InetAddress nextAddress = (InetAddress) reducedAddresses
-                                    .nextElement();
-                            assertTrue(
-                                    "validate that address without permission is not returned",
-                                    !nextAddress.equals(notOkAddresses.get(i)));
-                        }
+					while (reducedAddresses.hasMoreElements()) {
+						InetAddress nextAddress = (InetAddress) reducedAddresses
+								.nextElement();
+						assertTrue(
+								"validate that address without permission is not returned",
+								!nextAddress.equals(notOkAddresses.get(i)));
+					}
+				}
+			}
+
+			// validate that ok addresses are returned
+			for (int i = 0; i < okAddresses.size(); i++) {
+				boolean addressReturned = false;
+				Enumeration reducedAddresses = networkInterface1
+						.getInetAddresses();
+				while (reducedAddresses.hasMoreElements()) {
+                    InetAddress nextAddress = (InetAddress) reducedAddresses
+                            .nextElement();
+                    if (nextAddress.equals(okAddresses.get(i))) {
+                        addressReturned = true;
                     }
                 }
+				if (atLeastTwoInterfaces) {
+					reducedAddresses = networkInterface2.getInetAddresses();
+					while (reducedAddresses.hasMoreElements()) {
+						InetAddress nextAddress = (InetAddress) reducedAddresses
+								.nextElement();
+						if (nextAddress.equals(okAddresses.get(i))) {
+							addressReturned = true;
+						}
+					}
+				}
+				assertTrue("validate that address with permission is returned",
+						addressReturned);
+			}
+
+			// validate that we can get the interface by specifying the address.
+			// This is to be compatible
+			for (int i = 0; i < notOkAddresses.size(); i++) {
+                assertNotNull(
+                        "validate we cannot get the NetworkInterface with an address for which we have no privs",
+                        NetworkInterface
+                                .getByInetAddress((InetAddress) notOkAddresses
+                                        .get(i)));
             }
 
-            // validate that ok addresses are returned
-            for (int i = 0; i < okAddresses.size(); i++) {
-                boolean addressReturned = false;
-                Enumeration reducedAddresses = networkInterface1
-                        .getInetAddresses();
-                if (reducedAddresses != null) {
-                    while (reducedAddresses.hasMoreElements()) {
-                        InetAddress nextAddress = (InetAddress) reducedAddresses
-                                .nextElement();
-                        if (nextAddress.equals(okAddresses.get(i))) {
-                            addressReturned = true;
-                        }
-                    }
-                }
-                if (atLeastTwoInterfaces) {
-                    reducedAddresses = networkInterface2.getInetAddresses();
-                    if (reducedAddresses != null) {
-                        while (reducedAddresses.hasMoreElements()) {
-                            InetAddress nextAddress = (InetAddress) reducedAddresses
-                                    .nextElement();
-                            if (nextAddress.equals(okAddresses.get(i))) {
-                                addressReturned = true;
-                            }
-                        }
-                    }
-                }
-                assertTrue("validate that address with permission is returned",
-                        addressReturned);
+			// validate that we can get the network interface for the good
+			// addresses
+			for (int i = 0; i < okAddresses.size(); i++) {
+                assertNotNull(
+                        "validate we cannot get the NetworkInterface with an address fro which we have no privs",
+                        NetworkInterface
+                                .getByInetAddress((InetAddress) okAddresses
+                                        .get(i)));
             }
 
-            // validate that we can get the interface by specifying the address.
-            // This is to be compatible
-            for (int i = 0; i < notOkAddresses.size(); i++) {
-                try {
-                    assertNotNull(
-                            "validate we cannot get the NetworkInterface with an address for which we have no privs",
-                            NetworkInterface
-                                    .getByInetAddress((InetAddress) notOkAddresses
-                                            .get(i)));
-                } catch (Exception e) {
-                    fail("get NetworkInterface for address with no perm - exception");
-                }
-            }
+			System.setSecurityManager(null);
+		}
+	}
 
-            // validate that we can get the network interface for the good
-            // addresses
-            try {
-                for (int i = 0; i < okAddresses.size(); i++) {
-                    assertNotNull(
-                            "validate we cannot get the NetworkInterface with an address fro which we have no privs",
-                            NetworkInterface
-                                    .getByInetAddress((InetAddress) okAddresses
-                                            .get(i)));
-                }
-            } catch (Exception e) {
-                fail("get NetworkInterface for address with perm - exception");
-            }
+	/**
+	 * @tests java.net.NetworkInterface#getDisplayName()
+	 */
+	public void test_getDisplayName() {
+		if (atLeastOneInterface) {
+			assertNotNull("validate that non null display name is returned",
+					networkInterface1.getDisplayName());
+			assertFalse(
+					"validate that non-zero length display name is generated",
+					networkInterface1.getDisplayName().equals(""));
+		}
+		if (atLeastTwoInterfaces) {
+			assertFalse(
+					"Validate strings are different for different interfaces",
+					networkInterface1.getDisplayName().equals(
+							networkInterface2.getDisplayName()));
+		}
+	}
 
-            System.setSecurityManager(null);
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#getDisplayName()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getDisplayName",
-        args = {}
-    )
-    public void test_getDisplayName() {
-        if (atLeastOneInterface) {
-            assertNotNull("validate that non null display name is returned",
-                    networkInterface1.getDisplayName());
-            assertFalse(
-                    "validate that non-zero lengtj display name is generated",
-                    networkInterface1.getDisplayName().equals(""));
-        }
-        if (atLeastTwoInterfaces) {
-            assertFalse(
-                    "Validate strings are different for different interfaces",
-                    networkInterface1.getDisplayName().equals(
-                            networkInterface2.getDisplayName()));
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#getByName(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "SocketException checking missed.",
-        method = "getByName",
-        args = {java.lang.String.class}
-    )
-    public void test_getByNameLjava_lang_String() {
-        try {
-            assertNull("validate null handled ok",
+	/**
+	 * @tests java.net.NetworkInterface#getByName(java.lang.String)
+	 */
+	public void test_getByNameLjava_lang_String() throws Exception {
+		try {
+			assertNull("validate null handled ok",
                                    NetworkInterface.getByName(null));
-            fail("getByName did not throw NullPointerException for null argument");
-        } catch (NullPointerException e) {
-        } catch (Exception e) {
-            fail("getByName, null inetAddress - raised exception : "
-                    + e.getMessage());
-        }
+			fail("getByName did not throw NullPointerException for null argument");
+		} catch (NullPointerException e) {
+		} 
 
-        try {
-            assertNull("validate handled ok if we ask for name not associated with any interface",
-                                   NetworkInterface.getByName("8not a name4"));
-        } catch (Exception e) {
-            fail("getByName, unknown inetAddress - raised exception : "
-                    + e.getMessage());
-        }
+		assertNull("validate handled ok if we ask for name not associated with any interface",
+                                  NetworkInterface.getByName("8not a name4"));
 
-        // for each address in an interface validate that we get the right
-        // interface for that name
-        if (atLeastOneInterface) {
-            String theName = networkInterface1.getName();
-            if (theName != null) {
-                try {
-                    assertTrue(
-                            "validate that Interface can be obtained with its name",
-                            NetworkInterface.getByName(theName).equals(
-                                    networkInterface1));
-                } catch (Exception e) {
-                    fail("validate to get network interface using name - socket exception");
-                }
+		// for each address in an interface validate that we get the right
+		// interface for that name
+		if (atLeastOneInterface) {
+			String theName = networkInterface1.getName();
+			if (theName != null) {
+                assertEquals(
+                        "validate that Interface can be obtained with its name",
+                        networkInterface1, NetworkInterface.getByName(theName));
             }
-            try {
-                NetworkInterface.getByName(null);
-                fail("NullPointerException was not thrown.");
-            } catch(NullPointerException npe) {
-                //expected
-            } catch (SocketException e) {
-                fail("SocketException was thrown.");
+		}
+
+		// validate that we get the right interface with the second interface as
+		// well (ie we just don't always get the first interface
+		if (atLeastTwoInterfaces) {
+			String theName = networkInterface2.getName();
+			if (theName != null) {
+                assertEquals(
+                        "validate that Interface can be obtained with its name",
+                        networkInterface2, NetworkInterface.getByName(theName));
             }
-        }
+		}
+	}
 
-        // validate that we get the right interface with the second interface as
-        // well (ie we just don't always get the first interface
-        if (atLeastTwoInterfaces) {
-            String theName = networkInterface2.getName();
-            if (theName != null) {
-                try {
-                    assertTrue(
-                            "validate that Interface can be obtained with its name",
-                            NetworkInterface.getByName(theName).equals(
-                                    networkInterface2));
-                } catch (Exception e) {
-                    fail("validate to get network interface using name - socket exception");
-                }
-            }
-        }
-    }
+	/**
+	 * @tests java.net.NetworkInterface#getByInetAddress(java.net.InetAddress)
+	 */
+	public void test_getByInetAddressLjava_net_InetAddress() throws Exception {
 
-    /**
-     * @tests java.net.NetworkInterface#getByInetAddress(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "SocketException checking missed.",
-        method = "getByInetAddress",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_getByInetAddressLjava_net_InetAddress() {
+		byte addressBytes[] = new byte[4];
+		addressBytes[0] = 0;
+		addressBytes[1] = 0;
+		addressBytes[2] = 0;
+		addressBytes[3] = 0;
 
-        byte addressBytes[] = new byte[4];
-        addressBytes[0] = 0;
-        addressBytes[1] = 0;
-        addressBytes[2] = 0;
-        addressBytes[3] = 0;
-
-        try {
-            assertNull("validate null handled ok",
+		try {
+			assertNull("validate null handled ok",
                                    NetworkInterface.getByInetAddress(null));
-            fail("should not get here if getByInetAddress throws "
-                    + "NullPointerException if null passed in");
-        } catch (NullPointerException e) {
-        } catch (Exception e) {
-            fail("getByInetAddress, null inetAddress should have raised NPE"
-                    + " but instead threw a : " + e.getMessage());
-        }
+			fail("should not get here if getByInetAddress throws "
+					+ "NullPointerException if null passed in");
+		} catch (NullPointerException e) {
+		}
 
-        try {
-            assertNull("validate handled ok if we ask for address not associated with any interface",
-                                   NetworkInterface.getByInetAddress(InetAddress
-                            .getByAddress(addressBytes)));
-        } catch (Exception e) {
-            fail("getByInetAddress, unknown inetAddress threw exception : " + e);
-        }
+                assertNull("validate handled ok if we ask for address not associated with any interface",
+                           NetworkInterface.getByInetAddress(InetAddress
+                                                .getByAddress(addressBytes)));
 
-        // for each address in an interface validate that we get the right
-        // interface for that address
-        if (atLeastOneInterface) {
-            Enumeration addresses = networkInterface1.getInetAddresses();
-            if (addresses != null) {
-                while (addresses.hasMoreElements()) {
-                    InetAddress theAddress = (InetAddress) addresses
-                            .nextElement();
-                    try {
-                        assertTrue(
-                                "validate that Interface can be obtained with any one of its addresses",
-                                NetworkInterface.getByInetAddress(theAddress)
-                                        .equals(networkInterface1));
-                    } catch (Exception e) {
-                        fail("validate to get address using inetAddress " +
-                                "threw exception : " + e);
-                    }
-                }
+		// for each address in an interface validate that we get the right
+		// interface for that address
+		if (atLeastOneInterface) {
+			Enumeration addresses = networkInterface1.getInetAddresses();
+			while (addresses.hasMoreElements()) {
+                InetAddress theAddress = (InetAddress) addresses.nextElement();
+                assertEquals(
+                        "validate that Interface can be obtained with any one of its addresses",
+                        networkInterface1, NetworkInterface
+                                .getByInetAddress(theAddress));
             }
+		}
+
+		// validate that we get the right interface with the second interface as
+		// well (ie we just don't always get the first interface
+		if (atLeastTwoInterfaces) {
+			Enumeration addresses = networkInterface2.getInetAddresses();
+			while (addresses.hasMoreElements()) {
+                InetAddress theAddress = (InetAddress) addresses.nextElement();
+                assertEquals(
+                        "validate that Interface can be obtained with any one of its addresses",
+                        networkInterface2, NetworkInterface
+                                .getByInetAddress(theAddress));
+            }
+		}
+	}
+
+	/**
+	 * @tests java.net.NetworkInterface#getNetworkInterfaces()
+	 */
+	public void test_getNetworkInterfaces() throws Exception {
+
+		// really this is tested by all of the other calls but just make sure we
+		// can call it and get a list of interfaces if they exist
+		Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
+	}
+
+	/**
+	 * @tests java.net.NetworkInterface#equals(java.lang.Object)
+	 */
+	public void test_equalsLjava_lang_Object() {
+		// Test for method boolean
+		// java.net.SocketPermission.equals(java.lang.Object)
+		if (atLeastOneInterface) {
+            assertEquals("If objects are the same true is returned",
+                    sameAsNetworkInterface1, networkInterface1);
+            assertNotNull("Validate Null handled ok", networkInterface1);
+        }
+		if (atLeastTwoInterfaces) {
+			assertFalse("If objects are different false is returned",
+					networkInterface1.equals(networkInterface2));
+		}
+	}
+
+	/**
+	 * @tests java.net.NetworkInterface#hashCode()
+	 */
+	public void test_hashCode() {
+
+		if (atLeastOneInterface) {
+			assertTrue(
+					"validate that hash codes are the same for two calls on the same object",
+					networkInterface1.hashCode() == networkInterface1
+							.hashCode());
+			assertTrue(
+					"validate that hash codes are the same for two objects for which equals is true",
+					networkInterface1.hashCode() == sameAsNetworkInterface1
+							.hashCode());
+		}
+	}
+
+	/**
+	 * @tests java.net.NetworkInterface#toString()
+	 */
+	public void test_toString() {
+		if (atLeastOneInterface) {
+			assertNotNull("validate that non null string is generated",
+					networkInterface1.toString());
+			assertFalse("validate that non-zero length string is generated",
+					networkInterface1.toString().equals(""));
+		}
+		if (atLeastTwoInterfaces) {
+			assertFalse(
+					"Validate strings are different for different interfaces",
+					networkInterface1.toString().equals(
+							networkInterface2.toString()));
+		}
+	}
+
+    private class MockSecurityManager extends SecurityManager {
+        @Override
+        public void checkConnect(String host, int port) {
+            throw new SecurityException();
+        }
+    }
+
+    /**
+     * 
+     * @tests java.net.NetworkInterface#getInterfaceAddresses()
+     * 
+     * @since 1.6
+     */
+    public void test_getInterfaceAddresses() throws SocketException {
+        if (theInterfaces != null) {
+            SecurityManager oldSM = System.getSecurityManager();
+            System.setSecurityManager(new MockSecurityManager());
             
-            try {
-                NetworkInterface.getByInetAddress(null);
-                fail("NullPointerException should be thrown.");
-            } catch(NullPointerException npe) {
-                //expected
-            } catch (SocketException e) {
-                fail("SocketException was thrown.");
+            while (theInterfaces.hasMoreElements()) {
+                NetworkInterface netif = theInterfaces.nextElement();
+                assertEquals(netif.getName()
+                        + " getInterfaceAddresses should contain no element", 0,
+                        netif.getInterfaceAddresses().size());
             }
-        }
-
-        // validate that we get the right interface with the second interface as
-        // well (ie we just don't always get the first interface
-        if (atLeastTwoInterfaces) {
-            Enumeration addresses = networkInterface2.getInetAddresses();
-            if (addresses != null) {
-                while (addresses.hasMoreElements()) {
-                    InetAddress theAddress = (InetAddress) addresses
-                            .nextElement();
-                    try {
-                        assertTrue(
-                                "validate that Interface can be obtained with any one of its addresses",
-                                NetworkInterface.getByInetAddress(theAddress)
-                                        .equals(networkInterface2));
-                    } catch (Exception e) {
-                        fail("validate to get address using inetAddress "
-                                + "threw exception : " + e);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#getNetworkInterfaces()
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "SocketException checking missed.",
-        method = "getNetworkInterfaces",
-        args = {}
-    )
-    public void test_getNetworkInterfaces() {
-
-        // really this is tested by all of the other calls but just make sure we
-        // can call it and get a list of interfaces if they exist
-        try {
-            Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
-        } catch (Exception e) {
-            fail("get Network Interfaces - raised exception : "
-                    + e.getMessage());
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#equals(java.lang.Object)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "equals",
-        args = {java.lang.Object.class}
-    )
-    public void test_equalsLjava_lang_Object() {
-        // Test for method boolean
-        // java.net.SocketPermission.equals(java.lang.Object)
-        if (atLeastOneInterface) {
-            assertTrue("If objects are the same true is returned",
-                    networkInterface1.equals(sameAsNetworkInterface1));
-            assertFalse("Validate Null handled ok", networkInterface1
-                    .equals(null));
-        }
-        if (atLeastTwoInterfaces) {
-            assertFalse("If objects are different false is returned",
-                    networkInterface1.equals(networkInterface2));
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#hashCode()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "hashCode",
-        args = {}
-    )
-    public void test_hashCode() {
-
-        if (atLeastOneInterface) {
-            assertTrue(
-                    "validate that hash codes are the same for two calls on the same object",
-                    networkInterface1.hashCode() == networkInterface1
-                            .hashCode());
-            assertTrue(
-                    "validate that hash codes are the same for two objects for which equals is true",
-                    networkInterface1.hashCode() == sameAsNetworkInterface1
-                            .hashCode());
-        }
-    }
-
-    /**
-     * @tests java.net.NetworkInterface#toString()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "toString",
-        args = {}
-    )
-    public void test_toString() {
-        if (atLeastOneInterface) {
-            assertNotNull("validate that non null string is generated",
-                    networkInterface1.toString());
-            assertFalse("validate that non-zero length string is generated",
-                    networkInterface1.toString().equals(""));
-        }
-        if (atLeastTwoInterfaces) {
-            assertFalse(
-                    "Validate strings are different for different interfaces",
-                    networkInterface1.toString().equals(
-                            networkInterface2.toString()));
-        }
-    }
-
-    protected void setUp() {
-
-        Enumeration theInterfaces = null;
-        try {
+            System.setSecurityManager(oldSM);
+            
             theInterfaces = NetworkInterface.getNetworkInterfaces();
-        } catch (Exception e) {
-            fail("Exception occurred getting network interfaces : " + e);
+            while (theInterfaces.hasMoreElements()) {
+                NetworkInterface netif = theInterfaces.nextElement();
+                List<InterfaceAddress> interfaceAddrs = netif.getInterfaceAddresses();
+                assertTrue(interfaceAddrs instanceof ArrayList);
+                for (InterfaceAddress addr : interfaceAddrs) {
+                    assertNotNull(addr);                    
+                }
+                
+                List<InterfaceAddress> interfaceAddrs2 = netif.getInterfaceAddresses();
+                // RI fails on this since it cannot tolerate null broadcast address. 
+                assertEquals(interfaceAddrs, interfaceAddrs2);              
+            }
         }
-        
-        // Set up NetworkInterface instance members. Note that because the call
-        // to NetworkInterface.getNetworkInterfaces() returns *all* of the 
-        // interfaces on the test machine it is possible that one or more of 
-        // them will not currently be bound to an InetAddress. e.g. a laptop
-        // running connected by a wire to the local network may also have a 
-        // wireless interface that is not active and so has no InetAddress 
-        // bound to it. For these tests only work with NetworkInterface objects 
-        // that are bound to an InetAddress.   
-        if ((theInterfaces != null) && (theInterfaces.hasMoreElements())) {
-            while ((theInterfaces.hasMoreElements())
-                    && (atLeastOneInterface == false)) {
-                NetworkInterface theInterface = (NetworkInterface) theInterfaces
-                        .nextElement();
-                if (theInterface.getInetAddresses() != null) {
-                    // Ensure that the current NetworkInterface has at least
-                    // one InetAddress bound to it.  
-                    Enumeration addrs = theInterface.getInetAddresses();
-                    if ((addrs != null) && (addrs.hasMoreElements())) {
-                        atLeastOneInterface = true;
-                        networkInterface1 = theInterface;
-                    }// end if 
-                }
-            }
-
-            while ((theInterfaces.hasMoreElements())
-                    && (atLeastTwoInterfaces == false)) {
-                NetworkInterface theInterface = (NetworkInterface) theInterfaces
-                        .nextElement();
-                if (theInterface.getInetAddresses() != null) {
-                    // Ensure that the current NetworkInterface has at least
-                    // one InetAddress bound to it.  
-                    Enumeration addrs = theInterface.getInetAddresses();
-                    if ((addrs != null) && (addrs.hasMoreElements())) {
-                        atLeastTwoInterfaces = true;
-                        networkInterface2 = theInterface;
-                    }// end if 
-                }
-            }
-
-            // Only set sameAsNetworkInterface1 if we succeeded in finding 
-            // at least one good NetworkInterface
-            if (atLeastOneInterface) {
-                Enumeration addresses = networkInterface1.getInetAddresses();
-                if (addresses != null) {
-                    try {
-                        if (addresses.hasMoreElements()) {
-                            sameAsNetworkInterface1 = NetworkInterface
-                            .getByInetAddress((InetAddress) addresses
-                                    .nextElement());
-                        }
-                    } catch (SocketException e) {
-                        fail("SocketException occurred : " + e);
+    }   
+    
+    /**
+     * @tests java.net.NetworkInterface#isLoopback()
+     * 
+     * @since 1.6
+     */
+    public void test_isLoopback() throws SocketException {  
+        if (theInterfaces != null) {
+            while (theInterfaces.hasMoreElements()) {
+                NetworkInterface netif = theInterfaces.nextElement();
+                boolean loopback = false;
+                Enumeration<InetAddress> addrs = netif.getInetAddresses();
+                while(addrs != null && addrs.hasMoreElements()){
+                    if(addrs.nextElement().isLoopbackAddress()){
+                        loopback = true;
+                        break;
                     }
                 }
-            }// end if atLeastOneInterface
+                assertEquals(loopback, netif.isLoopback());
+            }
         }
     }
-
-    protected void tearDown() {
-        System.setSecurityManager(null);
+    
+    /**
+     * @tests java.net.NetworkInterface#getHardwareAddress()
+     * 
+     * @since 1.6
+     */
+    public void test_getHardwareAddress() throws SocketException {
+        if (theInterfaces != null) {
+            while (theInterfaces.hasMoreElements()) {
+                NetworkInterface netif = theInterfaces.nextElement();
+                byte[] hwAddr = netif.getHardwareAddress();
+                if (netif.isLoopback()) {
+                    assertTrue(hwAddr == null || hwAddr.length == 0);
+                } else {
+                    assertTrue(hwAddr.length >= 0);
+                }
+            }
+        }
     }
+    
+    /**
+     * 
+     * @tests java.net.NetworkInterface#getHardwareAddress()
+     * 
+     * @since 1.6
+     */
+    public void test_getMTU() throws SocketException {      
+        if (theInterfaces != null) {
+            while (theInterfaces.hasMoreElements()) {
+                NetworkInterface netif = theInterfaces.nextElement();
+                assertTrue(netif.getName() + "has non-positive MTU", netif.getMTU() >= 0);
+            }           
+        }
+    }
+    
+	protected void setUp() throws SocketException {
+
+		Enumeration theInterfaces = null;
+		try {
+			theInterfaces = NetworkInterface.getNetworkInterfaces();
+		} catch (Exception e) {
+			fail("Exception occurred getting network interfaces : " + e);
+		}
+		
+		// Set up NetworkInterface instance members. Note that because the call
+		// to NetworkInterface.getNetworkInterfaces() returns *all* of the 
+		// interfaces on the test machine it is possible that one or more of 
+		// them will not currently be bound to an InetAddress. e.g. a laptop
+		// running connected by a wire to the local network may also have a 
+		// wireless interface that is not active and so has no InetAddress 
+		// bound to it. For these tests only work with NetworkInterface objects 
+		// that are bound to an InetAddress.   
+		if ((theInterfaces != null) && (theInterfaces.hasMoreElements())) {
+			while ((theInterfaces.hasMoreElements())
+					&& (atLeastOneInterface == false)) {
+				NetworkInterface theInterface = (NetworkInterface) theInterfaces
+						.nextElement();
+				if (theInterface.getInetAddresses().hasMoreElements()) {
+					// Ensure that the current NetworkInterface has at least
+					// one InetAddress bound to it.  
+					Enumeration addrs = theInterface.getInetAddresses();
+					if ((addrs != null) && (addrs.hasMoreElements())) {
+						atLeastOneInterface = true;
+						networkInterface1 = theInterface;
+					}// end if 
+				}
+			}
+
+			while ((theInterfaces.hasMoreElements())
+					&& (atLeastTwoInterfaces == false)) {
+				NetworkInterface theInterface = (NetworkInterface) theInterfaces
+						.nextElement();
+				if (theInterface.getInetAddresses().hasMoreElements()) {
+					// Ensure that the current NetworkInterface has at least
+					// one InetAddress bound to it.  
+					Enumeration addrs = theInterface.getInetAddresses();
+					if ((addrs != null) && (addrs.hasMoreElements())) {
+						atLeastTwoInterfaces = true;
+						networkInterface2 = theInterface;
+					}// end if 
+				}
+			}
+
+			// Only set sameAsNetworkInterface1 if we succeeded in finding 
+			// at least one good NetworkInterface
+			if (atLeastOneInterface) {
+				Enumeration addresses = networkInterface1.getInetAddresses();
+				if (addresses.hasMoreElements()) {
+					try {
+						if (addresses.hasMoreElements()) {
+							sameAsNetworkInterface1 = NetworkInterface
+							.getByInetAddress((InetAddress) addresses
+									.nextElement());
+						}
+					} catch (SocketException e) {
+						fail("SocketException occurred : " + e);
+					}
+				}
+			}// end if atLeastOneInterface
+		}
+        theInterfaces = NetworkInterface.getNetworkInterfaces();
+	}
+
+	protected void tearDown() {
+		System.setSecurityManager(null);
+	}
 }