diff --git a/src/main/java/net/floodlightcontroller/packet/ARP.java b/src/main/java/net/floodlightcontroller/packet/ARP.java index e8428ead22fa27697a254ee3c7ce4bda3694a2dd..bf3f49385f440f8ed07571c38d341b13ab19e080 100644 --- a/src/main/java/net/floodlightcontroller/packet/ARP.java +++ b/src/main/java/net/floodlightcontroller/packet/ARP.java @@ -225,12 +225,23 @@ public class ARP extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.hardwareType = bb.getShort(); this.protocolType = bb.getShort(); this.hardwareAddressLength = bb.get(); this.protocolAddressLength = bb.get(); + if (this.hardwareAddressLength != 6) { + String msg = "Incorrect ARP hardware address length: " + + hardwareAddressLength; + throw new PacketParsingException(msg); + } + if (this.protocolAddressLength != 4) { + String msg = "Incorrect ARP protocol address length: " + + protocolAddressLength; + throw new PacketParsingException(msg); + } this.opCode = bb.getShort(); this.senderHardwareAddress = new byte[0xff & this.hardwareAddressLength]; bb.get(this.senderHardwareAddress, 0, this.senderHardwareAddress.length); diff --git a/src/main/java/net/floodlightcontroller/packet/BSN.java b/src/main/java/net/floodlightcontroller/packet/BSN.java index 27c8f70df69cce5896f66a5d64522a2bc1c9f654..676f54d48199b3734969171633247f6beddc4431 100644 --- a/src/main/java/net/floodlightcontroller/packet/BSN.java +++ b/src/main/java/net/floodlightcontroller/packet/BSN.java @@ -1,6 +1,6 @@ /** -* Copyright 2012, Big Switch Networks, Inc. -* +* Copyright 2012, Big Switch Networks, Inc. +* * 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 @@ -15,7 +15,7 @@ **/ /** - * + * */ package net.floodlightcontroller.packet; @@ -28,66 +28,66 @@ import java.util.Map; * */ public class BSN extends BasePacket { - public static final int BSN_MAGIC = 0x20000604; - public static final short BSN_VERSION_CURRENT = 0x0; - public static final short BSN_TYPE_PROBE = 0x1; - public static final short BSN_TYPE_BDDP = 0x2; - public static Map<Short, Class<? extends IPacket>> typeClassMap; - + public static final int BSN_MAGIC = 0x20000604; + public static final short BSN_VERSION_CURRENT = 0x0; + public static final short BSN_TYPE_PROBE = 0x1; + public static final short BSN_TYPE_BDDP = 0x2; + public static Map<Short, Class<? extends IPacket>> typeClassMap; + static { typeClassMap = new HashMap<Short, Class<? extends IPacket>>(); typeClassMap.put(BSN_TYPE_PROBE, BSNPROBE.class); typeClassMap.put(BSN_TYPE_BDDP, LLDP.class); } - protected short type; - protected short version; + protected short type; + protected short version; + + public BSN() { + version = BSN_VERSION_CURRENT; + } - public BSN() { - version = BSN_VERSION_CURRENT; - } - public BSN(short type) { - this.type = type; - version = BSN_VERSION_CURRENT; + this.type = type; + version = BSN_VERSION_CURRENT; } public short getType() { - return type; - } - - public BSN setType(short type) { - this.type = type; - return this; - } - + return type; + } + + public BSN setType(short type) { + this.type = type; + return this; + } + public short getVersion() { - return version; - } + return version; + } - public BSN setVersion(short version) { - this.version = version; - return this; - } + public BSN setVersion(short version) { + this.version = version; + return this; + } @Override public byte[] serialize() { - short length = 4 /* magic */ + 2 /* type */ + 2 /* version */; - - byte[] payloadData = null; - if (this.payload != null) { + short length = 4 /* magic */ + 2 /* type */ + 2 /* version */; + + byte[] payloadData = null; + if (this.payload != null) { payload.setParent(this); payloadData = payload.serialize(); length += payloadData.length; } - + byte[] data = new byte[length]; ByteBuffer bb = ByteBuffer.wrap(data); bb.putInt(BSN_MAGIC); bb.putShort(this.type); bb.putShort(this.version); if (payloadData != null) - bb.put(payloadData); + bb.put(payloadData); if (this.parent != null && this.parent instanceof Ethernet) ((Ethernet)this.parent).setEtherType(Ethernet.TYPE_BSN); @@ -96,22 +96,23 @@ public class BSN extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); - + int magic = bb.getInt(); if (magic != BSN_MAGIC) { - throw new RuntimeException("Invalid BSN magic " + magic); + throw new PacketParsingException("Invalid BSN magic " + magic); } - + this.type = bb.getShort(); this.version = bb.getShort(); if (this.version != BSN_VERSION_CURRENT) { - throw new RuntimeException( - "Invalid BSN packet version " + this.version + ", should be " - + BSN_VERSION_CURRENT); + throw new PacketParsingException( + "Invalid BSN packet version " + this.version + ", should be " + + BSN_VERSION_CURRENT); } - + IPacket payload; if (typeClassMap.containsKey(this.type)) { Class<? extends IPacket> clazz = typeClassMap.get(this.type); @@ -123,11 +124,10 @@ public class BSN extends BasePacket { } else { payload = new Data(); } - - this.payload = new Data(); + this.payload = payload.deserialize(data, bb.position(), bb.limit() - bb.position()); this.payload.setParent(this); - + return this; } @@ -156,17 +156,17 @@ public class BSN extends BasePacket { return false; BSN other = (BSN) obj; return (type == other.type && - version == other.version); + version == other.version); } - + public String toString() { - StringBuffer sb = new StringBuffer("\n"); - sb.append("BSN packet"); + StringBuffer sb = new StringBuffer("\n"); + sb.append("BSN packet"); if (typeClassMap.containsKey(this.type)) - sb.append(" type: " + typeClassMap.get(this.type).getCanonicalName()); + sb.append(" type: " + typeClassMap.get(this.type).getCanonicalName()); else - sb.append(" type: " + this.type); - - return sb.toString(); + sb.append(" type: " + this.type); + + return sb.toString(); } } diff --git a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java index 1343f769b86f45399f33357ff3932092007c562c..c9115eacb5c22c459cbaded572a64063125118c6 100644 --- a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java +++ b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java @@ -125,7 +125,8 @@ public class BSNPROBE extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); controllerId = bb.getLong(); diff --git a/src/main/java/net/floodlightcontroller/packet/BasePacket.java b/src/main/java/net/floodlightcontroller/packet/BasePacket.java index eed530c03d2e8047774697bc70032d58eee63981..9ed2871aaee86322680f039b0babba5483e4bbd5 100644 --- a/src/main/java/net/floodlightcontroller/packet/BasePacket.java +++ b/src/main/java/net/floodlightcontroller/packet/BasePacket.java @@ -113,7 +113,12 @@ public abstract class BasePacket implements IPacket { // cloning. Not the most efficient way but simple. We can revisit // if we hit performance problems. byte[] data = this.serialize(); - pkt.deserialize(this.serialize(), 0, data.length); + try { + pkt.deserialize(this.serialize(), 0, data.length); + } catch (PacketParsingException e) { + // This shouldn't happen here, since we already deserialized it once + return new Data(data); + } pkt.setParent(this.parent); return pkt; } diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java index 4fc2380762a5c71e019886cb6c0da82e6b84fc19..438e786a3459028888f1b95c6480ff052c5c5f45 100644 --- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java +++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java @@ -262,7 +262,7 @@ public class Ethernet extends BasePacket { try { payload = clazz.newInstance(); this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); - } catch (Exception e) { + } catch (PacketParsingException e) { if (log.isTraceEnabled()) { log.trace("Failed to parse ethernet packet {}->{}" + " payload as {}, treat as plain ethernet packet", @@ -271,12 +271,27 @@ public class Ethernet extends BasePacket { clazz.getClass().getName()}); log.trace("Exception from parsing {}", e); } - payload = new Data(); - this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); + this.payload = new Data(data); + } catch (InstantiationException e) { + if (log.isTraceEnabled()) { + log.trace("Fail to instantiate class {}, {}", + clazz.getClass().getName(), e); + } + this.payload = new Data(data); + } catch (IllegalAccessException e) { + if (log.isTraceEnabled()) { + log.trace("Fail to access class for instantiation {}, {}", + clazz.getClass().getName(), e); + } + this.payload = new Data(data); + } catch (RuntimeException e) { + if (log.isTraceEnabled()) { + log.trace("Runtime exception during packet parsing {}", e); + } + this.payload = new Data(data); } } else { - payload = new Data(); - this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); + this.payload = new Data(data); } this.payload.setParent(this); return this; diff --git a/src/main/java/net/floodlightcontroller/packet/ICMP.java b/src/main/java/net/floodlightcontroller/packet/ICMP.java index 6b02b5bd502a5869e35a86579152417f39cd0698..2988106484530d437df2b5fe62aac2c0a0bea480 100644 --- a/src/main/java/net/floodlightcontroller/packet/ICMP.java +++ b/src/main/java/net/floodlightcontroller/packet/ICMP.java @@ -184,7 +184,8 @@ public class ICMP extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.icmpType = bb.get(); this.icmpCode = bb.get(); diff --git a/src/main/java/net/floodlightcontroller/packet/IPacket.java b/src/main/java/net/floodlightcontroller/packet/IPacket.java index 02376cd990cbd1c1980b78bb7815323a46480cf2..4eaaada8e243c072a7a33c48c46fc9d2b1d6ea72 100644 --- a/src/main/java/net/floodlightcontroller/packet/IPacket.java +++ b/src/main/java/net/floodlightcontroller/packet/IPacket.java @@ -67,7 +67,8 @@ public interface IPacket { * @param length length of the data to deserialize * @return the deserialized data */ - public IPacket deserialize(byte[] data, int offset, int length); + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException; /** Clone this packet and its payload packet but not its parent. * diff --git a/src/main/java/net/floodlightcontroller/packet/IPv4.java b/src/main/java/net/floodlightcontroller/packet/IPv4.java index 327ef7fac9891833e41244d868e2614d15d18770..61d9730ba2040dd330e951f574b7c8471dcc051b 100644 --- a/src/main/java/net/floodlightcontroller/packet/IPv4.java +++ b/src/main/java/net/floodlightcontroller/packet/IPv4.java @@ -353,7 +353,8 @@ public class IPv4 extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); short sscratch; @@ -361,7 +362,8 @@ public class IPv4 extends BasePacket { this.headerLength = (byte) (this.version & 0xf); this.version = (byte) ((this.version >> 4) & 0xf); if (this.version != 4) { - throw new RuntimeException("Invalid version for IPv4 packet: " + + throw new PacketParsingException( + "Invalid version for IPv4 packet: " + this.version); } this.diffServ = bb.get(); diff --git a/src/main/java/net/floodlightcontroller/packet/PacketParsingException.java b/src/main/java/net/floodlightcontroller/packet/PacketParsingException.java new file mode 100644 index 0000000000000000000000000000000000000000..f27629de8c097516045c00be22ad4ae007994efd --- /dev/null +++ b/src/main/java/net/floodlightcontroller/packet/PacketParsingException.java @@ -0,0 +1,27 @@ +/** +* Copyright 2013, Big Switch Networks, Inc. +* +* 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 net.floodlightcontroller.packet; + +public class PacketParsingException extends Exception { + + public PacketParsingException(String msg) { + super(msg); + } + + private static final long serialVersionUID = -1177841297678875573L; + +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/packet/TCP.java b/src/main/java/net/floodlightcontroller/packet/TCP.java index 5c2f0294696351152a59701c412858b0dbde5c71..6af5932a55c15d9e4b5729ff6eac8998c9dc16eb 100644 --- a/src/main/java/net/floodlightcontroller/packet/TCP.java +++ b/src/main/java/net/floodlightcontroller/packet/TCP.java @@ -258,7 +258,8 @@ public class TCP extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.sourcePort = bb.getShort(); this.destinationPort = bb.getShort(); @@ -267,7 +268,7 @@ public class TCP extends BasePacket { this.flags = bb.getShort(); this.dataOffset = (byte) ((this.flags >> 12) & 0xf); if (this.dataOffset < 5) { - throw new RuntimeException("Invalid tcp header length < 20"); + throw new PacketParsingException("Invalid tcp header length < 20"); } this.flags = (short) (this.flags & 0x1ff); this.windowSize = bb.getShort(); diff --git a/src/main/java/net/floodlightcontroller/packet/UDP.java b/src/main/java/net/floodlightcontroller/packet/UDP.java index cbeeedfd18add16d1f657c7930cadf4bf08da6b8..710762c097137bede7a84da1fa7cd6de2a586057 100644 --- a/src/main/java/net/floodlightcontroller/packet/UDP.java +++ b/src/main/java/net/floodlightcontroller/packet/UDP.java @@ -202,7 +202,8 @@ public class UDP extends BasePacket { } @Override - public IPacket deserialize(byte[] data, int offset, int length) { + public IPacket deserialize(byte[] data, int offset, int length) + throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); this.sourcePort = bb.getShort(); this.destinationPort = bb.getShort(); diff --git a/src/test/java/net/floodlightcontroller/packet/ICMPTest.java b/src/test/java/net/floodlightcontroller/packet/ICMPTest.java index e554c4e7bc73a6093a390f7be263a56412af5b2a..fe71d9fc92b7adab0cebacc4e5c9dea05016cb59 100644 --- a/src/test/java/net/floodlightcontroller/packet/ICMPTest.java +++ b/src/test/java/net/floodlightcontroller/packet/ICMPTest.java @@ -58,7 +58,7 @@ public class ICMPTest { } @Test - public void testDeserialize() { + public void testDeserialize() throws Exception { IPacket packet = new IPv4(); packet.deserialize(pktSerialized, 0, pktSerialized.length); byte[] pktSerialized1 = packet.serialize(); diff --git a/src/test/java/net/floodlightcontroller/packet/IPv4Test.java b/src/test/java/net/floodlightcontroller/packet/IPv4Test.java index c9a86b03c73e3d7a7ba374c18f5f10c475dfbe06..9aa9e3d1093e197d4536f2cc08a475da7ed70ad2 100644 --- a/src/test/java/net/floodlightcontroller/packet/IPv4Test.java +++ b/src/test/java/net/floodlightcontroller/packet/IPv4Test.java @@ -85,7 +85,7 @@ public class IPv4Test { }; @Test - public void testDeserialize() { + public void testDeserialize() throws Exception { IPv4 packet = new IPv4(); packet.deserialize(pktSerialized, 0, pktSerialized.length); byte[] pktSerialized1 = packet.serialize(); @@ -93,7 +93,7 @@ public class IPv4Test { } @Test - public void testDeserializePadded() { + public void testDeserializePadded() throws Exception { // A real TLSv1 packet with crap added to the end byte[] pktSerializedPadded = new byte[] { 0x45, 0x00, 0x00, 0x2e, 0x41, (byte) 0xbe, 0x40, 0x00, 0x40, 0x06, @@ -112,7 +112,7 @@ public class IPv4Test { } @Test - public void testDeserializeFragment() { + public void testDeserializeFragment() throws Exception { // IP packet with more frag bit set byte[] pktSerializedFirstFrag = new byte[] { 0x45, 0x00, 0x00, 0x2e, 0x41, (byte) 0xbe, 0x20, 0x00, 0x40, 0x06, @@ -145,7 +145,7 @@ public class IPv4Test { } @Test - public void testDeserializeDontFragment() { + public void testDeserializeDontFragment() throws Exception { // IP packet with more frag bit set byte[] pktSerializedDontFrag = new byte[] { 0x45, 0x00, 0x00, 0x2e, 0x41, (byte) 0xbe, 0x60, 0x00, 0x40, 0x06, diff --git a/src/test/java/net/floodlightcontroller/packet/PacketTest.java b/src/test/java/net/floodlightcontroller/packet/PacketTest.java index b975166fafc0576306e0fdde88d740adb31d13de..c5a1bb2274b51e48a1ce5801e439d73a10b86232 100644 --- a/src/test/java/net/floodlightcontroller/packet/PacketTest.java +++ b/src/test/java/net/floodlightcontroller/packet/PacketTest.java @@ -100,7 +100,7 @@ public class PacketTest { this.packets = new IPacket[] { pkt1, pkt2, pkt3, pkt4 }; } - protected void doTestClone(IPacket pkt) { + protected void doTestClone(IPacket pkt) throws Exception { if (pkt.getPayload() != null) doTestClone(pkt.getPayload()); IPacket newPkt = (IPacket)pkt.clone(); @@ -127,16 +127,16 @@ public class PacketTest { assertEquals(false, Arrays.equals(newArp.getSenderProtocolAddress(), arp.getSenderProtocolAddress())); assertEquals(false, newPkt.equals(pkt)); + } else { + byte[] dummyData = dummyPkt.serialize().clone(); + newPkt = (IPacket)pkt.clone(); + newPkt.deserialize(dummyData, 0, dummyData.length); + assertEquals(false, newPkt.equals(pkt)); } - - byte[] dummyData = dummyPkt.serialize().clone(); - newPkt = (IPacket)pkt.clone(); - newPkt.deserialize(dummyData, 0, dummyData.length); - assertEquals(false, newPkt.equals(pkt)); } @Test - public void testClone() { + public void testClone() throws Exception { for (IPacket pkt: packets) { doTestClone(pkt); } diff --git a/src/test/java/net/floodlightcontroller/packet/TCPTest.java b/src/test/java/net/floodlightcontroller/packet/TCPTest.java index fcd5422f32e1c99f3f9ce9993953764af4ea9698..b453f972f17eff36c30fe036016dc07d066556fa 100644 --- a/src/test/java/net/floodlightcontroller/packet/TCPTest.java +++ b/src/test/java/net/floodlightcontroller/packet/TCPTest.java @@ -65,7 +65,7 @@ public class TCPTest { } @Test - public void testDeserialize() { + public void testDeserialize() throws PacketParsingException { IPacket packet = new IPv4(); packet.deserialize(pktSerialized, 0, pktSerialized.length); byte[] pktSerialized1 = packet.serialize();