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.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.openflowplugin.libraries.liblldp.HexEncode;
23 import org.opendaylight.openflowplugin.libraries.liblldp.NetUtils;
25 public class DHCPOptions {
27 private static class DhcpOption {
32 DhcpOption(byte code, byte[] value) {
33 if (code != OPT_PAD && code != OPT_END && value != null) {
36 this.length = (byte) value.length;
40 public byte getCode() {
44 public byte[] getValue() {
48 public byte[] serialize() {
49 byte[] opt1 = new byte[2];
51 opt1[1] = this.length;
52 return ArrayUtils.addAll(opt1, this.value);
56 public String toString() {
57 StringBuilder sb = new StringBuilder();
59 .append("code: ").append(this.code)
60 .append(", len: ").append(this.length)
61 .append(", value: 0x").append(HexEncode.bytesToHexString(this.value))
67 private final LinkedHashMap<Byte, DhcpOption> options;
69 public DHCPOptions() {
70 options = new LinkedHashMap<>();
73 private DhcpOption getOption(byte code) {
74 return this.options.get(code);
77 private void setOption(DhcpOption opt) {
78 this.options.put(opt.getCode(), opt);
81 public void setOption(byte code, byte[] opt) {
82 this.setOption(new DhcpOption(code, opt));
85 // It's unclear from all the callers if returning an empty array would be safe.
86 @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
88 public byte[] getOptionBytes(byte code) {
89 DhcpOption option = this.getOption(code);
90 return option != null ? option.getValue() : null;
93 public void setOptionByte(byte code, byte opt) {
94 this.setOption(new DhcpOption(code, DHCPUtils.byteToByteArray(opt)));
97 public byte getOptionByte(byte code) {
98 return this.getOption(code).getValue()[0];
101 public void setOptionShort(byte code, short opt) {
102 this.setOption(new DhcpOption(code, DHCPUtils.shortToByteArray(opt)));
105 public short getOptionShort(byte code) {
106 byte[] opt = this.getOptionBytes(code);
107 return DHCPUtils.byteArrayToShort(opt);
110 public void setOptionInt(byte code, int opt) {
111 this.setOption(new DhcpOption(code, DHCPUtils.intToByteArray(opt)));
114 public int getOptionInt(byte code) {
115 byte[] opt = this.getOptionBytes(code);
116 return NetUtils.byteArray4ToInt(opt);
119 public void setOptionInetAddr(byte code, InetAddress opt) {
120 this.setOption(new DhcpOption(code, DHCPUtils.inetAddrToByteArray(opt)));
124 public InetAddress getOptionInetAddr(byte code) {
125 byte[] opt = this.getOptionBytes(code);
127 return InetAddress.getByAddress(opt);
128 } catch (UnknownHostException | NullPointerException e) {
133 public void setOptionStrAddr(byte code, String opt) throws UnknownHostException {
134 this.setOption(new DhcpOption(code, DHCPUtils.strAddrToByteArray(opt)));
138 public String getOptionStrAddr(byte code) {
139 byte[] opt = this.getOptionBytes(code);
141 return InetAddress.getByAddress(opt).getHostAddress();
142 } catch (UnknownHostException | NullPointerException e) {
147 public void setOptionStrAddrs(byte code, List<String> addrs) throws UnknownHostException {
148 if (!addrs.isEmpty()) {
149 this.setOption(new DhcpOption(code, DHCPUtils.strListAddrsToByteArray(addrs)));
153 public void setOptionString(byte code, String str) {
154 this.setOption(new DhcpOption(code, str.getBytes(StandardCharsets.UTF_8)));
157 public byte[] serialize() {
158 byte[] serializedOptions = new byte[0];
159 for (DhcpOption dhcpOption: this.options.values()) {
160 serializedOptions = ArrayUtils.addAll(serializedOptions, dhcpOption.serialize());
162 byte[] end = new byte[] {(byte)255};
163 serializedOptions = ArrayUtils.addAll(serializedOptions, end);
164 return serializedOptions;
167 private byte[] getOptionValArray(byte[] opt, int pos, int len) {
168 byte[] val = new byte[len];
169 for (int i = 0; i < len; i++) {
170 val[i] = opt[pos + i];
175 public void deserialize(byte[] serializedOptions) {
180 if (serializedOptions != null) {
181 while (pos < serializedOptions.length) {
182 code = serializedOptions[pos++];
183 if (code == OPT_END) {
186 len = serializedOptions[pos++];
187 if (len + pos > serializedOptions.length) {
188 // Throw exception???
191 value = getOptionValArray(serializedOptions, pos, len);
192 setOption(code, value);
199 public String toString() {
200 StringBuilder sb = new StringBuilder();
203 for (DhcpOption dhcpOption: this.options.values()) {
204 //options = ArrayUtils.addAll(options, dOpt.serialize());
205 sb.append("Option").append(count++).append(dhcpOption.toString());
208 return sb.toString();
211 public boolean containsOption(byte code) {
212 return options.containsKey(code);
215 public DhcpOption unsetOption(byte code) {
216 return options.remove(code);