blob: c2bbeb604364ec23e9ad11ec1c9eb89dd9476e67 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Foundation
*
* 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.onlab.packet.dhcp;
import com.google.common.io.Resources;
import org.apache.commons.io.Charsets;
import org.apache.commons.lang.ArrayUtils;
import org.junit.Test;
import org.onlab.packet.DHCP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.PacketTestUtils;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.stream.IntStream;
import static org.junit.Assert.*;
/**
* Unit tests for DHCP class.
*/
public class DhcpTest {
private static final String DISCOVER = "dhcp_discover.bin";
private static final String OFFER = "dhcp_offer.bin";
private static final String REQUEST = "dhcp_request.bin";
private static final String ACK = "dhcp_ack.bin";
private static final String LONG_OPT = "dhcp_long_opt.bin";
private static final String EMPTY = "";
private static final byte HW_TYPE = 1;
private static final byte HW_ADDR_LEN = 6;
private static final byte HOPS = 1;
private static final int XID = 0x8f5a186c;
private static final short SECS = 0;
private static final short FLAGS = 0;
private static final int NO_IP = 0;
private static final Ip4Address GW_IP = Ip4Address.valueOf("10.0.4.254");
private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.99.3");
private static final MacAddress CLIENT_HW_ADDR = MacAddress.valueOf("00:aa:00:00:00:01");
private static final Ip4Address CLIENT_IP = Ip4Address.valueOf("10.0.4.1");
private static final Ip4Address DNS_1 = Ip4Address.valueOf("8.8.8.8");
private static final Ip4Address DNS_2 = Ip4Address.valueOf("8.8.4.4");
private static final Ip4Address SUBNET_MASK = Ip4Address.valueOf("255.255.255.0");
private static final String HOSTNAME = "charlie-n";
private static final String CIRCUIT_ID = "relay-eth0";
private static final String DOMAIN_NAME = "trellis.local";
@Test
public void testDeserializeBadInput() throws Exception {
PacketTestUtils.testDeserializeBadInput(DHCP.deserializer());
}
@Test
public void testDeserializeTruncated() throws Exception {
byte[] byteHeader = ByteBuffer.allocate(241)
.put((byte) 0x01) // op code
.put((byte) 0x01) // hardware type
.put((byte) 0x06) // hardware address len
.put((byte) 0x00) // hops
.putInt(0x3e8) // transaction id
.putShort((short) 0x0) // seconds
.putShort((short) 0x0) // flags
.putInt(0) // client ip
.putInt(0) // your ip
.putInt(0) // server ip
.putInt(0) // gateway ip
.put(MacAddress.valueOf("1a:1a:1a:1a:1a:1a").toBytes()) // client hardware address
.put(new byte[10]) // pad
.put(new byte[64]) // server name
.put(new byte[128]) // boot file name
.putInt(0x63825363) // magic cookie
.put((byte) 0xff) // end of options
.array();
PacketTestUtils.testDeserializeTruncated(DHCP.deserializer(), byteHeader);
}
/**
* Tests deserialize discover packet.
*/
@Test
public void testDeserializeDiscover() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(DISCOVER));
Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
assertEquals(DHCP.OPCODE_REQUEST, dhcp.getOpCode());
assertEquals(HW_TYPE, dhcp.getHardwareType());
assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
assertEquals(HOPS, dhcp.getHops());
assertEquals(XID, dhcp.getTransactionId());
assertEquals(SECS, dhcp.getSeconds());
assertEquals(FLAGS, dhcp.getFlags());
assertEquals(NO_IP, dhcp.getClientIPAddress());
assertEquals(NO_IP, dhcp.getYourIPAddress());
assertEquals(NO_IP, dhcp.getServerIPAddress());
assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
assertEquals(EMPTY, dhcp.getServerName());
assertEquals(EMPTY, dhcp.getBootFileName());
assertEquals(6, dhcp.getOptions().size());
DhcpOption option = dhcp.getOptions().get(0);
assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
assertEquals(1, option.length);
assertEquals(DHCP.MsgType.DHCPDISCOVER.getValue(), (int) option.getData()[0]);
option = dhcp.getOptions().get(1);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(CLIENT_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(2);
assertEquals(DHCP.DHCPOptionCode.OptionCode_HostName.getValue(), option.code);
assertEquals(9, option.length);
assertArrayEquals(HOSTNAME.getBytes(Charsets.US_ASCII), option.getData());
option = dhcp.getOptions().get(3);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedParameters.getValue(),
option.code);
assertEquals(13, option.length);
assertArrayEquals(new byte[]{1, 28, 2, 3, 15, 6, 119, 12, 44, 47, 26, 121, 42},
option.getData());
option = dhcp.getOptions().get(4);
assertTrue(option instanceof DhcpRelayAgentOption);
DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
assertEquals(12, relayAgentOption.length);
DhcpOption subOption = relayAgentOption
.getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
assertEquals(10, subOption.getLength());
assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
option = dhcp.getOptions().get(5);
assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
assertEquals(0, option.length);
}
/**
* Tests deserialize discover packet.
*/
@Test
public void testDeserializeOffer() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(OFFER));
Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
assertEquals(DHCP.OPCODE_REPLY, dhcp.getOpCode());
assertEquals(HW_TYPE, dhcp.getHardwareType());
assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
assertEquals(HOPS, dhcp.getHops());
assertEquals(XID, dhcp.getTransactionId());
assertEquals(SECS, dhcp.getSeconds());
assertEquals(FLAGS, dhcp.getFlags());
assertEquals(NO_IP, dhcp.getClientIPAddress());
assertEquals(CLIENT_IP.toInt(), dhcp.getYourIPAddress());
assertEquals(SERVER_IP.toInt(), dhcp.getServerIPAddress());
assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
assertEquals(EMPTY, dhcp.getServerName());
assertEquals(EMPTY, dhcp.getBootFileName());
assertEquals(9, dhcp.getOptions().size());
DhcpOption option = dhcp.getOptions().get(0);
assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
assertEquals(1, option.length);
assertEquals(DHCP.MsgType.DHCPOFFER.getValue(), (int) option.getData()[0]);
option = dhcp.getOptions().get(1);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(SERVER_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(2);
assertEquals(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(new byte[]{0, 0, 2, 88}, option.getData());
option = dhcp.getOptions().get(3);
assertEquals(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(SUBNET_MASK.toOctets(), option.getData());
option = dhcp.getOptions().get(4);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(GW_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(5);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainName.getValue(), option.code);
assertEquals(13, option.length);
assertArrayEquals(DOMAIN_NAME.getBytes(Charsets.US_ASCII), option.getData());
option = dhcp.getOptions().get(6);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue(), option.code);
assertEquals(8, option.length);
assertArrayEquals(ArrayUtils.addAll(DNS_1.toOctets(), DNS_2.toOctets()),
option.getData());
option = dhcp.getOptions().get(7);
assertTrue(option instanceof DhcpRelayAgentOption);
DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
assertEquals(12, relayAgentOption.length);
DhcpOption subOption = relayAgentOption
.getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
assertEquals(10, subOption.getLength());
assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
option = dhcp.getOptions().get(8);
assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
assertEquals(0, option.length);
}
/**
* Tests deserialize discover packet.
*/
@Test
public void testDeserializeRequest() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(REQUEST));
Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
assertEquals(DHCP.OPCODE_REQUEST, dhcp.getOpCode());
assertEquals(HW_TYPE, dhcp.getHardwareType());
assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
assertEquals(HOPS, dhcp.getHops());
assertEquals(XID, dhcp.getTransactionId());
assertEquals(SECS, dhcp.getSeconds());
assertEquals(FLAGS, dhcp.getFlags());
assertEquals(NO_IP, dhcp.getClientIPAddress());
assertEquals(NO_IP, dhcp.getYourIPAddress());
assertEquals(NO_IP, dhcp.getServerIPAddress());
assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
assertEquals(EMPTY, dhcp.getServerName());
assertEquals(EMPTY, dhcp.getBootFileName());
assertEquals(7, dhcp.getOptions().size());
DhcpOption option = dhcp.getOptions().get(0);
assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
assertEquals(1, option.length);
assertEquals(DHCP.MsgType.DHCPREQUEST.getValue(), (int) option.getData()[0]);
option = dhcp.getOptions().get(1);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(SERVER_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(2);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(CLIENT_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(3);
assertEquals(DHCP.DHCPOptionCode.OptionCode_HostName.getValue(), option.code);
assertEquals(9, option.length);
assertArrayEquals(HOSTNAME.getBytes(Charsets.US_ASCII), option.getData());
option = dhcp.getOptions().get(4);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RequestedParameters.getValue(),
option.code);
assertEquals(13, option.length);
assertArrayEquals(new byte[]{1, 28, 2, 3, 15, 6, 119, 12, 44, 47, 26, 121, 42},
option.getData());
option = dhcp.getOptions().get(5);
assertTrue(option instanceof DhcpRelayAgentOption);
DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
assertEquals(12, relayAgentOption.length);
DhcpOption subOption = relayAgentOption
.getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
assertEquals(10, subOption.getLength());
assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
option = dhcp.getOptions().get(6);
assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
assertEquals(0, option.length);
}
/**
* Tests deserialize discover packet.
*/
@Test
public void testDeserializeAck() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(ACK));
Ethernet eth = Ethernet.deserializer().deserialize(data, 0, data.length);
DHCP dhcp = (DHCP) eth.getPayload().getPayload().getPayload();
assertEquals(DHCP.OPCODE_REPLY, dhcp.getOpCode());
assertEquals(HW_TYPE, dhcp.getHardwareType());
assertEquals(HW_ADDR_LEN, dhcp.getHardwareAddressLength());
assertEquals(HOPS, dhcp.getHops());
assertEquals(XID, dhcp.getTransactionId());
assertEquals(SECS, dhcp.getSeconds());
assertEquals(FLAGS, dhcp.getFlags());
assertEquals(NO_IP, dhcp.getClientIPAddress());
assertEquals(CLIENT_IP.toInt(), dhcp.getYourIPAddress());
assertEquals(SERVER_IP.toInt(), dhcp.getServerIPAddress());
assertEquals(GW_IP.toInt(), dhcp.getGatewayIPAddress());
assertTrue(Arrays.equals(CLIENT_HW_ADDR.toBytes(), dhcp.getClientHardwareAddress()));
assertEquals(EMPTY, dhcp.getServerName());
assertEquals(EMPTY, dhcp.getBootFileName());
assertEquals(9, dhcp.getOptions().size());
DhcpOption option = dhcp.getOptions().get(0);
assertEquals(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue(), option.code);
assertEquals(1, option.length);
assertEquals(DHCP.MsgType.DHCPACK.getValue(), (int) option.getData()[0]);
option = dhcp.getOptions().get(1);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(SERVER_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(2);
assertEquals(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(new byte[]{0, 0, 2, 88}, option.getData());
option = dhcp.getOptions().get(3);
assertEquals(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(SUBNET_MASK.toOctets(), option.getData());
option = dhcp.getOptions().get(4);
assertEquals(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue(), option.code);
assertEquals(4, option.length);
assertArrayEquals(GW_IP.toOctets(), option.getData());
option = dhcp.getOptions().get(5);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainName.getValue(), option.code);
assertEquals(13, option.length);
assertArrayEquals(DOMAIN_NAME.getBytes(Charsets.US_ASCII), option.getData());
option = dhcp.getOptions().get(6);
assertEquals(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue(), option.code);
assertEquals(8, option.length);
assertArrayEquals(ArrayUtils.addAll(DNS_1.toOctets(), DNS_2.toOctets()),
option.getData());
option = dhcp.getOptions().get(7);
assertTrue(option instanceof DhcpRelayAgentOption);
DhcpRelayAgentOption relayAgentOption = (DhcpRelayAgentOption) option;
assertEquals(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue(), relayAgentOption.code);
assertEquals(12, relayAgentOption.length);
DhcpOption subOption = relayAgentOption
.getSubOption(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
assertEquals(10, subOption.getLength());
assertArrayEquals(CIRCUIT_ID.getBytes(Charsets.US_ASCII), subOption.getData());
option = dhcp.getOptions().get(8);
assertEquals(DHCP.DHCPOptionCode.OptionCode_END.getValue(), option.code);
assertEquals(0, option.length);
}
/**
* Test option with option length > 128.
*/
@Test
public void longOptionTest() throws Exception {
byte[] data = Resources.toByteArray(Dhcp6RelayTest.class.getResource(LONG_OPT));
DHCP dhcp = DHCP.deserializer().deserialize(data, 0, data.length);
assertEquals(2, dhcp.getOptions().size());
DhcpOption hostnameOption = dhcp.getOption(DHCP.DHCPOptionCode.OptionCode_HostName);
DhcpOption endOption = dhcp.getOption(DHCP.DHCPOptionCode.OptionCode_END);
assertNotNull(hostnameOption);
assertNotNull(endOption);
// Host name contains 200 "A"
StringBuilder hostnameBuilder = new StringBuilder();
IntStream.range(0, 200).forEach(i -> hostnameBuilder.append("A"));
String hostname = hostnameBuilder.toString();
assertEquals((byte) 200, hostnameOption.getLength());
assertArrayEquals(hostname.getBytes(Charsets.US_ASCII), hostnameOption.getData());
}
}