/* * 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.udp; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import org.krakenapps.pcap.Injectable; import org.krakenapps.pcap.PacketBuilder; import org.krakenapps.pcap.decoder.ip.InternetProtocol; import org.krakenapps.pcap.decoder.ip.IpPacket; import org.krakenapps.pcap.live.PcapDeviceManager; import org.krakenapps.pcap.live.PcapDeviceMetadata; import org.krakenapps.pcap.util.Buffer; import org.krakenapps.pcap.util.ChainBuffer; /** * @author mindori */ public class UdpPacket implements Injectable { private IpPacket ipPacket; private InetSocketAddress source; private InetSocketAddress destination; private int length; private int checksum; private Buffer data; private UdpPacket() { } public UdpPacket(IpPacket ipPacket, int sourcePort, int destinationPort) { this(ipPacket.getSourceAddress(), sourcePort, ipPacket.getDestinationAddress(), destinationPort); this.ipPacket = ipPacket; } public UdpPacket(InetAddress sourceIp, int sourcePort, InetAddress destinationIp, int destinationPort) { this.source = new InetSocketAddress(sourceIp, sourcePort); this.destination = new InetSocketAddress(destinationIp, destinationPort); } /* copy constructor */ public UdpPacket(UdpPacket other) { ipPacket = other.getIpPacket(); source = other.getSource(); destination = other.getDestination(); length = other.getLength(); checksum = other.getChecksum(); data = new ChainBuffer(other.getData()); } public IpPacket getIpPacket() { return ipPacket; } public InetSocketAddress getSource() { return source; } public InetSocketAddress getDestination() { return destination; } public int getSourcePort() { return source.getPort(); } public int getDestinationPort() { return destination.getPort(); } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public int getChecksum() { return checksum; } public void setChecksum(int checksum) { this.checksum = checksum; } public Buffer getData() { return data; } public void setData(Buffer data) { this.data = data; } @Override public Buffer getBuffer() { ByteBuffer hbuf = ByteBuffer.allocate(8); hbuf.putShort((short) source.getPort()); hbuf.putShort((short) destination.getPort()); hbuf.putShort((short) length); hbuf.putShort((short) checksum); Buffer buf = new ChainBuffer(hbuf.array()); buf.addLast(data); return buf; } @Override public String toString() { return String.format("udp {%s:%d > %s:%d - length: %d, checksum: 0x%02x}", source.getAddress().getHostAddress(), source.getPort(), destination.getAddress().getHostAddress(), destination.getPort(), length, checksum); } public static class Builder implements PacketBuilder { private InetAddress srcIp; private InetAddress dstIp; private Integer srcPort; private Integer dstPort; private Buffer data; private PacketBuilder nextBuilder; public Builder src(InetSocketAddress addr) { return src(addr.getAddress(), addr.getPort()); } public Builder src(String ip, int port) { try { return src(InetAddress.getByName(ip), port); } catch (UnknownHostException e) { throw new IllegalArgumentException("invalid ip format"); } } public Builder src(InetAddress ip, int port) { this.srcIp = ip; this.srcPort = port; return this; } public Builder dst(InetSocketAddress addr) { return dst(addr.getAddress(), addr.getPort()); } public Builder dst(String ip, int port) { try { return dst(InetAddress.getByName(ip), port); } catch (UnknownHostException e) { throw new IllegalArgumentException("invalid ip format"); } } public Builder dst(InetAddress ip, int port) { this.dstIp = ip; this.dstPort = port; return this; } public Builder data(Buffer data) { this.data = data; return this; } public Builder data(PacketBuilder builder) { this.nextBuilder = builder; return this; } @Override public Injectable build() { // resolve all values if (dstIp == null) throw new IllegalStateException("destination ip not found"); if (srcIp == null) { PcapDeviceMetadata metadata = PcapDeviceManager.getDeviceMetadata(dstIp); if (metadata == null) throw new IllegalArgumentException("route not found for destination " + dstIp.getHostAddress()); srcIp = metadata.getInet4Address(); } if (srcPort == null) srcPort = 40000; if (dstPort == null) throw new IllegalStateException("destination port not found"); UdpPacket p = new UdpPacket(); p.source = new InetSocketAddress(srcIp, srcPort); p.destination = new InetSocketAddress(dstIp, dstPort); p.length = data.readableBytes() + 8; p.data = data; p.checksum = UdpChecksum.sum(p); return p; } @Override public Object getDefault(String name) { if (name.equals("src_ip")) return srcIp; if (name.equals("dst_ip")) return dstIp; if (name.equals("ip_proto")) return InternetProtocol.UDP; if (name.equals("src_port")) return srcPort; if (name.equals("dst_port")) return dstPort; if (nextBuilder != null) return nextBuilder.getDefault(name); return null; } } }