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

io.pkts.framer.SllFramer 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.packet.MACPacket;
import io.pkts.packet.PCapPacket;
import io.pkts.packet.impl.MACPacketImpl;
import io.pkts.protocol.Protocol;

import java.io.IOException;

/**
 * SLL is the linux cooked-mode capture.
 * 
 * http://wiki.wireshark.org/SLL
 * 
 * Also, check out the source file pcap/sll.h in libpcap. it contains the
 * structure and the defined values
 * 
 * @author [email protected]
 */
public class SllFramer implements Framer {

    /**
     * See pcap/sll.h for the meaning of these values
     */
    private static final byte LINUX_SLL_HOST = (byte) 0x00;
    private static final byte LINUX_SLL_BROADCAST = (byte) 0x01;
    private static final byte LINUX_SLL_MULTICAST = (byte) 0x02;
    private static final byte LINUX_SLL_OTHERHOST = (byte) 0x03;
    private static final byte LINUX_SLL_OUTGOING = (byte) 0x04;

    /**
     * See pcap/sll.h for explanation of what this is. Also note that these
     * values are actually two bytes starting with 0x00 but I left that out
     * here.
     * 
     * Novell 802.3 frames without 802.2 LLC header
     * 
     */
    private static final byte LINUX_SLL_P_802_3 = (byte) 0x01;

    /**
     * 802.2 frames (not D/I/X Ethernet)
     */
    private static final byte LINUX_SLL_P_802_2 = (byte) 0x04;

    /**
     * 
     */
    public SllFramer() {
    }

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

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

        final Buffer headers = buffer.readBytes(16);
        final Buffer payload = buffer.slice(buffer.capacity());
        return new MACPacketImpl(Protocol.SLL, parent, headers, payload);
    }

    /**
     * (taken from pcap/sll.sh)
     * 
     * For captures on Linux cooked sockets, we construct a fake header that
     * includes:
     * 
     * a 2-byte "packet type" which is one of:
     * 
     * LINUX_SLL_HOST packet was sent to us LINUX_SLL_BROADCAST packet was
     * broadcast LINUX_SLL_MULTICAST packet was multicast LINUX_SLL_OTHERHOST
     * packet was sent to somebody else LINUX_SLL_OUTGOING packet was sent *by*
     * us;
     * 
     * a 2-byte Ethernet protocol field;
     * 
     * a 2-byte link-layer type;
     * 
     * a 2-byte link-layer address length;
     * 
     * an 8-byte source link-layer address, whose actual length is specified by
     * the previous value.
     * 
     * All fields except for the link-layer address are in network byte order.
     * 
     * DO NOT change the layout of this structure, or change any of the
     * LINUX_SLL_ values below. If you must change the link-layer header for a
     * "cooked" Linux capture, introduce a new DLT_ type (ask
     * "[email protected]" for one, so that you don't give it a
     * value that collides with a value already being used), and use the new
     * header in captures of that type, so that programs that can handle
     * DLT_LINUX_SLL captures will continue to handle them correctly without any
     * change, and so that capture files with different headers can be told
     * apart and programs that read them can dissect the packets in them.
     * 
     * 
     * {@inheritDoc}
     */
    @Override
    public boolean accept(final Buffer buffer) throws IOException {
        buffer.markReaderIndex();
        try {
            final Buffer test = buffer.readBytes(16);
            final byte b1 = test.getByte(0);
            final byte b2 = test.getByte(1);
            final byte b14 = test.getByte(14);
            final byte b15 = test.getByte(15);
            return validatePacketType(b1, b2) && isKnownEtherType(b14, b15);
        } catch (final IndexOutOfBoundsException e) {
            System.err.println("Strange, we are blowing up all the time...");
            return false;
        } finally {
            buffer.resetReaderIndex();
        }
    }

    private boolean isKnownEtherType(final byte b1, final byte b2) {
        return EthernetFramer.getEtherTypeSafe(b1, b2) != null;
    }

    private boolean validatePacketType(final byte b1, final byte b2) {
        if (b1 != (byte) 0x00) {
            return false;
        }

        return b2 == LINUX_SLL_HOST || b2 == LINUX_SLL_BROADCAST || b2 == LINUX_SLL_MULTICAST
                || b2 == LINUX_SLL_OTHERHOST || b2 == LINUX_SLL_OUTGOING;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy