Package ch.rakudave.jnetmap.net

Source Code of ch.rakudave.jnetmap.net.NetworkScan

package ch.rakudave.jnetmap.net;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import ch.rakudave.jnetmap.controller.Actions;
import ch.rakudave.jnetmap.controller.Scheduler;
import ch.rakudave.jnetmap.model.Connection;
import ch.rakudave.jnetmap.model.Map;
import ch.rakudave.jnetmap.model.IF.NetworkIF;
import ch.rakudave.jnetmap.model.IF.PhysicalIF;
import ch.rakudave.jnetmap.model.IF.TransparentIF;
import ch.rakudave.jnetmap.model.device.Device;
import ch.rakudave.jnetmap.model.device.Host;
import ch.rakudave.jnetmap.model.device.Device.Type;
import ch.rakudave.jnetmap.net.status.IsReachable;
import ch.rakudave.jnetmap.net.status.NativePing;
import ch.rakudave.jnetmap.net.status.OpenSocket;
import ch.rakudave.jnetmap.net.status.PingMethod;
import ch.rakudave.jnetmap.net.status.Status;
import ch.rakudave.jnetmap.util.Tuple;
import ch.rakudave.jnetmap.util.logging.Logger;

/**
* Scans a Subnet for (alive) Hosts
*
* @author rakudave
*/
public class NetworkScan implements ChangeListener {
  private Subnet subnet;
  private java.util.Map<InetAddress, PingMethod> found;
  private ChangeListener listener;
  private ExecutorService ex;

  public NetworkScan(Subnet subnet, ChangeListener updateListener) {
    this.subnet = subnet;
    listener = updateListener;
    found = new HashMap<InetAddress, PingMethod>();
  }

  @SuppressWarnings("unchecked")
  public void start(boolean doPortScan) {
    if (ex != null)
      return;
    ex = Executors.newFixedThreadPool(50);
    Queue<Future<Tuple<InetAddress, PingMethod>>> tasks = new LinkedList<Future<Tuple<InetAddress, PingMethod>>>();
    String[] addresses = subnet.getInfo().getAllAddresses();
    for (int i = 0; i < addresses.length; i++) {
      try {
        InetAddress address = InetAddress.getByName(addresses[i]);
        tasks.add((Future<Tuple<InetAddress, PingMethod>>) ex
            .submit(new HostCheck(address, this, doPortScan)));
      } catch (UnknownHostException uhe) {
        Logger.error("Invalid address: " + addresses[i], uhe);
      } catch (RejectedExecutionException ree) {
        Logger.debug("Scan interrupted: " + addresses[i], ree);
      }
    }
    ex.shutdown();
  }

  public boolean isDone() {
    return ex.isTerminated();
  }

  public void cancel() {
    ex.shutdownNow();
  }

  public java.util.Map<InetAddress, PingMethod> getFoundHosts() {
    return found;
  }

  public void addToMap(final java.util.Map<InetAddress, PingMethod> hosts, final Map map) {
    if (hosts == null || hosts.isEmpty() || map == null) return;
    // TODO devices are added at [0,0], find way to layout properly!
    Connection gToS = new Connection();
    Device gateway = null;
    Device aSwitch = null;
    NetworkIF gatewayIF = null;
    try { // try to find the gateway
      gatewayIF = tryFindIP(map, InetAddress.getByName(subnet.getInfo().getLowAddress()));
    } catch (UnknownHostException ex) {
      Logger.debug("Unable to find gateway-interface", ex);
    }
    if (gatewayIF == null) { // create a gateway if none was found
      gateway = new Host(Type.Router);
      gatewayIF = new PhysicalIF(gateway, gToS, subnet.getInfo().getLowAddress());
      map.addVertex(gateway);
      gateway.addInterface(gatewayIF);
    } else {
      gateway = gatewayIF.getDevice();
    }
    try { // try to find the switch attached to the gateway
      aSwitch = map.getOpposite(gateway, gatewayIF.getConnection());
      // if the opposite is not a switch, reset
      if (aSwitch != null && !aSwitch.getType().toString().toLowerCase().contains("switch")) aSwitch = null;
    } catch (Exception e) {
      Logger.debug("Unable to find opposite", e);
    }
    if (aSwitch == null) { // create a switch if necessary
      aSwitch = new Host(Type.Switch);
      map.addVertex(aSwitch);
      aSwitch.addInterface(new TransparentIF(aSwitch, gToS, gatewayIF));
      map.addEdge(gToS, gateway, aSwitch);
    }
    final Device gw = gateway, sw = aSwitch;
    final NetworkIF gif = gatewayIF;
    for (final InetAddress address : hosts.keySet()) {
      Scheduler.execute(new Runnable() {
        @Override
        public void run() {
          try {
            if (!address.equals(gif.getAddress())) {
              if (tryFindIP(map, address) != null) return;
              Logger.debug("Adding Interface "+address);
              Connection c = new Connection();
              Device d = new Host();
                d.setName(address.getHostName());
                PhysicalIF pif = new PhysicalIF(d, c, address.getHostAddress());
                  pif.setPingMethod(hosts.get(address));
                  pif.setSubnet(subnet.getInfo().getNetmask());
                  pif.setGateway(subnet.getInfo().getLowAddress());
                d.addInterface(pif);
                SNMP.inferProperties(d);
              sw.addInterface(new TransparentIF(sw, c, pif));
              map.addVertex(d);
              map.addEdge(c, d, sw);
            } else {
              if (gif instanceof PhysicalIF) ((PhysicalIF) gif).setPingMethod(hosts.get(address));
              gw.setName(address.getHostName());
            }
          } catch (Exception e) {
            Logger.error("Unable to add address " + address + " to map", e);
          }
            }
          });
    }
    Actions.refresh().actionPerformed(null);
  }

  public static NetworkIF tryFindIP(Map m, InetAddress address) {
    for (Device d : m.getVertices()) {
      for (NetworkIF nif : d.getInterfaces()) {
        if (address.equals(nif.getAddress()))
          return nif;
      }
    }
    return null;
  }

  public class HostCheck implements Runnable {
    private InetAddress address;
    private ChangeListener l;
    private boolean doPortScan;

    public HostCheck(InetAddress address, ChangeListener l,
        boolean doPortScan) {
      this.address = address;
      this.l = l;
      this.doPortScan = doPortScan;
    }

    @Override
    public void run() {
      Tuple<InetAddress, PingMethod> result;
      // ignore A/B/C-Broadcast addresses
      if (new Subnet(address.getHostAddress()+"/24").getInfo().getBroadcastAddress().equals(address.getHostAddress()) ||
          new Subnet(address.getHostAddress()+"/16").getInfo().getBroadcastAddress().equals(address.getHostAddress()) ||
          new Subnet(address.getHostAddress()+"/8").getInfo().getBroadcastAddress().equals(address.getHostAddress())) {
        return;
      }
      Logger.trace("Checking if "+address.getHostAddress()+" is up");
      if (IsReachable.getInstance().getStatus(address) == Status.UP) {
        result = new Tuple<InetAddress, PingMethod>(address,
            IsReachable.getInstance());
      } else if (NativePing.getInstance().getStatus(address) == Status.UP) {
        result = new Tuple<InetAddress, PingMethod>(address, NativePing
            .getInstance());
      } else if (doPortScan) {
        int port = PortScan.sweepCommon(address);
        result = (port != -1) ? new Tuple<InetAddress, PingMethod>(
            address, new OpenSocket(port)) : null;
      } else {
        result = null;
      }
      l.stateChanged(new ChangeEvent(result));
    }
  }

  @Override
  @SuppressWarnings("unchecked")
  public void stateChanged(ChangeEvent e) {
    Tuple<InetAddress, PingMethod> tuple = (Tuple<InetAddress, PingMethod>) e.getSource();
    found.put(tuple.getFirst(), tuple.getSecond());
    if (listener != null)
      listener.stateChanged(new ChangeEvent(tuple));
  }

  public static String getLocalAddress() {
    Enumeration<NetworkInterface> nets;
    try {
      nets = NetworkInterface.getNetworkInterfaces();
    } catch (SocketException e) {
      Logger.debug("Unable to get local interfaces", e);
      return null;
    }
        for (NetworkInterface netint : Collections.list(nets)) {
            for (InetAddress inetAddress : Collections.list(netint.getInetAddresses())) {
                if (!inetAddress.isLoopbackAddress()
                    && inetAddress.getHostAddress().matches("(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")) {
                  return inetAddress.getHostAddress();
                }
            }
        }
        return null;
  }
}
TOP

Related Classes of ch.rakudave.jnetmap.net.NetworkScan

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.