2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.dhcpservice.api;
11 import static org.opendaylight.netvirt.dhcpservice.api.DHCPConstants.OPT_END;
12 import static org.opendaylight.netvirt.dhcpservice.api.DHCPConstants.OPT_PAD;
14 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import java.net.InetAddress;
16 import java.net.UnknownHostException;
17 import java.nio.charset.StandardCharsets;
18 import java.util.LinkedHashMap;
19 import java.util.List;
20 import org.apache.commons.lang3.ArrayUtils;
21 import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
22 import org.opendaylight.openflowplugin.libraries.liblldp.NetUtils;
24 public class DHCPOptions {
26 private static class DhcpOption {
31 DhcpOption(byte code, byte[] value) {
32 if (code != OPT_PAD && code != OPT_END && value != null) {
35 this.length = (byte) value.length;
39 public byte getCode() {
43 public byte[] getValue() {
47 public byte[] serialize() {
48 byte[] opt1 = new byte[2];
50 opt1[1] = this.length;
51 return ArrayUtils.addAll(opt1, this.value);
55 public String toString() {
56 StringBuilder sb = new StringBuilder();
58 .append("code: ").append(this.code)
59 .append(", len: ").append(this.length)
60 .append(", value: 0x").append(HexEncode.bytesToHexString(this.value))
66 private final LinkedHashMap<Byte, DhcpOption> options;
68 public DHCPOptions() {
69 options = new LinkedHashMap<>();
72 private DhcpOption getOption(byte code) {
73 return this.options.get(code);
76 private void setOption(DhcpOption opt) {
77 this.options.put(opt.getCode(), opt);
80 public void setOption(byte code, byte[] opt) {
81 this.setOption(new DhcpOption(code, opt));
84 // It's unclear from all the callers if returning an empty array would be safe.
85 @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
86 public byte[] getOptionBytes(byte code) {
87 DhcpOption option = this.getOption(code);
88 return option != null ? option.getValue() : null;
91 public void setOptionByte(byte code, byte opt) {
92 this.setOption(new DhcpOption(code, DHCPUtils.byteToByteArray(opt)));
95 public byte getOptionByte(byte code) {
96 return this.getOption(code).getValue()[0];
99 public void setOptionShort(byte code, short opt) {
100 this.setOption(new DhcpOption(code, DHCPUtils.shortToByteArray(opt)));
103 public short getOptionShort(byte code) {
104 byte[] opt = this.getOptionBytes(code);
105 return DHCPUtils.byteArrayToShort(opt);
108 public void setOptionInt(byte code, int opt) {
109 this.setOption(new DhcpOption(code, DHCPUtils.intToByteArray(opt)));
112 public int getOptionInt(byte code) {
113 byte[] opt = this.getOptionBytes(code);
114 return NetUtils.byteArray4ToInt(opt);
117 public void setOptionInetAddr(byte code, InetAddress opt) {
118 this.setOption(new DhcpOption(code, DHCPUtils.inetAddrToByteArray(opt)));
121 public InetAddress getOptionInetAddr(byte code) {
122 byte[] opt = this.getOptionBytes(code);
124 return InetAddress.getByAddress(opt);
125 } catch (UnknownHostException | NullPointerException e) {
130 public void setOptionStrAddr(byte code, String opt) throws UnknownHostException {
131 this.setOption(new DhcpOption(code, DHCPUtils.strAddrToByteArray(opt)));
134 public String getOptionStrAddr(byte code) {
135 byte[] opt = this.getOptionBytes(code);
137 return InetAddress.getByAddress(opt).getHostAddress();
138 } catch (UnknownHostException | NullPointerException e) {
143 public void setOptionStrAddrs(byte code, List<String> addrs) throws UnknownHostException {
144 if (!addrs.isEmpty()) {
145 this.setOption(new DhcpOption(code, DHCPUtils.strListAddrsToByteArray(addrs)));
149 public void setOptionString(byte code, String str) {
150 this.setOption(new DhcpOption(code, str.getBytes(StandardCharsets.UTF_8)));
153 public byte[] serialize() {
154 byte[] serializedOptions = new byte[0];
155 for (DhcpOption dhcpOption: this.options.values()) {
156 serializedOptions = ArrayUtils.addAll(serializedOptions, dhcpOption.serialize());
158 byte[] end = new byte[] {(byte)255};
159 serializedOptions = ArrayUtils.addAll(serializedOptions, end);
160 return serializedOptions;
163 private byte[] getOptionValArray(byte[] opt, int pos, int len) {
164 byte[] val = new byte[len];
165 for (int i = 0; i < len; i++) {
166 val[i] = opt[pos + i];
171 public void deserialize(byte[] serializedOptions) {
176 if (serializedOptions != null) {
177 while (pos < serializedOptions.length) {
178 code = serializedOptions[pos++];
179 if (code == OPT_END) {
182 len = serializedOptions[pos++];
183 if (len + pos > serializedOptions.length) {
184 // Throw exception???
187 value = getOptionValArray(serializedOptions, pos, len);
188 setOption(code, value);
195 public String toString() {
196 StringBuilder sb = new StringBuilder();
199 for (DhcpOption dhcpOption: this.options.values()) {
200 //options = ArrayUtils.addAll(options, dOpt.serialize());
201 sb.append("Option").append(count++).append(dhcpOption.toString());
204 return sb.toString();
207 public boolean containsOption(byte code) {
208 return options.containsKey(code);
211 public DhcpOption unsetOption(byte code) {
212 return options.remove(code);