All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pcap4j.packet.Dot11ManagementPacket Maven / Gradle / Ivy

/*_##########################################################################
  _##
  _##  Copyright (C) 2016  Pcap4J.org
  _##
  _##########################################################################
*/

package org.pcap4j.packet;

import static org.pcap4j.util.ByteArrays.*;

import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

/**
 * IEEE802.11 management frame
 *
 * @see IEEE802.11
 * @author Kaito Yamada
 * @since pcap4j 1.7.0
 */
public abstract class Dot11ManagementPacket extends AbstractPacket {

  /** */
  private static final long serialVersionUID = -3972573868672848666L;

  private final Integer fcs;

  /**
   * @param rawData rawData
   * @param offset offset
   * @param length length
   * @param headerLen headerLen
   */
  protected Dot11ManagementPacket(byte[] rawData, int offset, int length, int headerLen) {
    int remainingLen = length - headerLen;
    if (remainingLen >= 4) {
      this.fcs = ByteArrays.getInt(rawData, offset + headerLen, ByteOrder.LITTLE_ENDIAN);
    } else {
      this.fcs = null;
    }
  }

  /**
   * @param builder builder
   * @param header header
   */
  protected Dot11ManagementPacket(Builder builder, Dot11ManagementHeader header) {
    if (builder.correctChecksumAtBuild) {
      this.fcs = ByteArrays.calcCrc32Checksum(header.getRawData());
    } else {
      this.fcs = builder.fcs;
    }
  }

  @Override
  public abstract Dot11ManagementHeader getHeader();

  /** @return fcs. May be null. */
  public Integer getFcs() {
    return fcs;
  }

  @Override
  protected int calcLength() {
    int length = super.calcLength();
    if (fcs != null) {
      length += 4;
    }
    return length;
  }

  @Override
  protected byte[] buildRawData() {
    byte[] rawData = super.buildRawData();
    if (fcs != null) {
      System.arraycopy(
          ByteArrays.toByteArray(fcs, ByteOrder.LITTLE_ENDIAN), 0, rawData, rawData.length - 4, 4);
    }
    return rawData;
  }

  @Override
  protected String buildString() {
    StringBuilder sb = new StringBuilder();

    sb.append(getHeader().toString());
    if (fcs != null) {
      String ls = System.getProperty("line.separator");
      sb.append("[IEEE802.11 Management Packet FCS]")
          .append(ls)
          .append("  FCS: 0x")
          .append(ByteArrays.toHexString(fcs, ""))
          .append(ls);
    }

    return sb.toString();
  }

  @Override
  public abstract Builder getBuilder();

  /** @return true if this FCS is present and valid; false otherwise. */
  public boolean hasValidFcs() {
    if (fcs == null) {
      return false;
    }
    return ByteArrays.calcCrc32Checksum(getHeader().getRawData()) == fcs.intValue();
  }

  /**
   * @author Kaito Yamada
   * @since pcap4j 1.7.0
   */
  public abstract static class Builder extends AbstractBuilder
      implements ChecksumBuilder {

    private Dot11FrameControl frameControl;
    private short duration;
    private MacAddress address1;
    private MacAddress address2;
    private MacAddress address3;
    private Dot11SequenceControl sequenceControl;
    private Dot11HtControl htControl;
    private Integer fcs;
    private boolean correctChecksumAtBuild;

    /** */
    public Builder() {}

    /** @param packet packet */
    protected Builder(Dot11ManagementPacket packet) {
      this.frameControl = packet.getHeader().frameControl;
      this.duration = packet.getHeader().duration;
      this.address1 = packet.getHeader().address1;
      this.address2 = packet.getHeader().address2;
      this.address3 = packet.getHeader().address3;
      this.sequenceControl = packet.getHeader().sequenceControl;
      this.htControl = packet.getHeader().htControl;
      this.fcs = packet.fcs;
    }

    /**
     * @param frameControl frameControl
     * @return this Builder object for method chaining.
     */
    public Builder frameControl(Dot11FrameControl frameControl) {
      this.frameControl = frameControl;
      return this;
    }

    /**
     * @param duration duration
     * @return this Builder object for method chaining.
     */
    public Builder duration(short duration) {
      this.duration = duration;
      return this;
    }

    /**
     * @param address1 address1
     * @return this Builder object for method chaining.
     */
    public Builder address1(MacAddress address1) {
      this.address1 = address1;
      return this;
    }

    /**
     * @param address2 address2
     * @return this Builder object for method chaining.
     */
    public Builder address2(MacAddress address2) {
      this.address2 = address2;
      return this;
    }

    /**
     * @param address3 address3
     * @return this Builder object for method chaining.
     */
    public Builder address3(MacAddress address3) {
      this.address3 = address3;
      return this;
    }

    /**
     * @param sequenceControl sequenceControl
     * @return this Builder object for method chaining.
     */
    public Builder sequenceControl(Dot11SequenceControl sequenceControl) {
      this.sequenceControl = sequenceControl;
      return this;
    }

    /**
     * @param htControl htControl
     * @return this Builder object for method chaining.
     */
    public Builder htControl(Dot11HtControl htControl) {
      this.htControl = htControl;
      return this;
    }

    /**
     * @param fcs fcs
     * @return this Builder object for method chaining.
     */
    public Builder fcs(Integer fcs) {
      this.fcs = fcs;
      return this;
    }

    @Override
    public Builder correctChecksumAtBuild(boolean correctChecksumAtBuild) {
      this.correctChecksumAtBuild = correctChecksumAtBuild;
      return this;
    }

    /** Call me at the top of {@link #build()}. */
    protected void checkForNull() {
      if (frameControl == null || address1 == null || address2 == null || address3 == null) {
        StringBuilder sb = new StringBuilder();
        sb.append("frameControl: ")
            .append(frameControl)
            .append(" address1: ")
            .append(address1)
            .append(" address2: ")
            .append(address2)
            .append(" address3: ")
            .append(address3);
        throw new NullPointerException(sb.toString());
      }
    }

    @Override
    public abstract Dot11ManagementPacket build();
  }

  /**
   * Header of IEEE802.11 management frame
   *
   * 
   *  0                             15
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |         Frame Control         |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |         Duration              |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                               |
   * |          Address1             |
   * |                               |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                               |
   * |          Address2             |
   * |                               |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                               |
   * |          Address3             |
   * |                               |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |       Sequence Control        |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |         HT Control            |
   * |                               |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * 
* * @see IEEE802.11 * @author Kaito Yamada * @since pcap4j 1.7.0 */ public abstract static class Dot11ManagementHeader extends AbstractHeader { /** */ private static final long serialVersionUID = 615170086003609919L; private static final int FRAME_CONTROL_OFFSET = 0; private static final int FRAME_CONTROL_SIZE = SHORT_SIZE_IN_BYTES; private static final int DURATION_OFFSET = FRAME_CONTROL_OFFSET + FRAME_CONTROL_SIZE; private static final int DURATION_SIZE = SHORT_SIZE_IN_BYTES; private static final int ADDRESS1_OFFSET = DURATION_OFFSET + DURATION_SIZE; private static final int ADDRESS1_SIZE = MacAddress.SIZE_IN_BYTES; private static final int ADDRESS2_OFFSET = ADDRESS1_OFFSET + ADDRESS1_SIZE; private static final int ADDRESS2_SIZE = MacAddress.SIZE_IN_BYTES; private static final int ADDRESS3_OFFSET = ADDRESS2_OFFSET + ADDRESS2_SIZE; private static final int ADDRESS3_SIZE = MacAddress.SIZE_IN_BYTES; private static final int SEQUENCE_CONTROL_OFFSET = ADDRESS3_OFFSET + ADDRESS3_SIZE; private static final int SEQUENCE_CONTROL_SIZE = SHORT_SIZE_IN_BYTES; private static final int HT_CONTROL_OFFSET = SEQUENCE_CONTROL_OFFSET + SEQUENCE_CONTROL_SIZE; private static final int HT_CONTROL_SIZE = INT_SIZE_IN_BYTES; private static final int DOT11_HEADER_MIN_SIZE = HT_CONTROL_OFFSET; private final Dot11FrameControl frameControl; private final short duration; private final MacAddress address1; private final MacAddress address2; private final MacAddress address3; private final Dot11SequenceControl sequenceControl; private final Dot11HtControl htControl; /** * @param rawData rawData * @param offset offset * @param length length * @throws IllegalRawDataException if parsing the raw data fails. */ protected Dot11ManagementHeader(byte[] rawData, int offset, int length) throws IllegalRawDataException { if (length < DOT11_HEADER_MIN_SIZE) { StringBuilder sb = new StringBuilder(200); sb.append("The data is too short to build a Dot11ManagementHeader (") .append(DOT11_HEADER_MIN_SIZE) .append(" bytes). data: ") .append(ByteArrays.toHexString(rawData, " ")) .append(", offset: ") .append(offset) .append(", length: ") .append(length); throw new IllegalRawDataException(sb.toString()); } this.frameControl = Dot11FrameControl.newInstance(rawData, offset + FRAME_CONTROL_OFFSET, length); this.duration = ByteArrays.getShort(rawData, offset + DURATION_OFFSET, ByteOrder.LITTLE_ENDIAN); this.address1 = ByteArrays.getMacAddress(rawData, offset + ADDRESS1_OFFSET); this.address2 = ByteArrays.getMacAddress(rawData, offset + ADDRESS2_OFFSET); this.address3 = ByteArrays.getMacAddress(rawData, offset + ADDRESS3_OFFSET); this.sequenceControl = Dot11SequenceControl.newInstance( rawData, offset + SEQUENCE_CONTROL_OFFSET, length - SEQUENCE_CONTROL_OFFSET); if (frameControl.isOrder()) { if (length < DOT11_HEADER_MIN_SIZE + HT_CONTROL_SIZE) { StringBuilder sb = new StringBuilder(200); sb.append("The data is too short to build a Dot11ManagementHeader (") .append(DOT11_HEADER_MIN_SIZE + HT_CONTROL_SIZE) .append(" bytes). data: ") .append(ByteArrays.toHexString(rawData, " ")) .append(", offset: ") .append(offset) .append(", length: ") .append(length); throw new IllegalRawDataException(sb.toString()); } this.htControl = Dot11HtControl.newInstance( rawData, offset + HT_CONTROL_OFFSET, length - HT_CONTROL_OFFSET); } else { this.htControl = null; } } /** @param builder builder */ protected Dot11ManagementHeader(Builder builder) { this.frameControl = builder.frameControl; this.duration = builder.duration; this.address1 = builder.address1; this.address2 = builder.address2; this.address3 = builder.address3; this.sequenceControl = builder.sequenceControl; this.htControl = builder.htControl; } /** @return frameControl */ public Dot11FrameControl getFrameControl() { return frameControl; } /** @return duration */ public short getDuration() { return duration; } /** @return duration */ public int getDurationAsInt() { return duration & 0xFFFF; } /** @return address1 */ public MacAddress getAddress1() { return address1; } /** @return address2 */ public MacAddress getAddress2() { return address2; } /** @return address3 */ public MacAddress getAddress3() { return address3; } /** @return sequenceControl */ public Dot11SequenceControl getSequenceControl() { return sequenceControl; } /** @return htControl. May be null. */ public Dot11HtControl getHtControl() { return htControl; } @Override protected List getRawFields() { List rawFields = new ArrayList(); rawFields.add(frameControl.getRawData()); rawFields.add(ByteArrays.toByteArray(duration, ByteOrder.LITTLE_ENDIAN)); rawFields.add(address1.getAddress()); rawFields.add(address2.getAddress()); rawFields.add(address3.getAddress()); rawFields.add(sequenceControl.getRawData()); if (htControl != null) { rawFields.add(htControl.getRawData()); } return rawFields; } @Override public int calcLength() { if (htControl != null) { return DOT11_HEADER_MIN_SIZE + HT_CONTROL_SIZE; } else { return DOT11_HEADER_MIN_SIZE; } } /** @return the header name. */ protected abstract String getHeaderName(); @Override protected String buildString() { StringBuilder sb = new StringBuilder(); String ls = System.getProperty("line.separator"); sb.append("[") .append(getHeaderName()) .append(" (") .append(length()) .append(" bytes)]") .append(ls); sb.append(" Frame Control:").append(ls).append(frameControl.toString(" ")); sb.append(" Duration: ").append(getDurationAsInt()).append(ls); sb.append(" Address1: ").append(address1).append(ls); sb.append(" Address2: ").append(address2).append(ls); sb.append(" Address3: ").append(address3).append(ls); sb.append(" Sequence Control: ").append(sequenceControl).append(ls); if (htControl != null) { sb.append(" HT Control:").append(ls).append(htControl.toString(" ")); } return sb.toString(); } @Override protected int calcHashCode() { final int prime = 31; int result = 17; result = prime * result + address1.hashCode(); result = prime * result + address2.hashCode(); result = prime * result + address3.hashCode(); result = prime * result + duration; result = prime * result + frameControl.hashCode(); result = prime * result + (htControl != null ? htControl.hashCode() : 0); result = prime * result + sequenceControl.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (getClass() != obj.getClass()) return false; Dot11ManagementHeader other = (Dot11ManagementHeader) obj; if (!address1.equals(other.address1)) return false; if (!address2.equals(other.address2)) return false; if (!address3.equals(other.address3)) return false; if (duration != other.duration) return false; if (!frameControl.equals(other.frameControl)) return false; if (htControl == null) { if (other.htControl != null) { return false; } } else if (!htControl.equals(other.htControl)) return false; if (!sequenceControl.equals(other.sequenceControl)) return false; return true; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy