All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.pkts.framer.IPv6Framer Maven / Gradle / Ivy

There is a newer version: 3.0.10
Show newest version
/**
 *
 */
package io.pkts.framer;

import io.pkts.buffer.Buffer;
import io.pkts.buffer.Buffers;
import io.pkts.packet.IPv6Packet;
import io.pkts.packet.MACPacket;
import io.pkts.packet.impl.IPv6PacketImpl;
import io.pkts.protocol.Protocol;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author [email protected]
 *
 */
public class IPv6Framer implements Framer {

    public IPv6Framer() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Protocol getProtocol() {
        return Protocol.IPv6;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IPv6Packet frame(final MACPacket parent, final Buffer payload) throws IOException {
        if (parent == null) {
            throw new IllegalArgumentException("The parent frame cannot be null");
        }

        final Buffer fixedHeader = payload.readBytes(IPv6PacketImpl.FIXED_HEADER_LENGTH);

        // byte 1, contains the version and the length
        final int version = (fixedHeader.getByte(0) & 0xF0) >> 4;
        if (version != IPv6Packet.VERSION_IDENTIFIER) {
            throw new FramingException(String.format("Invalid IPv6 version: %d", version), Protocol.IPv6);
        }

        final int payloadLength = fixedHeader.getUnsignedShort(4);

        int nextHeader = fixedHeader.getByte(6);

        final Buffer extensionHeadersBuffer = Buffers.createBuffer(400);
        while (nextHeader == IPv6Packet.EXTENSION_HOP_BY_HOP ||
                nextHeader == IPv6Packet.EXTENSION_DESTINATION_OPTIONS ||
                nextHeader == IPv6Packet.EXTENSION_ROUTING ||
                nextHeader == IPv6Packet.EXTENSION_FRAGMENT ||
                nextHeader == IPv6Packet.EXTENSION_AH ||
                nextHeader == IPv6Packet.EXTENSION_ESP ||
                nextHeader == IPv6Packet.EXTENSION_MOBILITY) {
            nextHeader = accumulateNextHeader(nextHeader, payload, extensionHeadersBuffer);
        }
        // TODO: extract actual PayloadLength from Hop-by-Hop extension header, if present


        // Trim off any padding from the upper layer, e.g. Ethernet padding for small packets.
        // If the captured frame was truncated, then use the truncated size for the data buffer, instead of what the
        // IPv6 header says its length should be.
        final int totalLength = IPv6PacketImpl.FIXED_HEADER_LENGTH + extensionHeadersBuffer.getWriterIndex() + payloadLength;
        final Buffer data = payload.slice(Math.min(totalLength, payload.capacity()));
        return new IPv6PacketImpl(parent, Buffers.wrap(fixedHeader, extensionHeadersBuffer), nextHeader, data);
    }

    private int accumulateNextHeader(final int protocolNumber, final Buffer payload, final Buffer extensionHeadersBuffer) throws IOException, FramingException {
        final int headerExtensionLen;
        final AtomicInteger nextHeaderProtocol = new AtomicInteger();
        switch (protocolNumber) {
            case IPv6Packet.EXTENSION_HOP_BY_HOP:
            case IPv6Packet.EXTENSION_ROUTING:
            case IPv6Packet.EXTENSION_DESTINATION_OPTIONS:
                nextHeaderProtocol.set(payload.getByte(IPv6PacketImpl.FIXED_HEADER_LENGTH));
                headerExtensionLen = 8 + payload.getByte(IPv6PacketImpl.FIXED_HEADER_LENGTH + 1) * 8;
                break;
            case IPv6Packet.EXTENSION_FRAGMENT:
                nextHeaderProtocol.set(payload.getByte(IPv6PacketImpl.FIXED_HEADER_LENGTH));
                headerExtensionLen = 8;
                break;
            case IPv6Packet.EXTENSION_AH:
                nextHeaderProtocol.set(payload.getByte(IPv6PacketImpl.FIXED_HEADER_LENGTH));
                headerExtensionLen = 4 * (payload.getByte(IPv6PacketImpl.FIXED_HEADER_LENGTH + 1) + 2);
                break;
            case IPv6Packet.EXTENSION_ESP:
                // TODO figure out how length is even parsed...
                // If we can't parse the header, we have to throw, because we need to parse it to find the next header.
            default:
                throw new FramingException(String.format("Unsupported IPv6 extension header: %d", protocolNumber), Protocol.IPv6);
        }
        final Buffer tmp = payload.readBytes(headerExtensionLen);
        extensionHeadersBuffer.write(tmp.getArray());
        return nextHeaderProtocol.get();
    }

    @Override
    public boolean accept(final Buffer data) {
        // TODO Auto-generated method stub
        return false;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy