/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.jicmp.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.opennms.jicmp.jna.NativeDatagramPacket;
/**
* IPPacket
*
* @author brozow
*/
public class IPPacket {
public enum Protocol {
ICMP(1),
TCP(6),
UDP(17),
V6_OVER_V4(41);
private int m_code;
private Protocol(int code) {
m_code = code;
}
public int getCode() {
return m_code;
}
public static Protocol toProtocol(int code) {
for(Protocol p : Protocol.values()) {
if (code == p.getCode()) {
return p;
}
}
throw new IllegalArgumentException(String.format("Unabled to find Protocol with code %d", code));
}
}
private ByteBuffer m_buffer;
public IPPacket(IPPacket p) {
this(p.m_buffer.duplicate());
}
public IPPacket(ByteBuffer buffer) {
m_buffer = buffer;
}
public IPPacket(byte[] data, int offset, int length) {
this(ByteBuffer.wrap(data, offset, length).slice());
}
public IPPacket(NativeDatagramPacket datagram) {
this(datagram.getContent());
}
/**
* Returns the version of the IP Packet which must be '4'
*/
public int getVersion() {
return ((m_buffer.get(0) & 0xf0) >> 4);
}
/**
* Returns the length of the header in bytes
*/
public int getHeaderLength() {
// Specifies the length of the IP packet header in 32 bit words. The minimum value for a valid header is 5.
// This is stored in bits 4-7 of header (low bits of first byte)
return (m_buffer.get(0) & 0xf) << 2; // shift effectively does * 4 (4 bytes per 32 bit word)
}
private InetAddress getAddrAtOffset(int offset) {
byte[] addr = new byte[4];
int oldPos = m_buffer.position();
try {
m_buffer.position(offset);
m_buffer.get(addr);
} finally {
m_buffer.position(oldPos);
}
InetAddress result = null;
try {
result = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {
// this can't happen
}
return result;
}
public int getTimeToLive() {
return 0xff & m_buffer.get(8);
}
public Protocol getProtocol() {
return Protocol.toProtocol(m_buffer.get(9));
}
public InetAddress getSourceAddress() {
return getAddrAtOffset(12);
}
public InetAddress getDestinationAddress() {
return getAddrAtOffset(16);
}
public ByteBuffer getPayload() {
ByteBuffer data = m_buffer.duplicate();
data.position(getHeaderLength());
return data.slice();
}
public int getPayloadLength() {
return getPayload().remaining();
}
}