/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.net.arp;
import java.net.SocketException;
import org.jnode.net.HardwareAddress;
import org.jnode.net.NetworkLayerHeader;
import org.jnode.net.ProtocolAddress;
import org.jnode.net.SocketBuffer;
import org.jnode.net.ethernet.EthernetAddress;
import org.jnode.net.ethernet.EthernetConstants;
import org.jnode.net.ipv4.IPv4Address;
/**
* @author epr
*/
public class ARPHeader implements NetworkLayerHeader {
private static final int ARP_DATA_LENGTH = 28;
private HardwareAddress sourceHardwareAddress;
private ProtocolAddress sourceProtocolAddress;
private HardwareAddress destinationHardwareAddress;
private ProtocolAddress destinationProtocolAddress;
private ARPOperation operation;
private final int hardwareType;
private final int protocolType;
private int hardwareAddressSize;
private int protocolAddressSize;
/**
* Create a new instance
*
* @param srcHWAddress
* @param srcPAddress
* @param targetHWAddress
* @param targetPAddress
* @param op
* @param hwtype
* @param ptype
*/
public ARPHeader(HardwareAddress srcHWAddress, ProtocolAddress srcPAddress,
HardwareAddress targetHWAddress, ProtocolAddress targetPAddress, ARPOperation op, int hwtype,
int ptype, int hwSize, int pSize) {
this.sourceHardwareAddress = srcHWAddress;
this.sourceProtocolAddress = srcPAddress;
this.destinationHardwareAddress = targetHWAddress;
this.destinationProtocolAddress = targetPAddress;
this.operation = op;
this.hardwareType = hwtype;
this.protocolType = ptype;
this.hardwareAddressSize = hwSize;
this.protocolAddressSize = pSize;
}
/**
* Create a new packet from a socketbuffer
*
* @param skbuf
*/
public ARPHeader(SocketBuffer skbuf) throws SocketException {
hardwareType = skbuf.get16(0);
protocolType = skbuf.get16(2);
hardwareAddressSize = skbuf.get(4);
protocolAddressSize = skbuf.get(5);
operation = ARPOperation.getType(skbuf.get16(6));
if ((hardwareType == 1) && (protocolType == EthernetConstants.ETH_P_IP)) {
sourceHardwareAddress = new EthernetAddress(skbuf, 8);
sourceProtocolAddress = new IPv4Address(skbuf, 14);
destinationHardwareAddress = new EthernetAddress(skbuf, 18);
destinationProtocolAddress = new IPv4Address(skbuf, 24);
} else {
throw new SocketException("Unknown hw,ptype: " + hardwareType + ',' + protocolType);
}
}
/**
* Gets the length of this header in bytes
*/
public int getLength() {
return (8 + (sourceHardwareAddress.getLength() + sourceProtocolAddress.getLength()) * 2);
}
/**
* Write this packet to the given buffer
*
* @param skbuf
*/
public void prefixTo(SocketBuffer skbuf) {
skbuf.insert(8 + (sourceHardwareAddress.getLength() + sourceProtocolAddress.getLength()) * 2);
int ofs = 0;
skbuf.set16(ofs + 0, hardwareType);
skbuf.set16(ofs + 2, protocolType);
skbuf.set(ofs + 4, sourceHardwareAddress.getLength());
skbuf.set(ofs + 5, sourceProtocolAddress.getLength());
skbuf.set16(ofs + 6, operation.getId());
ofs += 8;
sourceHardwareAddress.writeTo(skbuf, ofs);
ofs += sourceHardwareAddress.getLength();
sourceProtocolAddress.writeTo(skbuf, ofs);
ofs += sourceProtocolAddress.getLength();
destinationHardwareAddress.writeTo(skbuf, ofs);
ofs += destinationHardwareAddress.getLength();
destinationProtocolAddress.writeTo(skbuf, ofs);
}
/**
* Finalize the header in the given buffer. This method is called when all
* layers have set their header data and can be used e.g. to update checksum
* values.
*
* @param skbuf The buffer
* @param offset The offset to the first byte (in the buffer) of this header
* (since low layer headers are already prefixed)
*/
public void finalizeHeader(SocketBuffer skbuf, int offset) {
// Do nothing
}
/**
* Gets the source address of the packet described in this header
*/
public ProtocolAddress getSourceAddress() {
return sourceProtocolAddress;
}
/**
* Gets the source address of the packet described in this header
*/
public ProtocolAddress getDestinationAddress() {
return destinationProtocolAddress;
}
public int getDataLength() {
return ARP_DATA_LENGTH;
}
/**
* Gets the hardware type
*/
public int getHType() {
return hardwareType;
}
/**
* Gets the operation
*/
public ARPOperation getOperation() {
return operation;
}
/**
* Gets the protocol type
*/
public int getPType() {
return protocolType;
}
/**
* Gets the source hardware address
*/
public HardwareAddress getSrcHWAddress() {
return sourceHardwareAddress;
}
/**
* Gets the source protocol address
*/
public ProtocolAddress getSrcPAddress() {
return sourceProtocolAddress;
}
/**
* Gets the target hardware address
*/
public HardwareAddress getTargetHWAddress() {
return destinationHardwareAddress;
}
/**
* Gets the target protocol address
*/
public ProtocolAddress getTargetPAddress() {
return destinationProtocolAddress;
}
public int getHardwareAddressSize() {
return hardwareAddressSize;
}
public int getProtocolAddressSize() {
return protocolAddressSize;
}
/**
* Swap the two src and target addresses
*/
public void swapAddresses() {
final HardwareAddress hwTmp = destinationHardwareAddress;
final ProtocolAddress pTmp = destinationProtocolAddress;
destinationHardwareAddress = sourceHardwareAddress;
destinationProtocolAddress = sourceProtocolAddress;
sourceHardwareAddress = hwTmp;
sourceProtocolAddress = pTmp;
}
/**
* @param operation
*/
public void setOperation(ARPOperation operation) {
this.operation = operation;
}
/**
* @param address
*/
public void setSrcHWAddress(HardwareAddress address) {
sourceHardwareAddress = address;
}
/**
* @param address
*/
public void setSrcPAddress(ProtocolAddress address) {
sourceProtocolAddress = address;
}
}