17da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttpackage android.net.dhcp; 27da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 37da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport android.util.Log; 47da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 57da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.io.UnsupportedEncodingException; 67da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.net.InetAddress; 77da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.net.UnknownHostException; 87da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ByteBuffer; 97da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ByteOrder; 107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.charset.Charsets; 117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ShortBuffer; 127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.util.ArrayList; 147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.util.List; 157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt/** 177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Defines basic data and operations needed to build and use packets for the 187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP protocol. Subclasses create the specific packets used at each 197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * stage of the negotiation. 207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttabstract class DhcpPacket { 227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final String TAG = "DhcpPacket"; 237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Packet encapsulations. 267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_L2 = 0; // EthernetII header included 287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_L3 = 1; // IP/UDP header included 297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_BOOTP = 2; // BOOTP contents only 307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP layer definitions. 337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TYPE_UDP = (byte) 0x11; 357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: Version 4, Header Length 20 bytes 387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45; 407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: Flags 0, Fragment Offset 0, Don't Fragment 437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final short IP_FLAGS_OFFSET = (short) 0x4000; 457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: TOS 487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TOS_LOWDELAY = (byte) 0x10; 507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: TTL -- use default 64 from RFC1340 537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TTL = (byte) 0x40; 557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The client DHCP port. 587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt static final short DHCP_CLIENT = (short) 68; 607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The server DHCP port. 637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt static final short DHCP_SERVER = (short) 67; 657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The message op code indicating a request from a client. 687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BOOTREQUEST = (byte) 1; 707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The message op code indicating a response from the server. 737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BOOTREPLY = (byte) 2; 757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The code type used to identify an Ethernet MAC address in the 787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Client-ID field. 797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte CLIENT_ID_ETHER = (byte) 1; 817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The maximum length of a packet that can be constructed. 847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final int MAX_LENGTH = 1500; 867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Subnet Mask 897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_SUBNET_MASK = 1; 917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected InetAddress mSubnetMask; 927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Router 957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_ROUTER = 3; 977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected InetAddress mGateway; 987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP DNS Server 1017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_DNS_SERVER = 6; 1037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected List<InetAddress> mDnsServers; 1047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Host Name 1077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_HOST_NAME = 12; 1097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mHostName; 1107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP DOMAIN NAME 1137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_DOMAIN_NAME = 15; 1157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mDomainName; 1167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP BROADCAST ADDRESS 1197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BROADCAST_ADDRESS = 28; 1217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected InetAddress mBroadcastAddress; 1227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Requested IP Address 1257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_REQUESTED_IP = 50; 1277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected InetAddress mRequestedIp; 1287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Lease Time 1317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_LEASE_TIME = 51; 1337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected Integer mLeaseTime; 1347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Message Type 1377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE = 53; 1397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // the actual type values 1407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; 1417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2; 1427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; 1437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; 1447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_ACK = 5; 1457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_NAK = 6; 1467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8; 1477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Server Identifier 1507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_SERVER_IDENTIFIER = 54; 1527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected InetAddress mServerIdentifier; 1537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Parameter List 1567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_PARAMETER_LIST = 55; 1587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected byte[] mRequestedParams; 1597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP MESSAGE 1627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE = 56; 1647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mMessage; 1657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Renewal Time Value 1687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_RENEWAL_TIME = 58; 1707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: Vendor Class Identifier 1737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_VENDOR_CLASS_ID = 60; 1757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Client Identifier 1787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_CLIENT_IDENTIFIER = 61; 1807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The transaction identifier used in this particular DHCP negotiation 1837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final int mTransId; 1857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The IP address of the client host. This address is typically 1887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * proposed by the client (from an earlier DHCP negotiation) or 1897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * supplied by the server. 1907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final InetAddress mClientIp; 1927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final InetAddress mYourIp; 1937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private final InetAddress mNextIp; 1947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private final InetAddress mRelayIp; 1957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Does the client request a broadcast response? 1987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected boolean mBroadcast; 2007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The six-octet MAC of the client. 2037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final byte[] mClientMac; 2057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Asks the packet object to signal the next operation in the DHCP 2087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * protocol. The available actions are methods defined in the 2097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DhcpStateMachine interface. 2107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public abstract void doNextOp(DhcpStateMachine stateMachine); 2127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Asks the packet object to create a ByteBuffer serialization of 2157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * the packet for transmission. 2167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public abstract ByteBuffer buildPacket(int encap, short destUdp, 2187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short srcUdp); 2197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Allows the concrete class to fill in packet-type-specific details, 2227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * typically optional parameters at the end of the packet. 2237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt abstract void finishPacket(ByteBuffer buffer); 2257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp, 2277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress nextIp, InetAddress relayIp, 2287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac, boolean broadcast) { 2297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mTransId = transId; 2307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mClientIp = clientIp; 2317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mYourIp = yourIp; 2327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mNextIp = nextIp; 2337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mRelayIp = relayIp; 2347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mClientMac = clientMac; 2357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mBroadcast = broadcast; 2367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 2377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Returns the transaction ID. 2407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public int getTransactionId() { 2427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return mTransId; 2437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 2447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Creates a new L3 packet (including IP header) containing the 2477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP udp packet. This method relies upon the delegated method 2487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * finishPacket() to insert the per-packet contents. 2497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void fillInPacket(int encap, InetAddress destIp, 2517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf, 2527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte requestCode, boolean broadcast) { 2537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] destIpArray = destIp.getAddress(); 2547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] srcIpArray = srcIp.getAddress(); 2557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int ipLengthOffset = 0; 2567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int ipChecksumOffset = 0; 2577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int endIpHeader = 0; 2587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpHeaderOffset = 0; 2597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpLengthOffset = 0; 2607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpChecksumOffset = 0; 2617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.clear(); 2637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.order(ByteOrder.BIG_ENDIAN); 2647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // if a full IP packet needs to be generated, put the IP & UDP 2667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // headers in place, and pre-populate with artificial values 2677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // needed to seed the IP checksum. 2687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (encap == ENCAP_L3) { 2697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fake IP header, used in the IP-header checksum 2707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_VERSION_HEADER_LEN); 2717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY 2727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipLengthOffset = buf.position(); 2737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short)0); // length 2747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short)0); // id 2757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment 2767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TTL); // TTL: use default 64 from RFC1340 2777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TYPE_UDP); 2787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipChecksumOffset = buf.position(); 2797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // checksum 2807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(srcIpArray); 2827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(destIpArray); 2837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt endIpHeader = buf.position(); 2847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // UDP header 2867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpHeaderOffset = buf.position(); 2877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(srcUdp); 2887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(destUdp); 2897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpLengthOffset = buf.position(); 2907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // length 2917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpChecksumOffset = buf.position(); 2927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // UDP checksum -- initially zero 2937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 2947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // DHCP payload 2967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(requestCode); 2977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 1); // Hardware Type: Ethernet 2987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) mClientMac.length); // Hardware Address Length 2997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0); // Hop Count 3007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putInt(mTransId); // Transaction ID 3017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // Elapsed Seconds 3027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (broadcast) { 3047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0x8000); // Flags 3057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } else { 3067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0x0000); // Flags 3077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mClientIp.getAddress()); 3107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mYourIp.getAddress()); 3117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mNextIp.getAddress()); 3127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mRelayIp.getAddress()); 3137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mClientMac); 3147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(buf.position() + 3157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt (16 - mClientMac.length) // pad addr to 16 bytes 3167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 64 // empty server host name (64 bytes) 3177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 128); // empty boot file name (128 bytes) 3187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putInt(0x63825363); // magic number 3197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt finishPacket(buf); 3207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // round up to an even number of octets 3227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if ((buf.position() & 1) == 1) { 3237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0); 3247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // If an IP packet is being built, the IP & UDP checksums must be 3277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // computed. 3287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (encap == ENCAP_L3) { 3297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix UDP header: insert length 3307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpLen = (short)(buf.position() - udpHeaderOffset); 3317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(udpLengthOffset, udpLen); 3327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix UDP header: checksum 3337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // checksum for UDP at udpChecksumOffset 3347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpSeed = 0; 3357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // apply IPv4 pseudo-header. Read IP address src and destination 3377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // values from the IP header and accumulate checksum. 3387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2)); 3397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4)); 3407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6)); 3417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8)); 3427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // accumulate extra data for the pseudo-header 3447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += IP_TYPE_UDP; 3457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += udpLen; 3467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // and compute UDP checksum 3477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed, 3487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpHeaderOffset, 3497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position())); 3507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix IP header: insert length 3517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(ipLengthOffset, (short)buf.position()); 3527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fixup IP-header checksum 3537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(ipChecksumOffset, 3547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt (short) checksum(buf, 0, 0, endIpHeader)); 3557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 3597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Converts a signed short value to an unsigned int value. Needed 3607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * because Java does not have unsigned types. 3617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 3627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private int intAbs(short v) { 3637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (v < 0) { 3647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int r = v + 65536; 3657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return r; 3667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } else { 3677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return(v); 3687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 3727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Performs an IP checksum (used in IP header and across UDP 3737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * payload) on the specified portion of a ByteBuffer. The seed 3747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * allows the checksum to commence with a specified value. 3757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 3767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private int checksum(ByteBuffer buf, int seed, int start, int end) { 3777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int sum = seed; 3787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int bufPosition = buf.position(); 3797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // set position of original ByteBuffer, so that the ShortBuffer 3817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // will be correctly initialized 3827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(start); 3837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ShortBuffer shortBuf = buf.asShortBuffer(); 3847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // re-set ByteBuffer position 3867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(bufPosition); 3877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short[] shortArray = new short[(end - start) / 2]; 3897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt shortBuf.get(shortArray); 3907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (short s : shortArray) { 3927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum += intAbs(s); 3937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt start += shortArray.length * 2; 3967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // see if a singleton byte remains 3987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (end != start) { 3997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short b = buf.get(start); 4007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // make it unsigned 4027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (b < 0) { 4037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt b += 256; 4047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum += b * 256; 4077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); 4107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF); 4117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int negated = ~sum; 4127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return intAbs((short) negated); 4137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a single byte value. 4177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, byte value) { 4197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 4207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 1); 4217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(value); 4227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing an array of bytes. 4267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, byte[] payload) { 4287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (payload != null) { 4297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 4307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) payload.length); 4317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(payload); 4327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing an IP address. 4377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) { 4397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (addr != null) { 4407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt addTlv(buf, type, addr.getAddress()); 4417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a list of IP addresses. 4467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, List<InetAddress> addrs) { 4487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (addrs != null && addrs.size() > 0) { 4497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 4507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte)(4 * addrs.size())); 4517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (InetAddress addr : addrs) { 4537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(addr.getAddress()); 4547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a simple integer 4607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, Integer value) { 4627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (value != null) { 4637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 4647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 4); 4657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putInt(value.intValue()); 4667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing and ASCII string. 4717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlv(ByteBuffer buf, byte type, String str) { 4737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (str != null) { 4747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 4757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) str.length()); 4767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (int i = 0; i < str.length(); i++) { 4787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) str.charAt(i)); 4797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds the special end-of-optional-parameters indicator. 4857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected void addTlvEnd(ByteBuffer buf) { 4877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0xFF); 4887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Converts a MAC from an array of octets to an ASCII string. 4927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static String macToString(byte[] mac) { 4947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String macAddr = ""; 4957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (int i = 0; i < mac.length; i++) { 4977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String hexString = "0" + Integer.toHexString(mac[i]); 4987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // substring operation grabs the last 2 digits: this 5007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // allows signed bytes to be converted correctly. 5017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt macAddr += hexString.substring(hexString.length() - 2); 5027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (i != (mac.length - 1)) { 5047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt macAddr += ":"; 5057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return macAddr; 5097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public String toString() { 5127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String macAddr = macToString(mClientMac); 5137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return macAddr; 5157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Reads a four-octet value from a ByteBuffer and construct 5197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * an IPv4 address from that value. 5207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 5217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static InetAddress readIpAddress(ByteBuffer packet) { 5227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress result = null; 5237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] ipAddr = new byte[4]; 5247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipAddr); 5257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt try { 5277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt result = InetAddress.getByAddress(ipAddr); 5287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } catch (UnknownHostException ex) { 5297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // ipAddr is numeric, so this should not be 5307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // triggered. However, if it is, just nullify 5317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt result = null; 5327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return result; 5357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Reads a string of specified length from the buffer. 5397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 5407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static String readAsciiString(ByteBuffer buf, int byteCount) { 5417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] bytes = new byte[byteCount]; 5427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.get(bytes); 5437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return new String(bytes, 0, bytes.length, Charsets.US_ASCII); 5447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Creates a concrete DhcpPacket from the supplied ByteBuffer. The 5487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * buffer may have an L2 encapsulation (which is the full EthernetII 5497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * format starting with the source-address MAC) or an L3 encapsulation 5507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * (which starts with the IP header). 5517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * <br> 5527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * A subset of the optional parameters are parsed and are stored 5537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * in object fields. 5547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 5557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) 5567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt { 5577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // bootp parameters 5587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int transactionId; 5597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress clientIp; 5607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress yourIp; 5617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress nextIp; 5627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress relayIp; 5637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac; 564045b166ac27c3b7a67993b029f03088042bf4d5aStan Chesnutt List<InetAddress> dnsServers = new ArrayList<InetAddress>(); 5657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress gateway = null; // aka router 5667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt Integer leaseTime = null; 5677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress serverIdentifier = null; 5687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress netMask = null; 5697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String message = null; 5707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String vendorId = null; 5717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] expectedParams = null; 5727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String hostName = null; 5737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String domainName = null; 5747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress ipSrc = null; 5757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress ipDst = null; 5767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress bcAddr = null; 5777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress requestedIp = null; 5787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // dhcp options 5807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte dhcpType = (byte) 0xFF; 5817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.order(ByteOrder.BIG_ENDIAN); 5837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // check to see if we need to parse L2, IP, and UDP encaps 5857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (pktType == ENCAP_L2) { 5867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // System.out.println("buffer len " + packet.limit()); 5877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] l2dst = new byte[6]; 5887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] l2src = new byte[6]; 5897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(l2dst); 5917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(l2src); 5927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short l2type = packet.getShort(); 5947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (l2type != 0x0800) 5967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 5977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) { 6007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // assume l2type is 0x0800, i.e. IP 6017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipType = packet.get(); 6027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // System.out.println("ipType is " + ipType); 6037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipDiffServicesField = packet.get(); 6047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipTotalLength = packet.getShort(); 6057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipIdentification = packet.getShort(); 6067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipFlags = packet.get(); 6077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipFragOffset = packet.get(); 6087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipTTL = packet.get(); 6097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipProto = packet.get(); 6107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipChksm = packet.getShort(); 6117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipSrc = readIpAddress(packet); 6137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipDst = readIpAddress(packet); 6147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (ipProto != IP_TYPE_UDP) // UDP 6167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 6177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // assume UDP 6197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpSrcPort = packet.getShort(); 6207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpDstPort = packet.getShort(); 6217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpLen = packet.getShort(); 6227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpChkSum = packet.getShort(); 6237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if ((udpSrcPort != DHCP_SERVER) && (udpSrcPort != DHCP_CLIENT)) 6257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 6267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // assume bootp 6297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte type = packet.get(); 6307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte hwType = packet.get(); 6317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte addrLen = packet.get(); 6327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte hops = packet.get(); 6337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId = packet.getInt(); 6347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short elapsed = packet.getShort(); 6357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short bootpFlags = packet.getShort(); 6367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean broadcast = (bootpFlags & 0x8000) != 0; 6377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] ipv4addr = new byte[4]; 6387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt try { 6407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 6417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientIp = InetAddress.getByAddress(ipv4addr); 6427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 6437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt yourIp = InetAddress.getByAddress(ipv4addr); 6447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 6457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt nextIp = InetAddress.getByAddress(ipv4addr); 6467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 6477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt relayIp = InetAddress.getByAddress(ipv4addr); 6487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } catch (UnknownHostException ex) { 6497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 6507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac = new byte[addrLen]; 6537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(clientMac); 6547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // skip over address padding (16 octets allocated) 6567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.position(packet.position() + (16 - addrLen) 6577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 64 // skip server host name (64 chars) 6587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 128); // skip boot file name (128 chars) 6597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int dhcpMagicCookie = packet.getInt(); 6617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (dhcpMagicCookie != 0x63825363) 6637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 6647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // parse options 6667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean notFinishedOptions = true; 6677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt while ((packet.position() < packet.limit()) && notFinishedOptions) { 6697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte optionType = packet.get(); 6707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (optionType == (byte) 0xFF) { 6727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt notFinishedOptions = false; 6737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } else { 6747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte optionLen = packet.get(); 6757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int expectedLen = 0; 6767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt switch(optionType) { 6787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_SUBNET_MASK: 6797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt netMask = readIpAddress(packet); 6807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 6817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 6827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_ROUTER: 6837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt gateway = readIpAddress(packet); 6847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 6857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 6867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_DNS_SERVER: 6877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 0; 6887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (expectedLen = 0; expectedLen < optionLen; 6907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen += 4) { 6917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt dnsServers.add(readIpAddress(packet)); 6927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 6947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_HOST_NAME: 6957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 6967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt hostName = readAsciiString(packet, optionLen); 6977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 6987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_DOMAIN_NAME: 6997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 7007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt domainName = readAsciiString(packet, optionLen); 7017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_BROADCAST_ADDRESS: 7037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt bcAddr = readIpAddress(packet); 7047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 7057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_REQUESTED_IP: 7077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt requestedIp = readIpAddress(packet); 7087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 7097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_LEASE_TIME: 7117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt leaseTime = Integer.valueOf(packet.getInt()); 7127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 7137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE: 7157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt dhcpType = packet.get(); 7167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 1; 7177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_SERVER_IDENTIFIER: 7197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt serverIdentifier = readIpAddress(packet); 7207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = 4; 7217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_PARAMETER_LIST: 7237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedParams = new byte[optionLen]; 7247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(expectedParams); 7257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 7267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE: 7287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 7297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt message = readAsciiString(packet, optionLen); 7307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_VENDOR_CLASS_ID: 7327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 7337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt vendorId = readAsciiString(packet, optionLen); 7347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_CLIENT_IDENTIFIER: { // Client identifier 7367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] id = new byte[optionLen]; 7377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(id); 7387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen = optionLen; 7397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } break; 7407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt default: 7417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // ignore any other parameters 7427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (int i = 0; i < optionLen; i++) { 7437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt expectedLen++; 7447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte throwaway = packet.get(); 7457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (expectedLen != optionLen) { 7497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 7507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket newPacket; 7557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt switch(dhcpType) { 7577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case -1: return null; 7587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_DISCOVER: 7597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpDiscoverPacket( 7607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientMac, broadcast); 7617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_OFFER: 7637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpOfferPacket( 7647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, broadcast, ipSrc, yourIp, clientMac); 7657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_REQUEST: 7677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpRequestPacket( 7687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientIp, clientMac, broadcast); 7697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_DECLINE: 7717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpDeclinePacket( 7727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientIp, yourIp, nextIp, relayIp, 7737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 7747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_ACK: 7767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpAckPacket( 7777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, broadcast, ipSrc, yourIp, clientMac); 7787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_NAK: 7807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpNakPacket( 7817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientIp, yourIp, nextIp, relayIp, 7827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 7837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_INFORM: 7857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpInformPacket( 7867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientIp, yourIp, nextIp, relayIp, 7877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 7887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 7897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt default: 7907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt System.out.println("Unimplemented type: " + dhcpType); 7917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return null; 7927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mBroadcastAddress = bcAddr; 7957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mDnsServers = dnsServers; 7967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mDomainName = domainName; 7977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mGateway = gateway; 7987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mHostName = hostName; 7997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mLeaseTime = leaseTime; 8007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mMessage = message; 8017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mRequestedIp = requestedIp; 8027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mRequestedParams = expectedParams; 8037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mServerIdentifier = serverIdentifier; 8047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mSubnetMask = netMask; 8057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return newPacket; 8067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Parse a packet from an array of bytes. 8107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static DhcpPacket decodeFullPacket(byte[] packet, int pktType) 8127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt { 8137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN); 8147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return decodeFullPacket(buffer, pktType); 8157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-DISCOVER packet from the required specified 8197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * parameters. 8207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, 8227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac, boolean broadcast, byte[] expectedParams) { 8237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpDiscoverPacket( 8247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, clientMac, broadcast); 8257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedParams = expectedParams; 8267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 8277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-OFFER packet from the required specified 8317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * parameters. 8327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildOfferPacket(int encap, int transactionId, 8347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr, 8357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr, 8367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress gateway, List<InetAddress> dnsServers, 8377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress dhcpServerIdentifier, String domainName) { 8387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpOfferPacket( 8397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, broadcast, serverIpAddr, clientIpAddr, mac); 8407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mGateway = gateway; 8417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDnsServers = dnsServers; 8427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mLeaseTime = timeout; 8437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDomainName = domainName; 8447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = dhcpServerIdentifier; 8457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mSubnetMask = netMask; 8467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mBroadcastAddress = bcAddr; 8477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 8487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-ACK packet from the required specified parameters. 8527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildAckPacket(int encap, int transactionId, 8547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr, 8557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr, 8567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress gateway, List<InetAddress> dnsServers, 8577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress dhcpServerIdentifier, String domainName) { 8587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpAckPacket( 8597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId, broadcast, serverIpAddr, clientIpAddr, mac); 8607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mGateway = gateway; 8617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDnsServers = dnsServers; 8627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mLeaseTime = timeout; 8637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDomainName = domainName; 8647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mSubnetMask = netMask; 8657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = dhcpServerIdentifier; 8667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mBroadcastAddress = bcAddr; 8677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 8687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-NAK packet from the required specified parameters. 8727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildNakPacket(int encap, int transactionId, 8747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) { 8757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr, 8767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt serverIpAddr, serverIpAddr, serverIpAddr, mac); 8777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mMessage = "requested address not available"; 8787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedIp = clientIpAddr; 8797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 8807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 8837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-REQUEST packet from the required specified parameters. 8847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 8857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildRequestPacket(int encap, 8867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int transactionId, InetAddress clientIp, boolean broadcast, 8877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac, InetAddress requestedIpAddress, 8887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt InetAddress serverIdentifier, byte[] requestedParams, String hostName) { 8897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp, 8907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac, broadcast); 8917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedIp = requestedIpAddress; 8927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = serverIdentifier; 8937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mHostName = hostName; 8947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedParams = requestedParams; 8957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 8967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return result; 8977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt} 899