001    // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002    // The Molly framework is freely distributable under the terms of an
003    // MIT-style license. For details, see the molly pages web site at:
004    // http://www.mollypages.org/. Use, modify, have fun !
005    
006    package fc.net;
007    
008    import java.io.*;
009    import java.util.*;
010    import java.util.regex.*;
011    import java.nio.*;
012    import java.nio.channels.*;
013    import java.net.*;
014    
015    import fc.io.*;
016    import fc.util.*;
017    
018    /**
019    Network Interface Card related utility methods. Many of these
020    methods are specific to ethernet type nic's.
021    
022    @author hursh jain
023    **/
024    public class NIC 
025    {
026    //for internal debugging
027    private static boolean dbg = false;
028    static String linesep = IOUtil.LINE_SEP;
029    
030    /**
031    Returns a Map containing an IP address as the key and
032    a {@link NIC.NICInfo} object as the value. Returns <tt>null</tt> if 
033    the platform type is not supported.
034    <p>
035    <b>Note 1:</b> Requires a NT based system (NT, 2000, XP or later) if
036    running on windows. (this call will not work for lesser versions of
037    windows).<br>
038    <b>Note 2:</b> An english locale is needed for this method to work
039    properly (because we parse for certain english words to extract the 
040    results).
041    **/
042    public static Map getMAC() 
043      {
044      Platform p = Platform.getPlatform();
045      try {
046        if (p == p.WINDOWS)   return getWindowsMA();  
047        else if (p == p.LINUX)  return getLinuxMA(); 
048        else if (p == p.OSX)   return getOSXMA(); 
049      
050      //we presume that linux stype ifconfig works identically
051      //on other plaforms. This of course is dicey at best.
052      //But I don't have no steeenkin bsd etc to test on.
053      
054        else if (p == p.FREEBSD) return getLinuxMA();
055        else if (p == p.OPENBSD) return getLinuxMA();
056        }
057      catch (IOException e) {
058        e.printStackTrace();
059        }
060      return null;
061      } 
062    
063    private static Map getWindowsMA() throws IOException
064      {
065      Map macs = new HashMap();
066      Process p = Runtime.getRuntime().exec("ipconfig /all");
067        InputStream in = p.getInputStream();
068        try {
069        String result = IOUtil.inputStreamToString(in, true);     
070        if (dbg) System.out.println("getWindowsMA(): " + linesep + "--------------- result ------------ " + linesep + result + linesep + "--------------------------------");
071        
072        //for some reason ^$ does not work properly (for blank lines)
073        //even when multiline mode is chosen
074        
075        Pattern pat = Pattern.compile(
076          "(?i)(?m)(?s)Ethernet\\s+adapter\\s+(.*?):.*?" +
077          "Physical\\s+Address.*?:\\s*([a-zA-Z0-9\\-]*).*?" +
078          "NetBIOS.*?:\\s*\\w*"
079          );
080    
081        Pattern ip_pat = Pattern.compile(
082                  "(?i)(?m)IP\\s+Address.*?:\\s+(.+?)$"
083                 );
084        Matcher matcher = pat.matcher(result);
085        while (matcher.find()) {
086          if (dbg) System.out.println("getWindowsMA(): found: " + matcher.group(0));
087          String name = matcher.group(1);
088          String mac = matcher.group(2);
089          Matcher ipmatcher = ip_pat.matcher(matcher.group(0));
090          while (ipmatcher.find()) {
091            String ip = ipmatcher.group(1);
092            if (dbg) System.out.println("ip=" + ip + "; mac=" + mac + "; name=" + name);
093            NICInfo nicinfo = new NICInfo(name, mac);
094            macs.put(ip, nicinfo);  
095            }
096          }
097        } 
098      finally {
099        if ( in != null ) in.close();
100        }
101      return macs;
102        }
103    
104    private static Map getLinuxMA() throws IOException
105      {
106      Map macs = new HashMap();
107      Process p = Runtime.getRuntime().exec("ifconfig");
108        InputStream in = p.getInputStream();
109        try {
110        /*
111        //this should give us the entire input size but does NOT
112        //- instead returns 0 !
113        int resultlen = in.available();  
114        if (dbg) System.out.println("resultlen=" + resultlen);  
115        ReadableByteChannel bytechan = Channels.newChannel(in);
116        ByteBuffer bytebuf = ByteBuffer.allocate(resultlen);
117        bytechan.read(bytebuf); 
118        bytebuf.rewind();
119        if (dbg) System.out.println("ByteBuffer=" + bytebuf);               
120        CharBuffer cbuf = bytebuf.asCharBuffer(); 
121        if (dbg) System.out.println("CharBuffer=" + cbuf);                
122        */
123        
124        String result = IOUtil.inputStreamToString(in, true);
125    
126        String pat = 
127          "(?s)(?m)(?i)(eth.*?)\\s+.+?HWaddr\\s([a-zA-Z0-9:\\-]*).*?addr:(.+?)\\s";       
128    
129        Pattern linux_ifconfig_1_42 = Pattern.compile(pat);
130        Matcher matcher = linux_ifconfig_1_42.matcher(result);
131        while (matcher.find()) {
132          String name = matcher.group(1);
133          String mac = matcher.group(2);
134          String ip = matcher.group(3);
135          if (dbg) System.out.println("getLinuxMA(): found: " + matcher.group(0));
136          if (dbg) System.out.println("ip=" + ip + "; mac=" + mac + "; name=" + name);
137          NICInfo nicinfo = new NICInfo(name, mac);
138          macs.put(ip, nicinfo);  
139          }
140        } 
141      finally {
142        if ( in != null ) in.close();
143        }
144      return macs;
145        }
146    
147    
148    private static Map getOSXMA() throws IOException
149      {
150      Map macs = new HashMap();
151      Process p = Runtime.getRuntime().exec("ifconfig");
152        InputStream in = p.getInputStream();
153        try {
154        String result = IOUtil.inputStreamToString(in, true);
155        String pat = "(?s)(?m)(?i)(en\\d+):.+?.*?status.*?$";       
156    
157        Pattern osx = Pattern.compile(pat);
158        Matcher matcher = osx.matcher(result);
159    
160        Pattern ip_pat = Pattern.compile( "(?i)inet\\s+([0-9.]+)\\s*" );
161        Pattern eth_pat = Pattern.compile( "(?i)ether\\s+([a-zA-Z0-9:\\-]*)\\s*" );
162    
163        while (matcher.find()) 
164          {
165          String name = matcher.group(1);
166    
167          if (dbg)  {
168            System.out.println("\n\n=========found: group[0]===========");
169            System.out.println(matcher.group(0));
170            System.out.println("\n==================");
171            }
172            
173          String mac = null;
174          String ip = null;
175    
176          Matcher ip_matcher = ip_pat.matcher(matcher.group(0));
177          Matcher eth_matcher = eth_pat.matcher(matcher.group(0));
178          
179          if (ip_matcher.find()) {
180            ip = ip_matcher.group(1);
181            }
182    
183          if (eth_matcher.find()) {
184            mac = eth_matcher.group(1);
185            }
186    
187          if (dbg) System.out.println("ip=" + ip + "; mac=" + mac + "; name=" + name);
188          
189          if (ip != null && mac != null) {
190            NICInfo nicinfo = new NICInfo(name, mac);
191            macs.put(ip, nicinfo);
192            }
193          }
194        } 
195      finally {
196        if ( in != null ) in.close();
197        }
198      return macs;
199        }
200    
201    public static void main(String[] args) throws Exception
202      {
203      Args myargs = new Args(args);
204      if (myargs.flagExists("debug")) {
205        dbg = true;
206        }
207      System.out.println("[1] Mac Addresses: " + getMAC()); 
208      
209      System.out.println("\n[2] Using java networkinterface methods");  
210      Enumeration<NetworkInterface> infs = NetworkInterface.getNetworkInterfaces();
211      List list = Collections.list(infs);
212      for (int n = 0; n < list.size(); n++) {
213        NetworkInterface inf = (NetworkInterface) list.get(n);
214        System.out.println(
215          "name="+inf.getName()
216          +";ip="+Collections.list(inf.getInetAddresses())
217          +";hw="+inf.getHardwareAddress()
218          +";up="+inf.isUp());
219        }
220      }
221    
222    /** 
223    Contains information about IP addresses and the associated
224    interface names and MAC address. More than one IP address
225    can be associated with the same interface.
226    **/
227    public static class NICInfo 
228    {
229    String interfaceName;
230    String mac;
231     
232    NICInfo(String interfaceName, String mac) {
233      this.interfaceName = interfaceName;
234      this.mac = mac; 
235      }
236    /** 
237    returns the name of the interface. This name may not
238    be the same as the name returned by {@link NetworkInterface#getName} 
239    (especially on windows).
240    **/
241    public String getInterfaceName() { return interfaceName; }
242    
243    /** returns the MAC address of the interface **/
244    public String getMACAddress() { return mac; }
245    
246    public String toString() {
247      return "[NICInfo: name=" + interfaceName + "; MAC=" + mac + "]"; 
248      }
249    } //~class NICInfo
250    
251    
252    }  //~class NIC