blob: ac11dcc024e0dea40a63e5ae9e8444999ed61bb9 [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.onosproject.aaa.packet;
import org.onlab.packet.BasePacket;
import org.onlab.packet.Deserializer;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPacket;
import org.onlab.packet.MacAddress;
import java.nio.ByteBuffer;
import static org.onlab.packet.PacketUtils.checkInput;
/**
*
*/
public class EAPOL extends BasePacket {
private byte version = 0x01;
private byte eapolType;
private short packetLength;
/* 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
});
/**
* Get version.
* @return version
*/
public byte getVersion() {
return this.version;
}
/**
* Set version.
* @param version EAPOL version
* @return this
*/
public EAPOL setVersion(final byte version) {
this.version = version;
return this;
}
/**
* Get type.
* @return EAPOL type
*/
public byte getEapolType() {
return this.eapolType;
}
/**
* Set EAPOL type.
* @param eapolType EAPOL type
* @return this
*/
public EAPOL setEapolType(final byte eapolType) {
this.eapolType = eapolType;
return this;
}
/**
* Get packet length.
* @return packet length
*/
public short getPacketLength() {
return this.packetLength;
}
/**
* Set 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;
}
/**
*
* @param dstMac
* @param srcMac
* @param eapolType
* @param eap
* @return Ethernet frame
*/
public static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
short vlan, byte eapolType, EAP eap) {
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(dstMac.toBytes());
eth.setSourceMACAddress(srcMac.toBytes());
eth.setEtherType(EAPEthernet.TYPE_PAE);
if (vlan != Ethernet.VLAN_UNTAGGED) {
eth.setVlanID(vlan);
}
//eapol header
EAPOL eapol = new EAPOL();
eapol.setEapolType(eapolType);
eapol.setPacketLength(eap.getLength());
//eap part
eapol.setPayload(eap);
eth.setPayload(eapol);
eth.setPad(true);
return eth;
}
public static Deserializer<EAPOL> deserializer() {
return (data, offset, length) -> {
checkInput(data, offset, length, 0);
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) {
//deserialize the EAP Payload
eapol.payload = new EAP();
eapol.payload = eapol.payload.deserialize(data, bb.position(), length - 4);
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;
}
}