001/* NetworkInterface.java --
002   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.net;
040
041import gnu.classpath.SystemProperties;
042
043import gnu.java.lang.CPStringBuilder;
044
045import java.util.Enumeration;
046import java.util.Iterator;
047import java.util.Vector;
048
049/**
050 * This class models a network interface on the host computer.  A network
051 * interface contains a name (typically associated with a specific
052 * hardware adapter) and a list of addresses that are bound to it.
053 * For example, an ethernet interface may be named "eth0" and have the
054 * address 192.168.1.101 assigned to it.
055 *
056 * @author Michael Koch (konqueror@gmx.de)
057 * @since 1.4
058 */
059public final class NetworkInterface
060{
061  private final VMNetworkInterface netif;
062
063  private NetworkInterface(VMNetworkInterface netif)
064    {
065    this.netif = netif;
066    }
067
068  /** Creates an NetworkInterface instance which
069   * represents any interface in the system. Its only
070   * address is <code>0.0.0.0/0.0.0.0</code>. This
071   * method is needed by {@link MulticastSocket#getNetworkInterface}
072   */
073  static NetworkInterface createAnyInterface()
074  {
075    return new NetworkInterface(new VMNetworkInterface());
076  }
077
078  /**
079   * Returns the name of the network interface
080   *
081   * @return The name of the interface.
082   */
083  public String getName()
084  {
085    return netif.name;
086  }
087
088  /**
089   * Returns all available addresses of the network interface
090   *
091   * If a @see SecurityManager is available all addresses are checked
092   * with @see SecurityManager::checkConnect() if they are available.
093   * Only <code>InetAddresses</code> are returned where the security manager
094   * doesn't throw an exception.
095   *
096   * @return An enumeration of all addresses.
097   */
098  public Enumeration<InetAddress> getInetAddresses()
099  {
100    SecurityManager s = System.getSecurityManager();
101    Vector<InetAddress> inetAddresses
102      = new Vector<InetAddress>(netif.addresses);
103
104    if (s == null)
105      return inetAddresses.elements();
106
107    Vector<InetAddress> tmpInetAddresses = new Vector<InetAddress>(1, 1);
108
109    for (Enumeration<InetAddress> addresses = inetAddresses.elements();
110         addresses.hasMoreElements();)
111      {
112        InetAddress addr = addresses.nextElement();
113        try
114          {
115            s.checkConnect(addr.getHostAddress(), -1);
116            tmpInetAddresses.add(addr);
117          }
118        catch (SecurityException e)
119          {
120            // Ignore.
121          }
122      }
123
124    return tmpInetAddresses.elements();
125  }
126
127  /**
128   * Returns the display name of the interface
129   *
130   * @return The display name of the interface
131   */
132  public String getDisplayName()
133  {
134    return netif.name;
135  }
136
137  /**
138   * Returns an network interface by name
139   *
140   * @param name The name of the interface to return
141   *
142   * @return a <code>NetworkInterface</code> object representing the interface,
143   * or null if there is no interface with that name.
144   *
145   * @exception SocketException If an error occurs
146   * @exception NullPointerException If the specified name is null
147   */
148  public static NetworkInterface getByName(String name)
149    throws SocketException
150  {
151    if (name == null)
152      throw new NullPointerException();
153    VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
154    for (int i = 0; i < netifs.length; i++)
155      {
156        if (netifs[i].name.equals(name))
157          return new NetworkInterface(netifs[i]);
158      }
159    return null;
160  }
161
162  /**
163   * Return a network interface by its address
164   *
165   * @param addr The address of the interface to return
166   *
167   * @return the interface, or <code>null</code> if none found
168   *
169   * @exception SocketException If an error occurs
170   * @exception NullPointerException If the specified addess is null
171   */
172  public static NetworkInterface getByInetAddress(InetAddress addr)
173    throws SocketException
174  {
175    if (addr == null)
176      throw new NullPointerException();
177    VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
178    for (int i = 0; i < netifs.length; i++)
179      {
180        if (netifs[i].addresses.contains(addr))
181          return new NetworkInterface(netifs[i]);
182      }
183    return null;
184  }
185
186  /**
187   * Return an <code>Enumeration</code> of all available network interfaces
188   *
189   * @return all interfaces
190   *
191   * @exception SocketException If an error occurs
192   */
193  public static Enumeration<NetworkInterface> getNetworkInterfaces()
194    throws SocketException
195  {
196    VMNetworkInterface[] netifs = VMNetworkInterface.getVMInterfaces();
197    Vector<NetworkInterface> networkInterfaces =
198      new Vector<NetworkInterface>(netifs.length);
199    for (int i = 0; i < netifs.length; i++)
200      {
201        if (!netifs[i].addresses.isEmpty())
202          networkInterfaces.add(new NetworkInterface(netifs[i]));
203      }
204    return networkInterfaces.elements();
205  }
206
207  /**
208   * Checks if the current instance is equal to obj
209   *
210   * @param obj The object to compare with
211   *
212   * @return <code>true</code> if equal, <code>false</code> otherwise
213   */
214  public boolean equals(Object obj)
215  {
216    if (! (obj instanceof NetworkInterface))
217      return false;
218
219    NetworkInterface tmp = (NetworkInterface) obj;
220
221    if (netif.name == null)
222      return tmp.netif.name == null;
223
224    return (netif.name.equals(tmp.netif.name)
225            && (netif.addresses.equals(tmp.netif.addresses)));
226  }
227
228  /**
229   * Returns the hashcode of the current instance
230   *
231   * @return the hashcode
232   */
233  public int hashCode()
234  {
235    // FIXME: hash correctly
236    int hc = netif.addresses.hashCode();
237
238    if (netif.name != null)
239      hc += netif.name.hashCode();
240
241    return hc;
242  }
243
244  /**
245   * Returns a string representation of the interface
246   *
247   * @return the string
248   */
249  public String toString()
250  {
251    // FIXME: check if this is correct
252    CPStringBuilder result;
253    String separator = SystemProperties.getProperty("line.separator");
254
255    result = new CPStringBuilder();
256
257    result.append("name: ");
258    result.append(getDisplayName());
259    result.append(" (").append(getName()).append(") addresses:");
260    result.append(separator);
261
262    for (Iterator it = netif.addresses.iterator(); it.hasNext(); )
263      {
264        InetAddress address = (InetAddress) it.next();
265        result.append(address.toString()).append(";").append(separator);
266      }
267
268    return result.toString();
269  }
270
271  /**
272   * Determines whether this interface is ready to transfer data.
273   *
274   * @return whether the interface is up
275  */
276  public boolean isUp()
277    throws SocketException
278  {
279    return VMNetworkInterface.isUp(netif.name);
280  }
281
282  /**
283   * Determines whether this interface does point to point
284   * transmission.
285   *
286   * @return whether the interface does point to point transmission
287  */
288  public boolean isPointToPoint()
289    throws SocketException
290  {
291    return VMNetworkInterface.isPointToPoint(netif.name);
292  }
293
294  /**
295   * Determines whether this interface is the loopback interface.
296   *
297   * @return whether the interface is the loopback interface
298  */
299  public boolean isLoopback()
300    throws SocketException
301  {
302    return VMNetworkInterface.isLoopback(netif.name);
303  }
304
305  /**
306   * Determines whether this interface supports multicast transmission.
307   *
308   * @return whether the interface supports multicast transmission.
309  */
310  public boolean supportsMulticast()
311    throws SocketException
312  {
313    return VMNetworkInterface.supportsMulticast(netif.name);
314  }
315
316}