Renamed registry and packet packages
net.onrc.onos.registry.controller.* => net.onrc.onos.core.registry.*
net.onrc.onos.packet => net.onrc.onos.core.packet
Change-Id: I595e325a2c0bab709f248dde5d84ff7b6185cf8b
diff --git a/src/main/java/net/onrc/onos/core/packet/DHCP.java b/src/main/java/net/onrc/onos/core/packet/DHCP.java
new file mode 100644
index 0000000..16cc22f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/packet/DHCP.java
@@ -0,0 +1,517 @@
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson, Stanford University
+*
+* 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.onrc.onos.core.packet;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class DHCP extends BasePacket {
+ /**
+ * ------------------------------------------
+ * |op (1) | htype(1) | hlen(1) | hops(1) |
+ * ------------------------------------------
+ * | xid (4) |
+ * ------------------------------------------
+ * | secs (2) | flags (2) |
+ * ------------------------------------------
+ * | ciaddr (4) |
+ * ------------------------------------------
+ * | yiaddr (4) |
+ * ------------------------------------------
+ * | siaddr (4) |
+ * ------------------------------------------
+ * | giaddr (4) |
+ * ------------------------------------------
+ * | chaddr (16) |
+ * ------------------------------------------
+ * | sname (64) |
+ * ------------------------------------------
+ * | file (128) |
+ * ------------------------------------------
+ * | options (312) |
+ * ------------------------------------------
+ *
+ */
+ // Header + magic without options
+ public static int MIN_HEADER_LENGTH = 240;
+ public static byte OPCODE_REQUEST = 0x1;
+ public static byte OPCODE_REPLY = 0x2;
+
+ public static byte HWTYPE_ETHERNET = 0x1;
+
+ public enum DHCPOptionCode {
+ OptionCode_SubnetMask ((byte)1),
+ OptionCode_RequestedIP ((byte)50),
+ OptionCode_LeaseTime ((byte)51),
+ OptionCode_MessageType ((byte)53),
+ OptionCode_DHCPServerIp ((byte)54),
+ OptionCode_RequestedParameters ((byte)55),
+ OptionCode_RenewalTime ((byte)58),
+ OPtionCode_RebindingTime ((byte)59),
+ OptionCode_ClientID ((byte)61),
+ OptionCode_END ((byte)255);
+
+ protected byte value;
+
+ private DHCPOptionCode(byte value) {
+ this.value = value;
+ }
+
+ public byte getValue() {
+ return value;
+ }
+ }
+
+ protected byte opCode;
+ protected byte hardwareType;
+ protected byte hardwareAddressLength;
+ protected byte hops;
+ protected int transactionId;
+ protected short seconds;
+ protected short flags;
+ protected int clientIPAddress;
+ protected int yourIPAddress;
+ protected int serverIPAddress;
+ protected int gatewayIPAddress;
+ protected byte[] clientHardwareAddress;
+ protected String serverName;
+ protected String bootFileName;
+ protected List<DHCPOption> options = new ArrayList<DHCPOption>();
+
+ /**
+ * @return the opCode
+ */
+ public byte getOpCode() {
+ return opCode;
+ }
+
+ /**
+ * @param opCode the opCode to set
+ */
+ public DHCP setOpCode(byte opCode) {
+ this.opCode = opCode;
+ return this;
+ }
+
+ /**
+ * @return the hardwareType
+ */
+ public byte getHardwareType() {
+ return hardwareType;
+ }
+
+ /**
+ * @param hardwareType the hardwareType to set
+ */
+ public DHCP setHardwareType(byte hardwareType) {
+ this.hardwareType = hardwareType;
+ return this;
+ }
+
+ /**
+ * @return the hardwareAddressLength
+ */
+ public byte getHardwareAddressLength() {
+ return hardwareAddressLength;
+ }
+
+ /**
+ * @param hardwareAddressLength the hardwareAddressLength to set
+ */
+ public DHCP setHardwareAddressLength(byte hardwareAddressLength) {
+ this.hardwareAddressLength = hardwareAddressLength;
+ return this;
+ }
+
+ /**
+ * @return the hops
+ */
+ public byte getHops() {
+ return hops;
+ }
+
+ /**
+ * @param hops the hops to set
+ */
+ public DHCP setHops(byte hops) {
+ this.hops = hops;
+ return this;
+ }
+
+ /**
+ * @return the transactionId
+ */
+ public int getTransactionId() {
+ return transactionId;
+ }
+
+ /**
+ * @param transactionId the transactionId to set
+ */
+ public DHCP setTransactionId(int transactionId) {
+ this.transactionId = transactionId;
+ return this;
+ }
+
+ /**
+ * @return the seconds
+ */
+ public short getSeconds() {
+ return seconds;
+ }
+
+ /**
+ * @param seconds the seconds to set
+ */
+ public DHCP setSeconds(short seconds) {
+ this.seconds = seconds;
+ return this;
+ }
+
+ /**
+ * @return the flags
+ */
+ public short getFlags() {
+ return flags;
+ }
+
+ /**
+ * @param flags the flags to set
+ */
+ public DHCP setFlags(short flags) {
+ this.flags = flags;
+ return this;
+ }
+
+ /**
+ * @return the clientIPAddress
+ */
+ public int getClientIPAddress() {
+ return clientIPAddress;
+ }
+
+ /**
+ * @param clientIPAddress the clientIPAddress to set
+ */
+ public DHCP setClientIPAddress(int clientIPAddress) {
+ this.clientIPAddress = clientIPAddress;
+ return this;
+ }
+
+ /**
+ * @return the yourIPAddress
+ */
+ public int getYourIPAddress() {
+ return yourIPAddress;
+ }
+
+ /**
+ * @param yourIPAddress the yourIPAddress to set
+ */
+ public DHCP setYourIPAddress(int yourIPAddress) {
+ this.yourIPAddress = yourIPAddress;
+ return this;
+ }
+
+ /**
+ * @return the serverIPAddress
+ */
+ public int getServerIPAddress() {
+ return serverIPAddress;
+ }
+
+ /**
+ * @param serverIPAddress the serverIPAddress to set
+ */
+ public DHCP setServerIPAddress(int serverIPAddress) {
+ this.serverIPAddress = serverIPAddress;
+ return this;
+ }
+
+ /**
+ * @return the gatewayIPAddress
+ */
+ public int getGatewayIPAddress() {
+ return gatewayIPAddress;
+ }
+
+ /**
+ * @param gatewayIPAddress the gatewayIPAddress to set
+ */
+ public DHCP setGatewayIPAddress(int gatewayIPAddress) {
+ this.gatewayIPAddress = gatewayIPAddress;
+ return this;
+ }
+
+ /**
+ * @return the clientHardwareAddress
+ */
+ public byte[] getClientHardwareAddress() {
+ return clientHardwareAddress;
+ }
+
+ /**
+ * @param clientHardwareAddress the clientHardwareAddress to set
+ */
+ public DHCP setClientHardwareAddress(byte[] clientHardwareAddress) {
+ this.clientHardwareAddress = clientHardwareAddress;
+ return this;
+ }
+
+ /**
+ * Gets a specific DHCP option parameter
+ * @param opetionCode The option code to get
+ * @return The value of the option if it exists, null otherwise
+ */
+ public DHCPOption getOption(DHCPOptionCode optionCode) {
+ for (DHCPOption opt : options) {
+ if (opt.code == optionCode.value)
+ return opt;
+ }
+ return null;
+ }
+
+ /**
+ * @return the options
+ */
+ public List<DHCPOption> getOptions() {
+ return options;
+ }
+
+ /**
+ * @param options the options to set
+ */
+ public DHCP setOptions(List<DHCPOption> options) {
+ this.options = options;
+ return this;
+ }
+
+ /**
+ * @return the packetType base on option 53
+ */
+ public DHCPPacketType getPacketType() {
+ ListIterator<DHCPOption> lit = options.listIterator();
+ while (lit.hasNext()) {
+ DHCPOption option = lit.next();
+ // only care option 53
+ if (option.getCode() == 53) {
+ return DHCPPacketType.getType(option.getData()[0]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return the serverName
+ */
+ public String getServerName() {
+ return serverName;
+ }
+
+ /**
+ * @param serverName the serverName to set
+ */
+ public DHCP setServerName(String serverName) {
+ this.serverName = serverName;
+ return this;
+ }
+
+ /**
+ * @return the bootFileName
+ */
+ public String getBootFileName() {
+ return bootFileName;
+ }
+
+ /**
+ * @param bootFileName the bootFileName to set
+ */
+ public DHCP setBootFileName(String bootFileName) {
+ this.bootFileName = bootFileName;
+ return this;
+ }
+
+ @Override
+ public byte[] serialize() {
+ // not guaranteed to retain length/exact format
+ resetChecksum();
+
+ // minimum size 240 including magic cookie, options generally padded to 300
+ int optionsLength = 0;
+ for (DHCPOption option : this.options) {
+ if (option.getCode() == 0 || option.getCode() == 255) {
+ optionsLength += 1;
+ } else {
+ optionsLength += 2 + (int)(0xff & option.getLength());
+ }
+ }
+ int optionsPadLength = 0;
+ if (optionsLength < 60)
+ optionsPadLength = 60 - optionsLength;
+
+ byte[] data = new byte[240+optionsLength+optionsPadLength];
+ ByteBuffer bb = ByteBuffer.wrap(data);
+ bb.put(this.opCode);
+ bb.put(this.hardwareType);
+ bb.put(this.hardwareAddressLength);
+ bb.put(this.hops);
+ bb.putInt(this.transactionId);
+ bb.putShort(this.seconds);
+ bb.putShort(this.flags);
+ bb.putInt(this.clientIPAddress);
+ bb.putInt(this.yourIPAddress);
+ bb.putInt(this.serverIPAddress);
+ bb.putInt(this.gatewayIPAddress);
+ bb.put(this.clientHardwareAddress);
+ if (this.clientHardwareAddress.length < 16) {
+ for (int i = 0; i < (16 - this.clientHardwareAddress.length); ++i) {
+ bb.put((byte) 0x0);
+ }
+ }
+ writeString(this.serverName, bb, 64);
+ writeString(this.bootFileName, bb, 128);
+ // magic cookie
+ bb.put((byte) 0x63);
+ bb.put((byte) 0x82);
+ bb.put((byte) 0x53);
+ bb.put((byte) 0x63);
+ for (DHCPOption option : this.options) {
+ int code = option.getCode() & 0xff;
+ bb.put((byte) code);
+ if ((code != 0) && (code != 255)) {
+ bb.put(option.getLength());
+ bb.put(option.getData());
+ }
+ }
+ // assume the rest is padded out with zeroes
+ return data;
+ }
+
+ protected void writeString(String string, ByteBuffer bb, int maxLength) {
+ if (string == null) {
+ for (int i = 0; i < maxLength; ++i) {
+ bb.put((byte) 0x0);
+ }
+ } else {
+ byte[] bytes = null;
+ try {
+ bytes = string.getBytes("ascii");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("Failure encoding server name", e);
+ }
+ int writeLength = bytes.length;
+ if (writeLength > maxLength) {
+ writeLength = maxLength;
+ }
+ bb.put(bytes, 0, writeLength);
+ for (int i = writeLength; i < maxLength; ++i) {
+ bb.put((byte) 0x0);
+ }
+ }
+ }
+
+ @Override
+ public IPacket deserialize(byte[] data, int offset, int length) {
+ ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+ if (bb.remaining() < MIN_HEADER_LENGTH) {
+ return this;
+ }
+
+ this.opCode = bb.get();
+ this.hardwareType = bb.get();
+ this.hardwareAddressLength = bb.get();
+ this.hops = bb.get();
+ this.transactionId = bb.getInt();
+ this.seconds = bb.getShort();
+ this.flags = bb.getShort();
+ this.clientIPAddress = bb.getInt();
+ this.yourIPAddress = bb.getInt();
+ this.serverIPAddress = bb.getInt();
+ this.gatewayIPAddress = bb.getInt();
+ int hardwareAddressLength = 0xff & this.hardwareAddressLength;
+ this.clientHardwareAddress = new byte[hardwareAddressLength];
+
+ bb.get(this.clientHardwareAddress);
+ for (int i = hardwareAddressLength; i < 16; ++i)
+ bb.get();
+ this.serverName = readString(bb, 64);
+ this.bootFileName = readString(bb, 128);
+ // read the magic cookie
+ // magic cookie
+ bb.get();
+ bb.get();
+ bb.get();
+ bb.get();
+ // read options
+ while (bb.hasRemaining()) {
+ DHCPOption option = new DHCPOption();
+ int code = 0xff & bb.get(); // convert signed byte to int in range [0,255]
+ option.setCode((byte) code);
+ if (code == 0) {
+ // skip these
+ continue;
+ } else if (code != 255) {
+ if (bb.hasRemaining()) {
+ int l = 0xff & bb.get(); // convert signed byte to int in range [0,255]
+ option.setLength((byte) l);
+ if (bb.remaining() >= l) {
+ byte[] optionData = new byte[l];
+ bb.get(optionData);
+ option.setData(optionData);
+ } else {
+ // Skip the invalid option and set the END option
+ code = 0xff;
+ option.setCode((byte)code);
+ option.setLength((byte) 0);
+ }
+ } else {
+ // Skip the invalid option and set the END option
+ code = 0xff;
+ option.setCode((byte)code);
+ option.setLength((byte) 0);
+ }
+ }
+ this.options.add(option);
+ if (code == 255) {
+ // remaining bytes are supposed to be 0, but ignore them just in case
+ break;
+ }
+ }
+
+ return this;
+ }
+
+ protected String readString(ByteBuffer bb, int maxLength) {
+ byte[] bytes = new byte[maxLength];
+ bb.get(bytes);
+ String result = null;
+ try {
+ result = new String(bytes, "ascii").trim();
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("Failure decoding string", e);
+ }
+ return result;
+ }
+}