/* * * * 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 java.util.Arrays; import static com.google.common.base.MoreObjects.toStringHelper; import static org.onlab.packet.PacketUtils.checkHeaderLength; import static org.onlab.packet.PacketUtils.checkInput; /** * EAP (Extensible Authentication Protocol) packet. */ public class EAP extends BasePacket { private static final int HEADER_LENGTH = 4; public static final short MIN_LEN = 0x4; public static final short EAP_HDR_LEN_REQ_RESP = 5; public static final short EAP_HDR_LEN_SUC_FAIL = 4; // EAP Code public static final byte REQUEST = 0x1; public static final byte RESPONSE = 0x2; public static final byte SUCCESS = 0x3; public static final byte FAILURE = 0x4; // EAP Attribute Type public static final byte ATTR_IDENTITY = 0x1; public static final byte ATTR_NOTIFICATION = 0x2; public static final byte ATTR_NAK = 0x3; public static final byte ATTR_MD5 = 0x4; public static final byte ATTR_OTP = 0x5; public static final byte ATTR_GTC = 0x6; public static final byte ATTR_TLS = 0xd; protected byte code; protected byte identifier; protected short length; protected byte type; protected byte[] data; /** * Gets the EAP code. * * @return EAP code */ public byte getCode() { return this.code; } /** * Sets the EAP code. * * @param code EAP code * @return this */ public EAP setCode(final byte code) { this.code = code; return this; } /** * Gets the EAP identifier. * * @return EAP identifier */ public byte getIdentifier() { return this.identifier; } /** * Sets the EAP identifier. * * @param identifier EAP identifier * @return this */ public EAP setIdentifier(final byte identifier) { this.identifier = identifier; return this; } /** * Gets the get packet length. * * @return packet length */ public short getLength() { return this.length; } /** * Sets the packet length. * * @param length packet length * @return this */ public EAP setLength(final short length) { this.length = length; return this; } /** * Gets the data type. * * @return data type */ public byte getDataType() { return this.type; } /** * Sets the data type. * * @param type data type * @return this */ public EAP setDataType(final byte type) { this.type = type; return this; } /** * Gets the EAP data. * * @return EAP data */ public byte[] getData() { return this.data; } /** * Sets the EAP data. * * @param data EAP data to be set * @return this */ public EAP setData(final byte[] data) { this.data = data; return this; } /** * Default EAP constructor that sets the EAP code to 0. */ public EAP() { this.code = 0; } /** * EAP constructor that initially sets all fields. * * @param code EAP code * @param identifier EAP identifier * @param type packet type * @param data EAP data */ public EAP(byte code, byte identifier, byte type, byte[] data) { this.code = code; this.identifier = identifier; if (this.code == REQUEST || this.code == RESPONSE) { this.length = (short) (5 + (data == null ? 0 : data.length)); this.type = type; } else { this.length = (short) (4 + (data == null ? 0 : data.length)); } this.data = data; } /** * Deserializer for EAP packets. * * @return deserializer */ public static Deserializer<EAP> deserializer() { return (data, offset, length) -> { checkInput(data, offset, length, HEADER_LENGTH); EAP eap = new EAP(); final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); eap.code = bb.get(); eap.identifier = bb.get(); eap.length = bb.getShort(); checkHeaderLength(length, eap.length); int dataLength; if (eap.code == REQUEST || eap.code == RESPONSE) { eap.type = bb.get(); dataLength = eap.length - 5; } else { dataLength = eap.length - 4; } eap.data = new byte[dataLength]; bb.get(eap.data); return eap; }; } @Override public byte[] serialize() { final byte[] data = new byte[this.length]; final ByteBuffer bb = ByteBuffer.wrap(data); bb.put(this.code); bb.put(this.identifier); bb.putShort(this.length); if (this.code == REQUEST || this.code == RESPONSE) { bb.put(this.type); } if (this.data != null) { bb.put(this.data); } return data; } @Override public IPacket deserialize(final byte[] data, final int offset, final int length) { final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.code = bb.get(); this.identifier = bb.get(); this.length = bb.getShort(); int dataLength; if (this.code == REQUEST || this.code == RESPONSE) { this.type = bb.get(); dataLength = this.length - 5; } else { dataLength = this.length - 4; } this.data = new byte[dataLength]; bb.get(this.data); return this; } @Override public int hashCode() { final int prime = 3889; int result = super.hashCode(); result = prime * result + this.code; result = prime * result + this.identifier; result = prime * result + this.length; result = prime * result + this.type; return result; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof EAP)) { return false; } EAP that = (EAP) o; if (this.code != that.code) { return false; } if (this.identifier != that.identifier) { return false; } if (this.length != that.length) { return false; } if (this.type != that.type) { return false; } return true; } @Override public String toString() { return toStringHelper(getClass()) .add("code", Byte.toString(code)) .add("identifier", Byte.toString(identifier)) .add("length", Short.toString(length)) .add("type", Byte.toString(type)) .add("data", Arrays.toString(data)) .toString(); } }