/*
* Copyright 2009-2014 Jagornet Technologies, LLC. All Rights Reserved.
*
* This software is the proprietary information of Jagornet Technologies, LLC.
* Use is subject to license terms.
*
*/
/*
* This file TestDhcpMessage.java is part of Jagornet DHCP.
*
* Jagornet DHCP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jagornet DHCP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jagornet DHCP. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.jagornet.dhcp.message;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import junit.framework.TestCase;
import com.jagornet.dhcp.message.DhcpV6Message;
import com.jagornet.dhcp.option.base.DhcpOption;
import com.jagornet.dhcp.option.v6.DhcpV6ClientIdOption;
import com.jagornet.dhcp.option.v6.DhcpV6DnsServersOption;
import com.jagornet.dhcp.option.v6.DhcpV6OptionRequestOption;
import com.jagornet.dhcp.option.v6.DhcpV6ServerIdOption;
import com.jagornet.dhcp.option.v6.DhcpV6UserClassOption;
import com.jagornet.dhcp.util.DhcpConstants;
import com.jagornet.dhcp.xml.OpaqueData;
import com.jagornet.dhcp.xml.V6ServerIdOption;
public class TestDhcpMessage extends TestCase
{
// the address of the client itself
public static InetSocketAddress CLIENT_ADDR =
new InetSocketAddress("2001:DB8::A", DhcpConstants.V6_CLIENT_PORT);
public static String DNS1 = "2001:DB8:1::1";
public static String DNS2 = "2001:DB8:1::2";
public static String DNS3 = "2001:DB8:1::3";
public static DhcpV6Message buildMockDhcpMessage()
{
DhcpV6Message dhcpMessage =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT),
new InetSocketAddress(DhcpConstants.V6_CLIENT_PORT));
dhcpMessage.setMessageType(DhcpConstants.V6MESSAGE_TYPE_REPLY); // 1 byte
dhcpMessage.setTransactionId(90599); // 3 bytes
OpaqueData opaque = OpaqueData.Factory.newInstance();
opaque.setAsciiValue("jagornet-dhcpv6"); // 15 bytes
// MUST include server id in reply
V6ServerIdOption serverId = V6ServerIdOption.Factory.newInstance(); // 4 bytes (code + len)
serverId.setOpaqueData(opaque);
dhcpMessage.putDhcpOption(new DhcpV6ServerIdOption(serverId));
DhcpV6DnsServersOption dnsServers = new DhcpV6DnsServersOption(); // 4 bytes
dnsServers.addIpAddress(DNS1); // 16 bytes
dnsServers.addIpAddress(DNS2); // 16 bytes
dnsServers.addIpAddress(DNS3); // 16 bytes
dhcpMessage.putDhcpOption(dnsServers);
return dhcpMessage;
}
public static void checkEncodedMockDhcpMessage(ByteBuffer bb) throws Exception
{
// message type
assertEquals(DhcpConstants.V6MESSAGE_TYPE_REPLY, bb.get());
// transaction id
assertEquals((byte)0x01, bb.get());
assertEquals((byte)0x61, bb.get());
assertEquals((byte)0xe7, bb.get());
// server id option
assertEquals(DhcpConstants.V6OPTION_SERVERID, bb.getShort());
assertEquals(15, bb.getShort());
byte[] b = new byte[15];
bb.get(b);
assertEquals("jagornet-dhcpv6", new String(b));
// dns servers option
assertEquals(DhcpConstants.V6OPTION_DNS_SERVERS, bb.getShort());
assertEquals(48, bb.getShort());
b = new byte[16];
bb.get(b);
assertEquals(InetAddress.getByName(DNS1), InetAddress.getByAddress(b));
bb.get(b);
assertEquals(InetAddress.getByName(DNS2), InetAddress.getByAddress(b));
bb.get(b);
assertEquals(InetAddress.getByName(DNS3), InetAddress.getByAddress(b));
}
public void testEncode() throws Exception
{
DhcpV6Message dhcpMessage = buildMockDhcpMessage();
ByteBuffer bb = dhcpMessage.encode();
assertNotNull(bb);
assertEquals(75, bb.limit());
checkEncodedMockDhcpMessage(bb);
assertEquals(false, bb.hasRemaining());
}
public static ByteBuffer buildMockClientRequest()
{
ByteBuffer bb = ByteBuffer.allocate(1024);
bb.put((byte)DhcpConstants.V6MESSAGE_TYPE_INFO_REQUEST);
bb.put(new byte[] { (byte)0xff, (byte)0xff, (byte)0xff });
// client id option
bb.putShort((short)DhcpConstants.V6OPTION_CLIENTID);
bb.putShort((short)10);
bb.put("MyClientId".getBytes());
// option request option
bb.putShort((short)DhcpConstants.V6OPTION_ORO);
bb.putShort((short)2);
bb.putShort((short)DhcpConstants.V6OPTION_DNS_SERVERS);
// user class option
bb.putShort((short)DhcpConstants.V6OPTION_USER_CLASS);
bb.putShort((short)26);
bb.putShort((short)11);
bb.put("UserClass 1".getBytes());
bb.putShort((short)11);
bb.put("UserClass 2".getBytes());
bb.flip();
return bb;
}
public static void checkMockClientRequest(DhcpV6Message dhcpMessage)
{
assertEquals(CLIENT_ADDR.getAddress(), dhcpMessage.getRemoteAddress().getAddress());
assertEquals(DhcpConstants.V6MESSAGE_TYPE_INFO_REQUEST, dhcpMessage.getMessageType());
assertEquals(Long.parseLong("FFFFFF", 16), dhcpMessage.getTransactionId());
Map<Integer, DhcpOption> options = dhcpMessage.getDhcpOptionMap();
assertNotNull(options);
DhcpV6ClientIdOption clientId =
(DhcpV6ClientIdOption)options.get(DhcpConstants.V6OPTION_CLIENTID);
assertNotNull(clientId);
assertEquals("MyClientId", clientId.getOpaqueData().getAscii());
DhcpV6OptionRequestOption oro =
(DhcpV6OptionRequestOption)options.get(DhcpConstants.V6OPTION_ORO);
assertNotNull(oro);
assertEquals(Integer.valueOf(DhcpConstants.V6OPTION_DNS_SERVERS),
oro.getUnsignedShortList().get(0));
DhcpV6UserClassOption userClass =
(DhcpV6UserClassOption)options.get(DhcpConstants.V6OPTION_USER_CLASS);
assertNotNull(userClass);
assertEquals("UserClass 1",
userClass.getOpaqueDataList().get(0).getAscii());
assertEquals("UserClass 2",
userClass.getOpaqueDataList().get(1).getAscii());
}
public void testDecode() throws Exception
{
ByteBuffer bb = buildMockClientRequest();
int len = bb.limit();
DhcpV6Message dhcpMessage =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT),
CLIENT_ADDR);
dhcpMessage.decode(bb);
assertNotNull(dhcpMessage);
assertEquals(len, dhcpMessage.getLength());
checkMockClientRequest(dhcpMessage);
}
public void testEquals() throws Exception
{
DhcpV6Message msg1 =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT), CLIENT_ADDR);
msg1.setTransactionId(12345);
msg1.setMessageType((short)1);
DhcpV6ClientIdOption c1 = new DhcpV6ClientIdOption();
c1.getOpaqueData().setHex(
new byte[] { (byte)0xde, (byte)0xbb, (byte)0x1e, (byte)0xde, (byte)0xbb, (byte)0x1e });
msg1.putDhcpOption(c1);
DhcpV6Message msg2 =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT), CLIENT_ADDR);
msg2.setTransactionId(12345);
msg2.setMessageType((short)1);
DhcpV6ClientIdOption c2 = new DhcpV6ClientIdOption();
c2.getOpaqueData().setHex(
new byte[] { (byte)0xde, (byte)0xbb, (byte)0x1e, (byte)0xde, (byte)0xbb, (byte)0x1e });
msg2.putDhcpOption(c2);
// This was testing equality of message for cheap DOS detection, but we got rid of that
// assertEquals(msg1, msg2);
}
public void testSet() throws Exception
{
DhcpV6Message msg1 =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT), CLIENT_ADDR);
msg1.setTransactionId(12345);
msg1.setMessageType((short)1);
DhcpV6ClientIdOption c1 = new DhcpV6ClientIdOption();
c1.getOpaqueData().setHex(
new byte[] { (byte)0xde, (byte)0xbb, (byte)0x1e, (byte)0xde, (byte)0xbb, (byte)0x1e });
msg1.putDhcpOption(c1);
// System.out.println("msg1.hash=" + msg1.hashCode());
DhcpV6Message msg2 =
new DhcpV6Message(new InetSocketAddress(DhcpConstants.V6_SERVER_PORT), CLIENT_ADDR);
msg2.setTransactionId(12345);
msg2.setMessageType((short)1);
DhcpV6ClientIdOption c2 = new DhcpV6ClientIdOption();
c2.getOpaqueData().setHex(
new byte[] { (byte)0xde, (byte)0xbb, (byte)0x1e, (byte)0xde, (byte)0xbb, (byte)0x1e });
msg2.putDhcpOption(c2);
// System.out.println("msg2.hash=" + msg2.hashCode());
Set<DhcpV6Message> s = new HashSet<DhcpV6Message>();
s.add(msg1);
// This was testing equality of message for cheap DOS detection, but we got rid of that
// assertTrue(s.contains(msg2));
}
}