blob: 3a2aa5239767e086e6fb1e6b8f6b8d7980851f9c [file] [log] [blame]
/*
*
* * Copyright 2015 AT&T Foundry
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.onlab.packet;
import java.nio.ByteBuffer;
import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.checkHeaderLength;
import static org.onlab.packet.PacketUtils.checkInput;
/**
* EAPOL (Extensible Authentication Protocol over LAN) header.
*/
public class EAPOL extends BasePacket {
private byte version = 0x01;
private byte eapolType;
private short packetLength;
private static final int HEADER_LENGTH = 4;
// EAPOL Packet Type
public static final byte EAPOL_PACKET = 0x0;
public static final byte EAPOL_START = 0x1;
public static final byte EAPOL_LOGOFF = 0x2;
public static final byte EAPOL_KEY = 0x3;
public static final byte EAPOL_ASF = 0x4;
public static final MacAddress PAE_GROUP_ADDR = MacAddress.valueOf(new byte[] {
(byte) 0x01, (byte) 0x80, (byte) 0xc2, (byte) 0x00, (byte) 0x00, (byte) 0x03
});
/**
* Gets the version.
*
* @return version
*/
public byte getVersion() {
return this.version;
}
/**
* Sets the version.
*
* @param version EAPOL version
* @return this
*/
public EAPOL setVersion(final byte version) {
this.version = version;
return this;
}
/**
* Gets the type.
*
* @return EAPOL type
*/
public byte getEapolType() {
return this.eapolType;
}
/**
* Sets the EAPOL type.
*
* @param eapolType EAPOL type
* @return this
*/
public EAPOL setEapolType(final byte eapolType) {
this.eapolType = eapolType;
return this;
}
/**
* Gets the packet length.
*
* @return packet length
*/
public short getPacketLength() {
return this.packetLength;
}
/**
* Sets the packet length.
*
* @param packetLen packet length
* @return this
*/
public EAPOL setPacketLength(final short packetLen) {
this.packetLength = packetLen;
return this;
}
/**
* Serializes the packet, based on the code/type using the payload
* to compute its length.
*
* @return this
*/
@Override
public byte[] serialize() {
byte[] payloadData = null;
if (this.payload != null) {
this.payload.setParent(this);
payloadData = this.payload.serialize();
}
// prepare the buffer to hold the version (1), packet type (1),
// packet length (2) and the eap payload.
// if there is no payload, packet length is 0
byte[] data = new byte[4 + this.packetLength];
final ByteBuffer bb = ByteBuffer.wrap(data);
bb.put(this.version);
bb.put(this.eapolType);
bb.putShort(this.packetLength);
// put the EAP payload
if (payloadData != null) {
bb.put(payloadData);
}
return data;
}
@Override
public int hashCode() {
final int prime = 3889;
int result = super.hashCode();
result = prime * result + this.version;
result = prime * result + this.eapolType;
result = prime * result + this.packetLength;
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof EAPOL)) {
return false;
}
EAPOL that = (EAPOL) o;
if (this.version != that.version) {
return false;
}
if (this.eapolType != that.eapolType) {
return false;
}
if (this.packetLength != that.packetLength) {
return false;
}
return true;
}
/**
* Deserializer for EAPOL packets.
*
* @return deserializer
*/
public static Deserializer<EAPOL> deserializer() {
return (data, offset, length) -> {
checkInput(data, offset, length, HEADER_LENGTH);
EAPOL eapol = new EAPOL();
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
eapol.setVersion(bb.get());
eapol.setEapolType(bb.get());
eapol.setPacketLength(bb.getShort());
if (eapol.packetLength > 0) {
checkHeaderLength(length, HEADER_LENGTH + eapol.packetLength);
// deserialize the EAP Payload
eapol.payload = EAP.deserializer().deserialize(data,
bb.position(), bb.limit() - bb.position());
eapol.payload.setParent(eapol);
}
return eapol;
};
}
@Override
public IPacket deserialize(final byte[] data, final int offset,
final int length) {
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
// deserialize the EAPOL header
this.version = bb.get();
this.eapolType = bb.get();
this.packetLength = bb.getShort();
if (this.packetLength > 0) {
// deserialize the EAP Payload
this.payload = new EAP();
this.payload = this.payload.deserialize(data, bb.position(), length - 4);
this.payload.setParent(this);
}
return this;
}
@Override
public String toString() {
return toStringHelper(getClass())
.add("version", Byte.toString(version))
.add("eapolType", Byte.toString(eapolType))
.add("packetLength", Short.toString(packetLength))
.toString();
}
}