/** * 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.floodlightcontroller.packet; import java.nio.ByteBuffer; import org.projectfloodlight.openflow.types.ArpOpcode; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.MacAddress; /** * * @author David Erickson (daviderickson@cs.stanford.edu) */ public class ARP extends BasePacket { public static short HW_TYPE_ETHERNET = 0x1; public static short PROTO_TYPE_IP = 0x800; public static ArpOpcode OP_REQUEST = ArpOpcode.REQUEST; public static ArpOpcode OP_REPLY = ArpOpcode.REPLY; public static ArpOpcode OP_RARP_REQUEST = ArpOpcode.REQUEST_REVERSE; public static ArpOpcode OP_RARP_REPLY = ArpOpcode.REPLY_REVERSE; protected short hardwareType; protected short protocolType; protected byte hardwareAddressLength; protected byte protocolAddressLength; protected ArpOpcode opCode; protected MacAddress senderHardwareAddress; protected IPv4Address senderProtocolAddress; protected MacAddress targetHardwareAddress; protected IPv4Address 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 ArpOpcode getOpCode() { return opCode; } /** * @param opCode the opCode to set */ public ARP setOpCode(ArpOpcode opCode) { this.opCode = opCode; return this; } /** * @return the senderHardwareAddress */ public MacAddress getSenderHardwareAddress() { return senderHardwareAddress; } /** * @param senderHardwareAddress the senderHardwareAddress to set */ public ARP setSenderHardwareAddress(MacAddress senderHardwareAddress) { this.senderHardwareAddress = senderHardwareAddress; return this; } /** * @return the senderProtocolAddress */ public IPv4Address getSenderProtocolAddress() { return senderProtocolAddress; } /** * @param senderProtocolAddress the senderProtocolAddress to set */ public ARP setSenderProtocolAddress(IPv4Address senderProtocolAddress) { this.senderProtocolAddress = senderProtocolAddress; return this; } /** * @return the targetHardwareAddress */ public MacAddress getTargetHardwareAddress() { return targetHardwareAddress; } /** * @param targetHardwareAddress the targetHardwareAddress to set */ public ARP setTargetHardwareAddress(MacAddress targetHardwareAddress) { this.targetHardwareAddress = targetHardwareAddress; return this; } /** * @return the targetProtocolAddress */ public IPv4Address getTargetProtocolAddress() { return targetProtocolAddress; } /** * @return True if gratuitous ARP (SPA = TPA), false otherwise */ public boolean isGratuitous() { assert(senderProtocolAddress.getLength() == targetProtocolAddress.getLength()); return senderProtocolAddress.equals(targetProtocolAddress); } /** * @param targetProtocolAddress the targetProtocolAddress to set */ public ARP setTargetProtocolAddress(IPv4Address targetProtocolAddress) { this.targetProtocolAddress = targetProtocolAddress; 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((short) this.opCode.getOpcode()); bb.put(this.senderHardwareAddress.getBytes()); bb.put(this.senderProtocolAddress.getBytes()); bb.put(this.targetHardwareAddress.getBytes()); bb.put(this.targetProtocolAddress.getBytes()); return data; } @Override public IPacket deserialize(byte[] data, int offset, int length) throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.hardwareType = bb.getShort(); this.protocolType = bb.getShort(); this.hardwareAddressLength = bb.get(); this.protocolAddressLength = bb.get(); if (this.hardwareAddressLength != 6) { String msg = "Incorrect ARP hardware address length: " + hardwareAddressLength; throw new PacketParsingException(msg); } if (this.protocolAddressLength != 4) { String msg = "Incorrect ARP protocol address length: " + protocolAddressLength; throw new PacketParsingException(msg); } this.opCode = ArpOpcode.of(bb.getShort()); byte[] tmpMac = new byte[0xff & this.hardwareAddressLength]; byte[] tmpIp = new byte[0xff & this.protocolAddressLength]; bb.get(tmpMac, 0, this.hardwareAddressLength); this.senderHardwareAddress = MacAddress.of(tmpMac); bb.get(tmpIp, 0, this.protocolAddressLength); this.senderProtocolAddress = IPv4Address.of(tmpIp); bb.get(tmpMac, 0, this.hardwareAddressLength); this.targetHardwareAddress = MacAddress.of(tmpMac); bb.get(tmpIp, 0, this.protocolAddressLength); this.targetProtocolAddress = IPv4Address.of(tmpIp); return this; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + hardwareAddressLength; result = prime * result + hardwareType; result = prime * result + ((opCode == null) ? 0 : opCode.hashCode()); result = prime * result + protocolAddressLength; result = prime * result + protocolType; result = prime * result + ((senderHardwareAddress == null) ? 0 : senderHardwareAddress .hashCode()); result = prime * result + ((senderProtocolAddress == null) ? 0 : senderProtocolAddress .hashCode()); result = prime * result + ((targetHardwareAddress == null) ? 0 : targetHardwareAddress .hashCode()); result = prime * result + ((targetProtocolAddress == null) ? 0 : targetProtocolAddress .hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; ARP other = (ARP) obj; if (hardwareAddressLength != other.hardwareAddressLength) return false; if (hardwareType != other.hardwareType) return false; if (opCode == null) { if (other.opCode != null) return false; } else if (!opCode.equals(other.opCode)) return false; if (protocolAddressLength != other.protocolAddressLength) return false; if (protocolType != other.protocolType) return false; if (senderHardwareAddress == null) { if (other.senderHardwareAddress != null) return false; } else if (!senderHardwareAddress.equals(other.senderHardwareAddress)) return false; if (senderProtocolAddress == null) { if (other.senderProtocolAddress != null) return false; } else if (!senderProtocolAddress.equals(other.senderProtocolAddress)) return false; if (targetHardwareAddress == null) { if (other.targetHardwareAddress != null) return false; } else if (!targetHardwareAddress.equals(other.targetHardwareAddress)) return false; if (targetProtocolAddress == null) { if (other.targetProtocolAddress != null) return false; } else if (!targetProtocolAddress.equals(other.targetProtocolAddress)) return false; return true; } @Override public String toString() { return "ARP [hardwareType=" + hardwareType + ", protocolType=" + protocolType + ", hardwareAddressLength=" + hardwareAddressLength + ", protocolAddressLength=" + protocolAddressLength + ", opCode=" + opCode + ", senderHardwareAddress=" + senderHardwareAddress + ", senderProtocolAddress=" + senderProtocolAddress + ", targetHardwareAddress=" + targetHardwareAddress + ", targetProtocolAddress=" + targetProtocolAddress + "]"; } }