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

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

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

import java.io.IOException;
import java.io.OutputStream;

import io.pkts.buffer.Buffer;
import io.pkts.frame.UnknownEtherType;
import io.pkts.packet.MACPacket;
import io.pkts.packet.PCapPacket;
import io.pkts.packet.impl.MACPacketImpl;
import io.pkts.protocol.Protocol;

/**
 * Simple framer for framing Ethernet frames
 * 
 * @author [email protected]
 */
public class EthernetFramer implements Framer {

    public EthernetFramer() {
    }

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

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

        // final Buffer destMacAddress = buffer.readBytes(6);
        // final Buffer srcMacAddress = buffer.readBytes(6);
        // final byte b1 = buffer.readByte();
        // final byte b2 = buffer.readByte();

        if (buffer.getReadableBytes() < 14) {
            throw new FramingException("not enough bytes for header", getProtocol());
        }
        Buffer headers;
        try {
            EtherType etherType = getEtherType(buffer.getByte(12), buffer.getByte(13));
            if (etherType == EtherType.Dot1Q) {
                getEtherType(buffer.getByte(16), buffer.getByte(17));
                headers = buffer.readBytes(18);
            } else {
                headers = buffer.readBytes(14);
            }
        } catch (IndexOutOfBoundsException e) {
            throw new FramingException("not enough bytes for header", getProtocol());
        } catch (final UnknownEtherType e) {
            throw new FramingException(String.format("unknown ether type: 0x%02x%02x", e.getB1(), e.getB2()), getProtocol());
        }

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

    public static EtherType getEtherType(final byte b1, final byte b2) throws UnknownEtherType {
        final EtherType type = getEtherTypeSafe(b1, b2);
        if (type != null) {
            return type;
        }

        // will implement as we need to
        throw new UnknownEtherType(b1, b2);
    }

    public static EtherType getEtherTypeSafe(final byte b1, final byte b2) {
        int type = ((b1 << 8) & 0xFF00) | (b2 & 0xFF);
        if (type < 1536) {
            return EtherType.None;
        }
        for (EtherType t: EtherType.values()) {
          if (b1 == t.b1 && b2 == t.b2) {
              return t;
          }
        }

        return null;
    }

    @Override
    public boolean accept(final Buffer data) {
        return false;
    }

    public enum EtherType {
        IPv4((byte) 0x08, (byte) 0x00),
        ARP((byte) 0x08, (byte) 0x06),
        IPv6((byte) 0x86, (byte) 0xdd),
        LLDP((byte) 0x88, (byte) 0xcc),
        EAPOL((byte) 0x88, (byte) 0x8e),
        // Representing EtherType < 1536, which is actually a length of the frame and not a meaningful type
        None((byte) 0x00, (byte) 0x00),
        Dot1Q((byte) 0x81, (byte) 0x00)
        ;

        private final byte b1;
        private final byte b2;

        EtherType(final byte b1, final byte b2) {
            this.b1 = b1;
            this.b2 = b2;
        }

        public byte getB1() {
            return b1;
        }

        public byte getB2() {
            return b2;
        }

        public void write(final OutputStream out) throws IOException {
            out.write(this.b1);
            out.write(this.b2);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy