/** * Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University * * 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 net.onrc.onos.core.packet; import java.nio.ByteBuffer; import java.util.Arrays; import org.apache.commons.lang3.ArrayUtils; // CHECKSTYLE IGNORE WriteTag FOR NEXT 2 LINES /** * @author David Erickson (daviderickson@cs.stanford.edu) */ public class ARP extends BasePacket { public static final short HW_TYPE_ETHERNET = 0x1; public static final short PROTO_TYPE_IP = 0x800; public static final short OP_REQUEST = 0x1; public static final short OP_REPLY = 0x2; public static final short OP_RARP_REQUEST = 0x3; public static final short OP_RARP_REPLY = 0x4; protected short hardwareType; protected short protocolType; protected byte hardwareAddressLength; protected byte protocolAddressLength; protected short opCode; protected byte[] senderHardwareAddress; protected byte[] senderProtocolAddress; protected byte[] targetHardwareAddress; protected byte[] targetProtocolAddress; /** * @return the hardwareType */ public short getHardwareType() { return hardwareType; } /** * @param hardwareType the hardwareType to set */ public ARP setHardwareType(short hardwareType) { this.hardwareType = hardwareType; return this; } /** * @return the protocolType */ public short getProtocolType() { return protocolType; } /** * @param protocolType the protocolType to set */ public ARP setProtocolType(short protocolType) { this.protocolType = protocolType; return this; } /** * @return the hardwareAddressLength */ public byte getHardwareAddressLength() { return hardwareAddressLength; } /** * @param hardwareAddressLength the hardwareAddressLength to set */ public ARP setHardwareAddressLength(byte hardwareAddressLength) { this.hardwareAddressLength = hardwareAddressLength; return this; } /** * @return the protocolAddressLength */ public byte getProtocolAddressLength() { return protocolAddressLength; } /** * @param protocolAddressLength the protocolAddressLength to set */ public ARP setProtocolAddressLength(byte protocolAddressLength) { this.protocolAddressLength = protocolAddressLength; return this; } /** * @return the opCode */ public short getOpCode() { return opCode; } /** * @param opCode the opCode to set */ public ARP setOpCode(short opCode) { this.opCode = opCode; return this; } /** * @return the senderHardwareAddress */ public byte[] getSenderHardwareAddress() { return ArrayUtils.clone(this.senderHardwareAddress); } /** * @param senderHardwareAddress the senderHardwareAddress to set */ public ARP setSenderHardwareAddress(byte[] senderHardwareAddress) { this.senderHardwareAddress = ArrayUtils.clone(senderHardwareAddress); return this; } /** * @return the senderProtocolAddress */ public byte[] getSenderProtocolAddress() { return ArrayUtils.clone(this.senderProtocolAddress); } /** * @param senderProtocolAddress the senderProtocolAddress to set */ public ARP setSenderProtocolAddress(byte[] senderProtocolAddress) { this.senderProtocolAddress = ArrayUtils.clone(senderProtocolAddress); return this; } public ARP setSenderProtocolAddress(int address) { this.senderProtocolAddress = ByteBuffer.allocate(4).putInt(address).array(); return this; } /** * @return the targetHardwareAddress */ public byte[] getTargetHardwareAddress() { return ArrayUtils.clone(this.targetHardwareAddress); } /** * @param targetHardwareAddress the targetHardwareAddress to set */ public ARP setTargetHardwareAddress(byte[] targetHardwareAddress) { this.targetHardwareAddress = ArrayUtils.clone(targetHardwareAddress); return this; } /** * @return the targetProtocolAddress */ public byte[] getTargetProtocolAddress() { return ArrayUtils.clone(this.targetProtocolAddress); } /** * @return True if gratuitous ARP (SPA = TPA), false otherwise */ public boolean isGratuitous() { assert (senderProtocolAddress.length == targetProtocolAddress.length); int indx = 0; while (indx < senderProtocolAddress.length) { if (senderProtocolAddress[indx] != targetProtocolAddress[indx]) { return false; } indx++; } return true; } /** * @param targetProtocolAddress the targetProtocolAddress to set */ public ARP setTargetProtocolAddress(byte[] targetProtocolAddress) { this.targetProtocolAddress = ArrayUtils.clone(targetProtocolAddress); return this; } public ARP setTargetProtocolAddress(int address) { this.targetProtocolAddress = ByteBuffer.allocate(4).putInt(address).array(); return this; } @Override public byte[] serialize() { int length = 8 + (2 * (0xff & this.hardwareAddressLength)) + (2 * (0xff & this.protocolAddressLength)); byte[] data = new byte[length]; ByteBuffer bb = ByteBuffer.wrap(data); bb.putShort(this.hardwareType); bb.putShort(this.protocolType); bb.put(this.hardwareAddressLength); bb.put(this.protocolAddressLength); bb.putShort(this.opCode); bb.put(this.senderHardwareAddress, 0, 0xff & this.hardwareAddressLength); bb.put(this.senderProtocolAddress, 0, 0xff & this.protocolAddressLength); bb.put(this.targetHardwareAddress, 0, 0xff & this.hardwareAddressLength); bb.put(this.targetProtocolAddress, 0, 0xff & this.protocolAddressLength); return data; } @Override public IPacket deserialize(byte[] data, int offset, int length) { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.hardwareType = bb.getShort(); this.protocolType = bb.getShort(); this.hardwareAddressLength = bb.get(); this.protocolAddressLength = bb.get(); this.opCode = bb.getShort(); this.senderHardwareAddress = new byte[0xff & this.hardwareAddressLength]; bb.get(this.senderHardwareAddress, 0, this.senderHardwareAddress.length); this.senderProtocolAddress = new byte[0xff & this.protocolAddressLength]; bb.get(this.senderProtocolAddress, 0, this.senderProtocolAddress.length); this.targetHardwareAddress = new byte[0xff & this.hardwareAddressLength]; bb.get(this.targetHardwareAddress, 0, this.targetHardwareAddress.length); this.targetProtocolAddress = new byte[0xff & this.protocolAddressLength]; bb.get(this.targetProtocolAddress, 0, this.targetProtocolAddress.length); return this; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 13121; int result = super.hashCode(); result = prime * result + hardwareAddressLength; result = prime * result + hardwareType; result = prime * result + opCode; result = prime * result + protocolAddressLength; result = prime * result + protocolType; result = prime * result + Arrays.hashCode(senderHardwareAddress); result = prime * result + Arrays.hashCode(senderProtocolAddress); result = prime * result + Arrays.hashCode(targetHardwareAddress); result = prime * result + Arrays.hashCode(targetProtocolAddress); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (!(obj instanceof ARP)) { return false; } ARP other = (ARP) obj; if (hardwareAddressLength != other.hardwareAddressLength) { return false; } if (hardwareType != other.hardwareType) { return false; } if (opCode != other.opCode) { return false; } if (protocolAddressLength != other.protocolAddressLength) { return false; } if (protocolType != other.protocolType) { return false; } if (!Arrays.equals(senderHardwareAddress, other.senderHardwareAddress)) { return false; } if (!Arrays.equals(senderProtocolAddress, other.senderProtocolAddress)) { return false; } if (!Arrays.equals(targetHardwareAddress, other.targetHardwareAddress)) { return false; } if (!Arrays.equals(targetProtocolAddress, other.targetProtocolAddress)) { return false; } return true; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "ARP [hardwareType=" + hardwareType + ", protocolType=" + protocolType + ", hardwareAddressLength=" + hardwareAddressLength + ", protocolAddressLength=" + protocolAddressLength + ", opCode=" + opCode + ", senderHardwareAddress=" + Arrays.toString(senderHardwareAddress) + ", senderProtocolAddress=" + Arrays.toString(senderProtocolAddress) + ", targetHardwareAddress=" + Arrays.toString(targetHardwareAddress) + ", targetProtocolAddress=" + Arrays.toString(targetProtocolAddress) + "]"; } }