Package org.pcap4j.core

Source Code of org.pcap4j.core.PcapNetworkInterface

/*_##########################################################################
  _##
  _##  Copyright (C) 2011  Kaito Yamada
  _##
  _##########################################################################
*/

package org.pcap4j.core;

import java.util.ArrayList;
import java.util.List;
import org.pcap4j.core.NativeMappings.PcapErrbuf;
import org.pcap4j.core.NativeMappings.PcapLibrary;
import org.pcap4j.core.NativeMappings.pcap_addr;
import org.pcap4j.core.NativeMappings.pcap_if;
import org.pcap4j.core.NativeMappings.sockaddr_dl;
import org.pcap4j.core.NativeMappings.sockaddr_ll;
import org.pcap4j.core.NativeMappings.timeval;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.LinkLayerAddress;
import org.pcap4j.util.MacAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;

/**
* @author Kaito Yamada
* @since pcap4j 0.9.1
*/
public final class PcapNetworkInterface {

  private static final Logger logger
    = LoggerFactory.getLogger(PcapNetworkInterface.class);

  private static final int PCAP_IF_LOOPBACK = 0x00000001;

  private final String name;
  private final String description;
  private final List<PcapAddress> addresses = new ArrayList<PcapAddress>();
  private final List<LinkLayerAddress> linkLayerAddresses = new ArrayList<LinkLayerAddress>();
  private final boolean loopBack;
  private final boolean local;

  private PcapNetworkInterface(pcap_if pif, boolean local) {
    this.name = pif.name;
    this.description = pif.description;

    for (
      pcap_addr pcapAddr = pif.addresses;
      pcapAddr != null;
      pcapAddr = pcapAddr.next
    ) {
      short sa_family = pcapAddr.addr.getSaFamily();
      if (sa_family == Inets.AF_INET) {
        addresses.add(PcapIpV4Address.newInstance(pcapAddr));
      }
      else if (sa_family == Inets.AF_INET6) {
        addresses.add(PcapIpV6Address.newInstance(pcapAddr));
      }
      else {
        if (Platform.isLinux() && sa_family == Inets.AF_PACKET) {
          sockaddr_ll sll = new sockaddr_ll(pcapAddr.addr.getPointer());
          byte[] addr = sll.sll_addr;
          int addrLength = sll.sll_halen & 0xFF;
          if (addrLength == 6) {
            linkLayerAddresses.add(ByteArrays.getMacAddress(addr, 0));
          }
          else if (addr.length == 0) {
            continue;
          }
          else {
            linkLayerAddresses.add(
              LinkLayerAddress.getByAddress(ByteArrays.getSubArray(addr, 0, addrLength))
            );
          }
        }
        else if (
             (Platform.isMac() || Platform.isFreeBSD() || Platform.isOpenBSD()) || Platform.iskFreeBSD()
          && sa_family == Inets.AF_LINK
        ) {
          sockaddr_dl sdl = new sockaddr_dl(pcapAddr.addr.getPointer());
          byte[] addr = sdl.getAddress();
          if (addr.length == 6) {
            linkLayerAddresses.add(MacAddress.getByAddress(addr));
          }
          else if (addr.length == 0) {
            continue;
          }
          else {
            linkLayerAddresses.add(LinkLayerAddress.getByAddress(addr));
          }
        }
        else {
          logger.warn(
            "{} is not supported address family. Ignore it.",
            sa_family
          );
        }
      }
    }

    if (pif.flags == PCAP_IF_LOOPBACK) {
      this.loopBack = true;
    }
    else {
      this.loopBack = false;
    }

    this.local = local;
  }

  static PcapNetworkInterface newInstance(pcap_if pif, boolean local) {
    return new PcapNetworkInterface(pif, local);
  }

  /**
   *
   * @return name
   */
  public String getName() {
    return name;
  }

  /**
   *
   * @return description
   */
  public String getDescription() {
    return description;
  }

  /**
   *
   * @return inet addresses
   */
  public List<PcapAddress> getAddresses() {
    return new ArrayList<PcapAddress>(addresses);
  }

  /**
   *
   * @return link layer addresses
   */
  public ArrayList<LinkLayerAddress> getLinkLayerAddresses() {
    return new ArrayList<LinkLayerAddress>(linkLayerAddresses);
  }

  /**
   *
   * @return true if the network interface represented by this object
   *         is a loop back interface; false otherwise.
   */
  public boolean isLoopBack() {
    return loopBack;
  }

  /**
   *
   * @return true if the network interface represented by this object
   *         is a local interface; false otherwise.
   */
  public boolean isLocal() {
    return local;
  }

  /**
   *
   * @author Kaito Yamada
   * @version pcap4j 0.9.1
   */
  public enum PromiscuousMode {

    /**
     *
     */
    PROMISCUOUS(1),

    /**
     *
     */
    NONPROMISCUOUS(0);

    private final int value;

    private PromiscuousMode(int value) {
      this.value = value;
    }

    /**
     *
     * @return value
     */
    public int getValue() {
      return value;
    }
  }

  /**
   *
   * @param snaplen Snapshot length, which is the number of bytes captured for each packet.
   * @param mode
   * @param timeoutMillis Read timeout. Most OSs buffer packets.
   *                      The OSs pass the packets to Pcap4j after the buffer gets full
   *                      or the read timeout expires.
   *                      Must be non-negative. May be ignored by some OSs.
   *                      0 means disable buffering on Solaris.
   *                      0 means infinite on the other OSs.
   *                      1 through 9 means infinite on Solaris.
   * @return a new PcapHandle object.
   * @throws PcapNativeException
   */
  public PcapHandle openLive(
    int snaplen, PromiscuousMode mode, int timeoutMillis
  ) throws PcapNativeException {
    if (mode == null) {
      StringBuilder sb = new StringBuilder();
      sb.append("mode: ").append(mode);
      throw new NullPointerException(sb.toString());
    }

    PcapErrbuf errbuf = new PcapErrbuf();
    Pointer handle
      = NativeMappings.pcap_open_live(
          name,
          snaplen,
          mode.getValue(),
          timeoutMillis,
          errbuf
        );
    if (handle == null || errbuf.length() != 0) {
      throw new PcapNativeException(errbuf.toString());
    }

    if (timeoutMillis == 0 && Platform.isSolaris()) {
      // disable buffering
      timeval to = new timeval();
      to.tv_sec = new NativeLong(0);
      to.tv_usec = new NativeLong(0);

      int rc = PcapLibrary.INSTANCE.strioctl(
                 NativeMappings.getFdFromPcapT(handle),
                 NativeMappings.SBIOCSTIME,
                 to.size(),
                 to.getPointer()
               );

      if (rc < 0) {
        throw new PcapNativeException(
                "SBIOCSTIME: "
                  + NativeMappings.pcap_strerror(
                      NativeMappings.ERRNO_P.getInt(0)
                    ).getString(0)
              );
      }
    }

    return new PcapHandle(handle);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder(250);

    sb.append("name: [").append(name)
      .append("] description: [").append(description);

    for (PcapAddress addr: addresses) {
      sb.append("] address: [").append(addr.getAddress());
    }

    sb.append("] loopBack: [").append(loopBack)
      .append("]");
    sb.append("] local: [").append(local)
      .append("]");

    return sb.toString();
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) { return true; }
    if (!(obj instanceof PcapNetworkInterface)) { return false; }

    PcapNetworkInterface other = (PcapNetworkInterface)obj;
    return    this.name.equals(other.getName())
           && this.local == other.isLocal();
  }

  @Override
  public int hashCode() {
    return toString().hashCode();
  }

}
TOP

Related Classes of org.pcap4j.core.PcapNetworkInterface

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.