Merge "Implement the Java 6 NetworkInterface/InterfaceAddress functionality." into dalvik-dev
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);
+	}
 }