/* * Copyright 2010 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.pcap.decoder.ethernet; import java.io.IOException; import java.net.InetAddress; import org.krakenapps.pcap.Injectable; import org.krakenapps.pcap.PacketBuilder; import org.krakenapps.pcap.live.PcapDeviceManager; import org.krakenapps.pcap.live.PcapDeviceMetadata; import org.krakenapps.pcap.packet.PcapPacket; import org.krakenapps.pcap.util.Arping; import org.krakenapps.pcap.util.Buffer; import org.krakenapps.pcap.util.ChainBuffer; /** * Ethernet frame * * @author mindori */ public class EthernetFrame implements Injectable { private final EthernetHeader header; private final Buffer payload; private PcapPacket pcapPacket; public EthernetFrame(MacAddress source, MacAddress destination, int type, Buffer payload) { this.header = new EthernetHeader(source, destination, type); this.payload = payload; } public EthernetFrame(EthernetHeader header, Buffer payload) { this.header = header; this.payload = payload; } public EthernetFrame(EthernetFrame other) { // copy constructor this.header = other.header; this.payload = other.payload; } public PcapPacket getPcapPacket() { return pcapPacket; } public void setPcapPacket(PcapPacket pcapPacket) { this.pcapPacket = pcapPacket; } public MacAddress getDestination() { return header.getDestination(); } public MacAddress getSource() { return header.getSource(); } public int getType() { return header.getType(); } public Buffer getData() { return payload; } public EthernetFrame dup() { ChainBuffer buf = new ChainBuffer(); buf.addLast(payload); EthernetFrame f = new EthernetFrame(this.getSource(), this.getDestination(), this.getType(), buf); f.setPcapPacket(pcapPacket); return f; } @Override public String toString() { return String.format("ethernet {dst: %s, src: %s, type: 0x%X}", getDestination(), getSource(), getType()); } @Override public Buffer getBuffer() { Buffer buf = new ChainBuffer(); buf.addLast(header.getBuffer()); buf.addLast(payload); return buf; } public static class Builder implements PacketBuilder { private MacAddress dstMac; private MacAddress srcMac; private Integer type; private Buffer data; private PacketBuilder nextBuilder; public Builder dst(MacAddress dst) { this.dstMac = dst; return this; } public Builder src(MacAddress src) { this.srcMac = src; return this; } public Builder type(int type) { this.type = type; return this; } public Builder data(PacketBuilder builder) { this.nextBuilder = builder; return this; } public Builder data(Buffer data) { this.data = data; return this; } @Override public Injectable build() { // resolve InetAddress dstIp = (InetAddress) getDefault("dst_ip"); if (dstMac == null && getDefault("dst_mac") == null) { if (dstIp == null) throw new IllegalStateException("destination ip not found"); try { this.dstMac = Arping.query(dstIp, 1000); if (dstMac == null) throw new IllegalStateException("destination mac not resolved, arping timeout"); } catch (IOException e) { throw new IllegalStateException("destination mac not found"); } } if (srcMac == null) { PcapDeviceMetadata metadata = PcapDeviceManager.getDeviceMetadata(dstIp); srcMac = metadata.getMacAddress(); } if (type == null) { type = (Integer) getDefault("eth_type"); if (type == null) throw new IllegalStateException("ether type not found"); } Buffer buffer = data; if (buffer == null) buffer = nextBuilder.build().getBuffer(); return new EthernetFrame(srcMac, dstMac, type, buffer); } @Override public Object getDefault(String name) { if (name.equals("src_mac")) return srcMac; if (name.equals("dst_mac")) return dstMac; if (nextBuilder != null) return nextBuilder.getDefault(name); return null; } } }