17da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttpackage android.net.dhcp; 27da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 386bff86778d006d59a36bb10c7a577d982934402Lorenzo Colittiimport android.net.DhcpResults; 486bff86778d006d59a36bb10c7a577d982934402Lorenzo Colittiimport android.net.LinkAddress; 586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colittiimport android.net.NetworkUtils; 66241874355c0e0d9ff04e993ad1d522c66b8c50bHugo Benichiimport android.net.metrics.DhcpErrorEvent; 786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colittiimport android.os.Build; 886bff86778d006d59a36bb10c7a577d982934402Lorenzo Colittiimport android.os.SystemProperties; 97f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colittiimport android.system.OsConstants; 10511818ffb3a21de86d02ccc29e3c1c92d75c81c4Erik Klineimport android.text.TextUtils; 11e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichiimport com.android.internal.annotations.VisibleForTesting; 127f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti 1306ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colittiimport java.io.UnsupportedEncodingException; 1451697effe9567a144532190ad534370a00c15996Lorenzo Colittiimport java.net.Inet4Address; 157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.net.UnknownHostException; 16fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colittiimport java.nio.BufferUnderflowException; 177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ByteBuffer; 187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ByteOrder; 197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.nio.ShortBuffer; 20e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichiimport java.nio.charset.StandardCharsets; 217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.util.ArrayList; 22eca9b9bd8b9a4d0a2de8af8edc20834dd46b98b3Lorenzo Colittiimport java.util.Arrays; 237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnuttimport java.util.List; 247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt/** 267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Defines basic data and operations needed to build and use packets for the 277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP protocol. Subclasses create the specific packets used at each 287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * stage of the negotiation. 29473355f96b91a1fbeb6f8f8f0bcd3c887da12f40Erik Kline * 30473355f96b91a1fbeb6f8f8f0bcd3c887da12f40Erik Kline * @hide 317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 32473355f96b91a1fbeb6f8f8f0bcd3c887da12f40Erik Klinepublic abstract class DhcpPacket { 337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final String TAG = "DhcpPacket"; 347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 35d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti // dhcpcd has a minimum lease of 20 seconds, but DhcpStateMachine would refuse to wake up the 36d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti // CPU for anything shorter than 5 minutes. For sanity's sake, this must be higher than the 37d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti // DHCP client timeout. 38d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti public static final int MINIMUM_LEASE = 60; 39d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti public static final int INFINITE_LEASE = (int) 0xffffffff; 40d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti 4151697effe9567a144532190ad534370a00c15996Lorenzo Colitti public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY; 4251697effe9567a144532190ad534370a00c15996Lorenzo Colitti public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL; 437f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti public static final byte[] ETHER_BROADCAST = new byte[] { 447f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti (byte) 0xff, (byte) 0xff, (byte) 0xff, 457f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti (byte) 0xff, (byte) 0xff, (byte) 0xff, 467f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti }; 4751697effe9567a144532190ad534370a00c15996Lorenzo Colitti 487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Packet encapsulations. 507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_L2 = 0; // EthernetII header included 527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_L3 = 1; // IP/UDP header included 537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static final int ENCAP_BOOTP = 2; // BOOTP contents only 547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 56b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti * Minimum length of a DHCP packet, excluding options, in the above encapsulations. 57b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti */ 58b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti public static final int MIN_PACKET_LENGTH_BOOTP = 236; // See diagram in RFC 2131, section 2. 59b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8; 60b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14; 61b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 62d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti public static final int HWADDR_LEN = 16; 6306ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti public static final int MAX_OPTION_LEN = 255; 6477fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti 6577fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti /** 6677fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti * The minimum and maximum MTU that we are prepared to use. We set the minimum to the minimum 6777fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti * IPv6 MTU because the IPv6 stack enters unusual codepaths when the link MTU drops below 1280, 6877fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti * and does not recover if the MTU is brought above 1280 again. We set the maximum to 1500 6977fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti * because in general it is risky to assume that the hardware is able to send/receive packets 7077fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti * larger than 1500 bytes even if the network supports it. 7177fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti */ 7277fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti private static final int MIN_MTU = 1280; 7377fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti private static final int MAX_MTU = 1500; 7477fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti 75b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti /** 767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP layer definitions. 777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TYPE_UDP = (byte) 0x11; 797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: Version 4, Header Length 20 bytes 827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45; 847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: Flags 0, Fragment Offset 0, Don't Fragment 877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final short IP_FLAGS_OFFSET = (short) 0x4000; 897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: TOS 927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TOS_LOWDELAY = (byte) 0x10; 947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * IP: TTL -- use default 64 from RFC1340 977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private static final byte IP_TTL = (byte) 0x40; 997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The client DHCP port. 1027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt static final short DHCP_CLIENT = (short) 68; 1047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The server DHCP port. 1077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt static final short DHCP_SERVER = (short) 67; 1097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The message op code indicating a request from a client. 1127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BOOTREQUEST = (byte) 1; 1147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The message op code indicating a response from the server. 1177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BOOTREPLY = (byte) 2; 1197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The code type used to identify an Ethernet MAC address in the 1227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Client-ID field. 1237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte CLIENT_ID_ETHER = (byte) 1; 1257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The maximum length of a packet that can be constructed. 1287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final int MAX_LENGTH = 1500; 1307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 132496906ee7008b72619f230c65f103533d4d2d68aErik Kline * The magic cookie that identifies this as a DHCP packet instead of BOOTP. 133496906ee7008b72619f230c65f103533d4d2d68aErik Kline */ 134496906ee7008b72619f230c65f103533d4d2d68aErik Kline private static final int DHCP_MAGIC_COOKIE = 0x63825363; 135496906ee7008b72619f230c65f103533d4d2d68aErik Kline 136496906ee7008b72619f230c65f103533d4d2d68aErik Kline /** 1377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Subnet Mask 1387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_SUBNET_MASK = 1; 14051697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected Inet4Address mSubnetMask; 1417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Router 1447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_ROUTER = 3; 146025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti protected List <Inet4Address> mGateways; 1477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP DNS Server 1507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_DNS_SERVER = 6; 15251697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected List<Inet4Address> mDnsServers; 1537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Host Name 1567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_HOST_NAME = 12; 1587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mHostName; 1597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP DOMAIN NAME 1627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_DOMAIN_NAME = 15; 1647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mDomainName; 1657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 167fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * DHCP Optional Type: DHCP Interface MTU 168fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti */ 169fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static final byte DHCP_MTU = 26; 170fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected Short mMtu; 171fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 172fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti /** 1737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP BROADCAST ADDRESS 1747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_BROADCAST_ADDRESS = 28; 17651697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected Inet4Address mBroadcastAddress; 1777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 179b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti * DHCP Optional Type: Vendor specific information 180b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti */ 181b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti protected static final byte DHCP_VENDOR_INFO = 43; 182b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti protected String mVendorInfo; 183b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti 184b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti /** 1857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Requested IP Address 1867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_REQUESTED_IP = 50; 18851697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected Inet4Address mRequestedIp; 1897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Lease Time 1927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_LEASE_TIME = 51; 1947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected Integer mLeaseTime; 1957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 1967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 1977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Message Type 1987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 1997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE = 53; 2007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // the actual type values 2017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; 2027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2; 2037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; 2047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; 2057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_ACK = 5; 2067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_NAK = 6; 2077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8; 2087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Server Identifier 2117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_SERVER_IDENTIFIER = 54; 21351697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected Inet4Address mServerIdentifier; 2147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Parameter List 2177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_PARAMETER_LIST = 55; 2197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected byte[] mRequestedParams; 2207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP MESSAGE 2237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_MESSAGE = 56; 2257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected String mMessage; 2267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 228fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * DHCP Optional Type: Maximum DHCP Message Size 229fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti */ 230fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; 231fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected Short mMaxMessageSize; 232fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 233fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti /** 2347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Renewal Time Value 2357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_RENEWAL_TIME = 58; 237fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected Integer mT1; 238fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 239fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti /** 240fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * DHCP Optional Type: Rebinding Time Value 241fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti */ 242fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static final byte DHCP_REBINDING_TIME = 59; 243fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected Integer mT2; 2447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: Vendor Class Identifier 2477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_VENDOR_CLASS_ID = 60; 24986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti protected String mVendorId; 2507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP Optional Type: DHCP Client Identifier 2537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected static final byte DHCP_CLIENT_IDENTIFIER = 61; 2557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 257b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti * DHCP zero-length option code: pad 258b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti */ 259b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti protected static final byte DHCP_OPTION_PAD = 0x00; 260b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti 261b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti /** 262b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti * DHCP zero-length option code: end of options 263b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti */ 264b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti protected static final byte DHCP_OPTION_END = (byte) 0xff; 265b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti 266b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti /** 2677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The transaction identifier used in this particular DHCP negotiation 2687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final int mTransId; 2707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2723e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti * The seconds field in the BOOTP header. Per RFC, should be nonzero in client requests only. 2733e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti */ 2743e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti protected final short mSecs; 2753e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti 2763e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti /** 2777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The IP address of the client host. This address is typically 2787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * proposed by the client (from an earlier DHCP negotiation) or 2797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * supplied by the server. 2807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 28151697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected final Inet4Address mClientIp; 28251697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected final Inet4Address mYourIp; 28351697effe9567a144532190ad534370a00c15996Lorenzo Colitti private final Inet4Address mNextIp; 28451697effe9567a144532190ad534370a00c15996Lorenzo Colitti private final Inet4Address mRelayIp; 2857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Does the client request a broadcast response? 2887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected boolean mBroadcast; 2907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * The six-octet MAC of the client. 2937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 2947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt protected final byte[] mClientMac; 2957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 2967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 2977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Asks the packet object to create a ByteBuffer serialization of 2987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * the packet for transmission. 2997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 3007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public abstract ByteBuffer buildPacket(int encap, short destUdp, 3017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short srcUdp); 3027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 3047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Allows the concrete class to fill in packet-type-specific details, 3057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * typically optional parameters at the end of the packet. 3067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 3077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt abstract void finishPacket(ByteBuffer buffer); 3087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3096c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti // Set in unit tests, to ensure that the test does not break when run on different devices and 3106c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti // on different releases. 3116c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti static String testOverrideVendorId = null; 3126c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti static String testOverrideHostname = null; 3136c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti 3143e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, 31551697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address nextIp, Inet4Address relayIp, 3167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac, boolean broadcast) { 3177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mTransId = transId; 3183e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti mSecs = secs; 3197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mClientIp = clientIp; 3207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mYourIp = yourIp; 3217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mNextIp = nextIp; 3227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mRelayIp = relayIp; 3237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mClientMac = clientMac; 3247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt mBroadcast = broadcast; 3257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 3287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Returns the transaction ID. 3297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 3307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public int getTransactionId() { 3317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return mTransId; 3327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 3337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 33586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti * Returns the client MAC. 33686bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti */ 33786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti public byte[] getClientMac() { 33886bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti return mClientMac; 33986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 34086bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti 34186bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti /** 342f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti * Returns the client ID. This follows RFC 2132 and is based on the hardware address. 343f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti */ 344f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti public byte[] getClientId() { 345f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti byte[] clientId = new byte[mClientMac.length + 1]; 346f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti clientId[0] = CLIENT_ID_ETHER; 347f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length); 348f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti return clientId; 349f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti } 350f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti 351f443bfc25e80ef46aedd616d4ecb4c95abd7be7aLorenzo Colitti /** 3527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Creates a new L3 packet (including IP header) containing the 3537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * DHCP udp packet. This method relies upon the delegated method 3547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * finishPacket() to insert the per-packet contents. 3557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 35651697effe9567a144532190ad534370a00c15996Lorenzo Colitti protected void fillInPacket(int encap, Inet4Address destIp, 35751697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf, 3587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte requestCode, boolean broadcast) { 3597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] destIpArray = destIp.getAddress(); 3607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] srcIpArray = srcIp.getAddress(); 3617f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti int ipHeaderOffset = 0; 3627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int ipLengthOffset = 0; 3637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int ipChecksumOffset = 0; 3647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int endIpHeader = 0; 3657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpHeaderOffset = 0; 3667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpLengthOffset = 0; 3677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpChecksumOffset = 0; 3687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.clear(); 3707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.order(ByteOrder.BIG_ENDIAN); 3717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3727f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti if (encap == ENCAP_L2) { 3737f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti buf.put(ETHER_BROADCAST); 3747f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti buf.put(mClientMac); 3757f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti buf.putShort((short) OsConstants.ETH_P_IP); 3767f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti } 3777f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti 3787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // if a full IP packet needs to be generated, put the IP & UDP 3797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // headers in place, and pre-populate with artificial values 3807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // needed to seed the IP checksum. 3817f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti if (encap <= ENCAP_L3) { 3827f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti ipHeaderOffset = buf.position(); 3837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_VERSION_HEADER_LEN); 3847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY 3857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipLengthOffset = buf.position(); 3867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short)0); // length 3877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short)0); // id 3887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment 3897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TTL); // TTL: use default 64 from RFC1340 3907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(IP_TYPE_UDP); 3917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipChecksumOffset = buf.position(); 3927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // checksum 3937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(srcIpArray); 3957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(destIpArray); 3967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt endIpHeader = buf.position(); 3977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 3987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // UDP header 3997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpHeaderOffset = buf.position(); 4007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(srcUdp); 4017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(destUdp); 4027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpLengthOffset = buf.position(); 4037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // length 4047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpChecksumOffset = buf.position(); 4057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0); // UDP checksum -- initially zero 4067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // DHCP payload 4097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(requestCode); 4107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 1); // Hardware Type: Ethernet 4117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) mClientMac.length); // Hardware Address Length 4127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0); // Hop Count 4137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putInt(mTransId); // Transaction ID 4143e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti buf.putShort(mSecs); // Elapsed Seconds 4157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (broadcast) { 4177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0x8000); // Flags 4187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } else { 4197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort((short) 0x0000); // Flags 4207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mClientIp.getAddress()); 4237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mYourIp.getAddress()); 4247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mNextIp.getAddress()); 4257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mRelayIp.getAddress()); 4267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(mClientMac); 4277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(buf.position() + 428d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti (HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes 4297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 64 // empty server host name (64 bytes) 4307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 128); // empty boot file name (128 bytes) 431496906ee7008b72619f230c65f103533d4d2d68aErik Kline buf.putInt(DHCP_MAGIC_COOKIE); // magic number 4327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt finishPacket(buf); 4337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // round up to an even number of octets 4357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if ((buf.position() & 1) == 1) { 4367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0); 4377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4397da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // If an IP packet is being built, the IP & UDP checksums must be 4407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // computed. 4417f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti if (encap <= ENCAP_L3) { 4427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix UDP header: insert length 4437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpLen = (short)(buf.position() - udpHeaderOffset); 4447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(udpLengthOffset, udpLen); 4457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix UDP header: checksum 4467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // checksum for UDP at udpChecksumOffset 4477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int udpSeed = 0; 4487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // apply IPv4 pseudo-header. Read IP address src and destination 4507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // values from the IP header and accumulate checksum. 4517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2)); 4527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4)); 4537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6)); 4547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8)); 4557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // accumulate extra data for the pseudo-header 4577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += IP_TYPE_UDP; 4587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpSeed += udpLen; 4597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // and compute UDP checksum 4607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed, 4617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt udpHeaderOffset, 4627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position())); 4637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fix IP header: insert length 4647f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti buf.putShort(ipLengthOffset, (short)(buf.position() - ipHeaderOffset)); 4657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // fixup IP-header checksum 4667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putShort(ipChecksumOffset, 4677f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti (short) checksum(buf, 0, ipHeaderOffset, endIpHeader)); 4687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Converts a signed short value to an unsigned int value. Needed 4737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * because Java does not have unsigned types. 4747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 475b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti private static int intAbs(short v) { 476b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti return v & 0xFFFF; 4777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 4787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 4807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Performs an IP checksum (used in IP header and across UDP 4817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * payload) on the specified portion of a ByteBuffer. The seed 4827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * allows the checksum to commence with a specified value. 4837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 4847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt private int checksum(ByteBuffer buf, int seed, int start, int end) { 4857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int sum = seed; 4867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int bufPosition = buf.position(); 4877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // set position of original ByteBuffer, so that the ShortBuffer 4897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // will be correctly initialized 4907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(start); 4917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ShortBuffer shortBuf = buf.asShortBuffer(); 4927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // re-set ByteBuffer position 4947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.position(bufPosition); 4957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short[] shortArray = new short[(end - start) / 2]; 4977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt shortBuf.get(shortArray); 4987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 4997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (short s : shortArray) { 5007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum += intAbs(s); 5017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt start += shortArray.length * 2; 5047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // see if a singleton byte remains 5067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (end != start) { 5077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short b = buf.get(start); 5087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // make it unsigned 5107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (b < 0) { 5117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt b += 256; 5127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum += b * 256; 5157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); 5187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF); 5197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int negated = ~sum; 5207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return intAbs((short) negated); 5217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a single byte value. 5257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 526fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, byte value) { 5277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 5287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 1); 5297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(value); 5307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing an array of bytes. 5347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 535fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) { 5367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (payload != null) { 53706ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti if (payload.length > MAX_OPTION_LEN) { 53806ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti throw new IllegalArgumentException("DHCP option too long: " 53906ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti + payload.length + " vs. " + MAX_OPTION_LEN); 54006ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti } 5417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 5427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) payload.length); 5437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(payload); 5447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing an IP address. 5497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 550fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) { 5517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (addr != null) { 5527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt addTlv(buf, type, addr.getAddress()); 5537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 5577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a list of IP addresses. 5587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 559fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) { 56006ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti if (addrs == null || addrs.size() == 0) return; 5617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 56206ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti int optionLen = 4 * addrs.size(); 56306ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti if (optionLen > MAX_OPTION_LEN) { 56406ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti throw new IllegalArgumentException("DHCP option too long: " 56506ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti + optionLen + " vs. " + MAX_OPTION_LEN); 56606ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti } 56706ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti 56806ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti buf.put(type); 56906ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti buf.put((byte)(optionLen)); 57006ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti 57106ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti for (Inet4Address addr : addrs) { 57206ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti buf.put(addr.getAddress()); 5737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 577fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * Adds an optional parameter containing a short integer 578fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti */ 579fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, Short value) { 580fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti if (value != null) { 581fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti buf.put(type); 582fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti buf.put((byte) 2); 583fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti buf.putShort(value.shortValue()); 584fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti } 585fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti } 586fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 587fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti /** 5887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds an optional parameter containing a simple integer 5897da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 590fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, Integer value) { 5917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (value != null) { 5927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put(type); 5937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 4); 5947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.putInt(value.intValue()); 5957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 5977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 5987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 59906ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti * Adds an optional parameter containing an ASCII string. 6007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 601fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlv(ByteBuffer buf, byte type, String str) { 60206ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti try { 60306ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti addTlv(buf, type, str.getBytes("US-ASCII")); 60406ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti } catch (UnsupportedEncodingException e) { 60506ac4b8dd1877d8a82103f11c236f1527b692f94Lorenzo Colitti throw new IllegalArgumentException("String is not US-ASCII: " + str); 6067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 6107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Adds the special end-of-optional-parameters indicator. 6117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 612fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected static void addTlvEnd(ByteBuffer buf) { 6137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.put((byte) 0xFF); 6147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6166c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti private String getVendorId() { 6176c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti if (testOverrideVendorId != null) return testOverrideVendorId; 6186c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti return "android-dhcp-" + Build.VERSION.RELEASE; 6196c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti } 6206c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti 6216c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti private String getHostname() { 6226c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti if (testOverrideHostname != null) return testOverrideHostname; 6236c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti return SystemProperties.get("net.hostname"); 6246c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti } 6256c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti 6267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 627fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * Adds common client TLVs. 628fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * 629fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket 630fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti * methods to take them. 631fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti */ 632fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti protected void addCommonClientTlvs(ByteBuffer buf) { 633fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); 6346c7acb6ec7494235dd80d972fb3db0f7b48fb4fcLorenzo Colitti addTlv(buf, DHCP_VENDOR_CLASS_ID, getVendorId()); 635511818ffb3a21de86d02ccc29e3c1c92d75c81c4Erik Kline final String hn = getHostname(); 636511818ffb3a21de86d02ccc29e3c1c92d75c81c4Erik Kline if (!TextUtils.isEmpty(hn)) addTlv(buf, DHCP_HOST_NAME, hn); 637fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti } 638fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 639fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti /** 6407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Converts a MAC from an array of octets to an ASCII string. 6417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 6427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static String macToString(byte[] mac) { 6437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String macAddr = ""; 6447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt for (int i = 0; i < mac.length; i++) { 6467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String hexString = "0" + Integer.toHexString(mac[i]); 6477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // substring operation grabs the last 2 digits: this 6497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // allows signed bytes to be converted correctly. 6507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt macAddr += hexString.substring(hexString.length() - 2); 6517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (i != (mac.length - 1)) { 6537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt macAddr += ":"; 6547da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return macAddr; 6587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6597da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public String toString() { 6617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String macAddr = macToString(mClientMac); 6627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return macAddr; 6647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 6677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Reads a four-octet value from a ByteBuffer and construct 6687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * an IPv4 address from that value. 6697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 67051697effe9567a144532190ad534370a00c15996Lorenzo Colitti private static Inet4Address readIpAddress(ByteBuffer packet) { 67151697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address result = null; 6727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] ipAddr = new byte[4]; 6737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipAddr); 6747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt try { 67651697effe9567a144532190ad534370a00c15996Lorenzo Colitti result = (Inet4Address) Inet4Address.getByAddress(ipAddr); 6777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } catch (UnknownHostException ex) { 6787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // ipAddr is numeric, so this should not be 6797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // triggered. However, if it is, just nullify 6807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt result = null; 6817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return result; 6847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 6857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 6867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 6877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Reads a string of specified length from the buffer. 6887da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 689a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti private static String readAsciiString(ByteBuffer buf, int byteCount, boolean nullOk) { 6907da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] bytes = new byte[byteCount]; 6917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt buf.get(bytes); 692a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti int length = bytes.length; 693a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti if (!nullOk) { 694a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti // Stop at the first null byte. This is because some DHCP options (e.g., the domain 695a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti // name) are passed to netd via FrameworkListener, which refuses arguments containing 696a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti // null bytes. We don't do this by default because vendorInfo is an opaque string which 697a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti // could in theory contain null bytes. 698a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti for (length = 0; length < bytes.length; length++) { 699a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti if (bytes[length] == 0) { 700a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti break; 701a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti } 702a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti } 703a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti } 704a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti return new String(bytes, 0, length, StandardCharsets.US_ASCII); 7057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 707b19238c48814c5a1438b1238794e121876ae89abErik Kline private static boolean isPacketToOrFromClient(short udpSrcPort, short udpDstPort) { 708b19238c48814c5a1438b1238794e121876ae89abErik Kline return (udpSrcPort == DHCP_CLIENT) || (udpDstPort == DHCP_CLIENT); 709b19238c48814c5a1438b1238794e121876ae89abErik Kline } 710b19238c48814c5a1438b1238794e121876ae89abErik Kline 711b19238c48814c5a1438b1238794e121876ae89abErik Kline private static boolean isPacketServerToServer(short udpSrcPort, short udpDstPort) { 712b19238c48814c5a1438b1238794e121876ae89abErik Kline return (udpSrcPort == DHCP_SERVER) && (udpDstPort == DHCP_SERVER); 713b19238c48814c5a1438b1238794e121876ae89abErik Kline } 714b19238c48814c5a1438b1238794e121876ae89abErik Kline 715496906ee7008b72619f230c65f103533d4d2d68aErik Kline public static class ParseException extends Exception { 7162677b1957b444e2dae5737feee989109b811547cHugo Benichi public final int errorCode; 7172677b1957b444e2dae5737feee989109b811547cHugo Benichi public ParseException(int errorCode, String msg, Object... args) { 718496906ee7008b72619f230c65f103533d4d2d68aErik Kline super(String.format(msg, args)); 7192677b1957b444e2dae5737feee989109b811547cHugo Benichi this.errorCode = errorCode; 720496906ee7008b72619f230c65f103533d4d2d68aErik Kline } 721496906ee7008b72619f230c65f103533d4d2d68aErik Kline } 722496906ee7008b72619f230c65f103533d4d2d68aErik Kline 7237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 7247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Creates a concrete DhcpPacket from the supplied ByteBuffer. The 7257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * buffer may have an L2 encapsulation (which is the full EthernetII 7267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * format starting with the source-address MAC) or an L3 encapsulation 7277da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * (which starts with the IP header). 7287da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * <br> 7297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * A subset of the optional parameters are parsed and are stored 7307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * in object fields. 7317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 732e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi @VisibleForTesting 733e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException 7347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt { 7357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // bootp parameters 7367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt int transactionId; 7373e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti short secs; 73851697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address clientIp; 73951697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address yourIp; 74051697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address nextIp; 74151697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address relayIp; 7427da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] clientMac; 743025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti List<Inet4Address> dnsServers = new ArrayList<>(); 744025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti List<Inet4Address> gateways = new ArrayList<>(); // aka router 74551697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address serverIdentifier = null; 74651697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address netMask = null; 7477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String message = null; 7487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String vendorId = null; 749b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti String vendorInfo = null; 7507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] expectedParams = null; 7517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String hostName = null; 7527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt String domainName = null; 75351697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address ipSrc = null; 75451697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address ipDst = null; 75551697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address bcAddr = null; 75651697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address requestedIp = null; 7577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 758fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti // The following are all unsigned integers. Internally we store them as signed integers of 759fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti // the same length because that way we're guaranteed that they can't be out of the range of 760fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need 761fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti // to cast it. 762fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti Short mtu = null; 763fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti Short maxMessageSize = null; 764fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti Integer leaseTime = null; 765fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti Integer T1 = null; 766fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti Integer T2 = null; 767fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti 7687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // dhcp options 7697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte dhcpType = (byte) 0xFF; 7707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.order(ByteOrder.BIG_ENDIAN); 7727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // check to see if we need to parse L2, IP, and UDP encaps 7747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt if (pktType == ENCAP_L2) { 775b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti if (packet.remaining() < MIN_PACKET_LENGTH_L2) { 7762677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.L2_TOO_SHORT, 7772677b1957b444e2dae5737feee989109b811547cHugo Benichi "L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2); 778b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 779b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 7807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] l2dst = new byte[6]; 7817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] l2src = new byte[6]; 7827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(l2dst); 7847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(l2src); 7857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short l2type = packet.getShort(); 7877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 7886241874355c0e0d9ff04e993ad1d522c66b8c50bHugo Benichi if (l2type != OsConstants.ETH_P_IP) { 7892677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.L2_WRONG_ETH_TYPE, 7902677b1957b444e2dae5737feee989109b811547cHugo Benichi "Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP); 7916241874355c0e0d9ff04e993ad1d522c66b8c50bHugo Benichi } 7927da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 7937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 794fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti if (pktType <= ENCAP_L3) { 795b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti if (packet.remaining() < MIN_PACKET_LENGTH_L3) { 7962677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.L3_TOO_SHORT, 7972677b1957b444e2dae5737feee989109b811547cHugo Benichi "L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3); 798b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 799b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 8007f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti byte ipTypeAndLength = packet.get(); 8017f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti int ipVersion = (ipTypeAndLength & 0xf0) >> 4; 8027f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti if (ipVersion != 4) { 8032677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException( 8042677b1957b444e2dae5737feee989109b811547cHugo Benichi DhcpErrorEvent.L3_NOT_IPV4, "Invalid IP version %d", ipVersion); 8057f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti } 8067f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti 8077da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // System.out.println("ipType is " + ipType); 8087da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipDiffServicesField = packet.get(); 8097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipTotalLength = packet.getShort(); 8107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipIdentification = packet.getShort(); 8117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipFlags = packet.get(); 8127da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipFragOffset = packet.get(); 8137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipTTL = packet.get(); 8147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte ipProto = packet.get(); 8157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short ipChksm = packet.getShort(); 8167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipSrc = readIpAddress(packet); 8187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ipDst = readIpAddress(packet); 8197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 820496906ee7008b72619f230c65f103533d4d2d68aErik Kline if (ipProto != IP_TYPE_UDP) { 8212677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException( 8222677b1957b444e2dae5737feee989109b811547cHugo Benichi DhcpErrorEvent.L4_NOT_UDP, "Protocol not UDP: %d", ipProto); 823496906ee7008b72619f230c65f103533d4d2d68aErik Kline } 8247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 825b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti // Skip options. This cannot cause us to read beyond the end of the buffer because the 826b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti // IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than 827b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti // MIN_PACKET_LENGTH_L3. 8287f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti int optionWords = ((ipTypeAndLength & 0x0f) - 5); 8297f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti for (int i = 0; i < optionWords; i++) { 8307f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti packet.getInt(); 8317f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti } 8327f7cc6115914b4a0ebd99c5d77db8f571195a1fbLorenzo Colitti 8337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // assume UDP 8347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpSrcPort = packet.getShort(); 8357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpDstPort = packet.getShort(); 8367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpLen = packet.getShort(); 8377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short udpChkSum = packet.getShort(); 8387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 839b19238c48814c5a1438b1238794e121876ae89abErik Kline // Only accept packets to or from the well-known client port (expressly permitting 840b19238c48814c5a1438b1238794e121876ae89abErik Kline // packets from ports other than the well-known server port; http://b/24687559), and 841b19238c48814c5a1438b1238794e121876ae89abErik Kline // server-to-server packets, e.g. for relays. 842b19238c48814c5a1438b1238794e121876ae89abErik Kline if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) && 843b19238c48814c5a1438b1238794e121876ae89abErik Kline !isPacketServerToServer(udpSrcPort, udpDstPort)) { 844f55c9c1781d1bf24360bc1cb3d2c41fb8a9d6107Lorenzo Colitti // This should almost never happen because we use SO_ATTACH_FILTER on the packet 845f55c9c1781d1bf24360bc1cb3d2c41fb8a9d6107Lorenzo Colitti // socket to drop packets that don't have the right source ports. However, it's 846f55c9c1781d1bf24360bc1cb3d2c41fb8a9d6107Lorenzo Colitti // possible that a packet arrives between when the socket is bound and when the 847f55c9c1781d1bf24360bc1cb3d2c41fb8a9d6107Lorenzo Colitti // filter is set. http://b/26696823 . 8482677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.L4_WRONG_PORT, 8492677b1957b444e2dae5737feee989109b811547cHugo Benichi "Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort); 850496906ee7008b72619f230c65f103533d4d2d68aErik Kline } 8517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 853b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. 854b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { 8552677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.BOOTP_TOO_SHORT, 8562677b1957b444e2dae5737feee989109b811547cHugo Benichi "Invalid type or BOOTP packet too short, %d < %d", 857496906ee7008b72619f230c65f103533d4d2d68aErik Kline packet.remaining(), MIN_PACKET_LENGTH_BOOTP); 858b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 859b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 8607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte type = packet.get(); 8617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte hwType = packet.get(); 862d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti int addrLen = packet.get() & 0xff; 8637da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte hops = packet.get(); 8647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt transactionId = packet.getInt(); 8653e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti secs = packet.getShort(); 8667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt short bootpFlags = packet.getShort(); 8677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean broadcast = (bootpFlags & 0x8000) != 0; 8687da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt byte[] ipv4addr = new byte[4]; 8697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt try { 8717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 87251697effe9567a144532190ad534370a00c15996Lorenzo Colitti clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 8737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 87451697effe9567a144532190ad534370a00c15996Lorenzo Colitti yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 8757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 87651697effe9567a144532190ad534370a00c15996Lorenzo Colitti nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 8777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(ipv4addr); 87851697effe9567a144532190ad534370a00c15996Lorenzo Colitti relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 8797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } catch (UnknownHostException ex) { 8802677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.L3_INVALID_IP, 8812677b1957b444e2dae5737feee989109b811547cHugo Benichi "Invalid IPv4 address: %s", Arrays.toString(ipv4addr)); 8827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 8837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 884d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // Some DHCP servers have been known to announce invalid client hardware address values such 885d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // as 0xff. The legacy DHCP client accepted these becuause it does not check the length at 886d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // all but only checks that the interface MAC address matches the first bytes of the address 887d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // in the packets. We're a bit stricter: if the length is obviously invalid (i.e., bigger 888d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // than the size of the field), we fudge it to 6 (Ethernet). http://b/23725795 889d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti // TODO: evaluate whether to make this test more liberal. 890d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti if (addrLen > HWADDR_LEN) { 891d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti addrLen = ETHER_BROADCAST.length; 892d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti } 893d64144a37ca0a6f341c0092cc04271831ff5f90dLorenzo Colitti 8947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac = new byte[addrLen]; 8957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.get(clientMac); 8967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 8977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // skip over address padding (16 octets allocated) 8987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt packet.position(packet.position() + (16 - addrLen) 8997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 64 // skip server host name (64 chars) 9007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt + 128); // skip boot file name (128 chars) 9017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 902006e0613016c1a0e0627f992f5a93a7b7198edbaHugo Benichi // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211 903006e0613016c1a0e0627f992f5a93a7b7198edbaHugo Benichi if (packet.remaining() < 4) { 904006e0613016c1a0e0627f992f5a93a7b7198edbaHugo Benichi throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message"); 905006e0613016c1a0e0627f992f5a93a7b7198edbaHugo Benichi } 9067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 907006e0613016c1a0e0627f992f5a93a7b7198edbaHugo Benichi int dhcpMagicCookie = packet.getInt(); 908496906ee7008b72619f230c65f103533d4d2d68aErik Kline if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) { 9092677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE, 9102677b1957b444e2dae5737feee989109b811547cHugo Benichi "Bad magic cookie 0x%08x, should be 0x%08x", 9112677b1957b444e2dae5737feee989109b811547cHugo Benichi dhcpMagicCookie, DHCP_MAGIC_COOKIE); 912496906ee7008b72619f230c65f103533d4d2d68aErik Kline } 9137da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 9147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt // parse options 9157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt boolean notFinishedOptions = true; 9167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 9177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt while ((packet.position() < packet.limit()) && notFinishedOptions) { 9186241874355c0e0d9ff04e993ad1d522c66b8c50bHugo Benichi final byte optionType = packet.get(); // cannot underflow because position < limit 919b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti try { 920b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti if (optionType == DHCP_OPTION_END) { 921b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti notFinishedOptions = false; 922b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti } else if (optionType == DHCP_OPTION_PAD) { 923b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti // The pad option doesn't have a length field. Nothing to do. 924b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } else { 925b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti int optionLen = packet.get() & 0xFF; 926b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti int expectedLen = 0; 927b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 928b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti switch(optionType) { 929b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_SUBNET_MASK: 930b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti netMask = readIpAddress(packet); 931b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 932b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 933b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_ROUTER: 934025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { 935025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti gateways.add(readIpAddress(packet)); 936025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti } 937b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 938b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_DNS_SERVER: 939b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { 940b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti dnsServers.add(readIpAddress(packet)); 941b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 942b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 943b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_HOST_NAME: 944b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 945a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti hostName = readAsciiString(packet, optionLen, false); 946b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 947b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_MTU: 948b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 2; 94977fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti mtu = packet.getShort(); 950b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 951b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_DOMAIN_NAME: 952b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 953a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti domainName = readAsciiString(packet, optionLen, false); 954b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 955b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_BROADCAST_ADDRESS: 956b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti bcAddr = readIpAddress(packet); 957b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 958b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 959b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_REQUESTED_IP: 960b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti requestedIp = readIpAddress(packet); 961b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 962b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 963b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_LEASE_TIME: 964b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti leaseTime = Integer.valueOf(packet.getInt()); 965b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 966b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 967b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_MESSAGE_TYPE: 968b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti dhcpType = packet.get(); 969b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 1; 970b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 971b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_SERVER_IDENTIFIER: 972b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti serverIdentifier = readIpAddress(packet); 973b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 974b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 975b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_PARAMETER_LIST: 976b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedParams = new byte[optionLen]; 977b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti packet.get(expectedParams); 978b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 979b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 980b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_MESSAGE: 981b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 982a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti message = readAsciiString(packet, optionLen, false); 983b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 984b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_MAX_MESSAGE_SIZE: 985b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 2; 986b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti maxMessageSize = Short.valueOf(packet.getShort()); 987b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 988b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_RENEWAL_TIME: 989b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 990b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti T1 = Integer.valueOf(packet.getInt()); 991b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 992b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_REBINDING_TIME: 993b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = 4; 994b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti T2 = Integer.valueOf(packet.getInt()); 995b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 996b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_VENDOR_CLASS_ID: 997b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 998b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti // Embedded nulls are safe as this does not get passed to netd. 999a12bde35672c45af7bca8170ee1a3b3370bec30eLorenzo Colitti vendorId = readAsciiString(packet, optionLen, true); 1000b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti break; 1001b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti case DHCP_CLIENT_IDENTIFIER: { // Client identifier 1002b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti byte[] id = new byte[optionLen]; 1003b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti packet.get(id); 1004b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen = optionLen; 1005b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } break; 1006b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti case DHCP_VENDOR_INFO: 1007b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti expectedLen = optionLen; 1008b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti // Embedded nulls are safe as this does not get passed to netd. 1009b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti vendorInfo = readAsciiString(packet, optionLen, true); 1010b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti break; 1011b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti default: 1012b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti // ignore any other parameters 1013b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti for (int i = 0; i < optionLen; i++) { 1014b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti expectedLen++; 1015b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti byte throwaway = packet.get(); 1016b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 1017b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 1018b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti 1019b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti if (expectedLen != optionLen) { 10202677b1957b444e2dae5737feee989109b811547cHugo Benichi final int errorCode = DhcpErrorEvent.errorCodeWithOption( 10216241874355c0e0d9ff04e993ad1d522c66b8c50bHugo Benichi DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType); 10222677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(errorCode, 10232677b1957b444e2dae5737feee989109b811547cHugo Benichi "Invalid length %d for option %d, expected %d", 1024496906ee7008b72619f230c65f103533d4d2d68aErik Kline optionLen, optionType, expectedLen); 1025b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } 10267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 1027b05c9234e644b9648ff21c991ef010df10783b0cLorenzo Colitti } catch (BufferUnderflowException e) { 10282677b1957b444e2dae5737feee989109b811547cHugo Benichi final int errorCode = DhcpErrorEvent.errorCodeWithOption( 10292677b1957b444e2dae5737feee989109b811547cHugo Benichi DhcpErrorEvent.BUFFER_UNDERFLOW, optionType); 10302677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(errorCode, "BufferUnderflowException"); 10317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 10327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 10337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 10347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket newPacket; 10357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 10367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt switch(dhcpType) { 1037496906ee7008b72619f230c65f103533d4d2d68aErik Kline case (byte) 0xFF: 10382677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE, 10392677b1957b444e2dae5737feee989109b811547cHugo Benichi "No DHCP message type option"); 10407da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_DISCOVER: 10417da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpDiscoverPacket( 10423e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientMac, broadcast); 10437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_OFFER: 10457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpOfferPacket( 1046f68edb16116307553059a889ef456227a9697918Lorenzo Colitti transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); 10477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_REQUEST: 10497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpRequestPacket( 10503e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientIp, clientMac, broadcast); 10517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10527da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_DECLINE: 10537da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpDeclinePacket( 10543e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientIp, yourIp, nextIp, relayIp, 10557da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 10567da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10577da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_ACK: 10587da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpAckPacket( 1059f68edb16116307553059a889ef456227a9697918Lorenzo Colitti transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); 10607da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10617da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_NAK: 10627da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpNakPacket( 10633e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientIp, yourIp, nextIp, relayIp, 10647da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 10657da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10667da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt case DHCP_MESSAGE_TYPE_INFORM: 10677da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket = new DhcpInformPacket( 10683e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientIp, yourIp, nextIp, relayIp, 10697da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac); 10707da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt break; 10717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt default: 10722677b1957b444e2dae5737feee989109b811547cHugo Benichi throw new ParseException(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE, 10732677b1957b444e2dae5737feee989109b811547cHugo Benichi "Unimplemented DHCP type %d", dhcpType); 10747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 10757da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 10767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mBroadcastAddress = bcAddr; 10777da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mDnsServers = dnsServers; 10787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mDomainName = domainName; 1079025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti newPacket.mGateways = gateways; 10807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mHostName = hostName; 10817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mLeaseTime = leaseTime; 10827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mMessage = message; 1083fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti newPacket.mMtu = mtu; 10847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mRequestedIp = requestedIp; 10857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mRequestedParams = expectedParams; 10867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mServerIdentifier = serverIdentifier; 10877da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt newPacket.mSubnetMask = netMask; 1088fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti newPacket.mMaxMessageSize = maxMessageSize; 1089fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti newPacket.mT1 = T1; 1090fe5ffce09c4a163ee9a190aedc9fd7cea38a576fLorenzo Colitti newPacket.mT2 = T2; 109186bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti newPacket.mVendorId = vendorId; 1092b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti newPacket.mVendorInfo = vendorInfo; 10937da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return newPacket; 10947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 10957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 10967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 109786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti * Parse a packet from an array of bytes, stopping at the given length. 10987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 109986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType) 1100496906ee7008b72619f230c65f103533d4d2d68aErik Kline throws ParseException { 110186bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN); 1102e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi try { 1103e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi return decodeFullPacket(buffer, pktType); 1104e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi } catch (ParseException e) { 1105e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi throw e; 1106e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi } catch (Exception e) { 1107e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi throw new ParseException(DhcpErrorEvent.PARSING_ERROR, e.getMessage()); 1108e0ea7fecd63002ac2d3df18490fd1c16578d1935Hugo Benichi } 11097da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 11107da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 11117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 111286bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti * Construct a DhcpResults object from a DHCP reply packet. 111386bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti */ 111486bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti public DhcpResults toDhcpResults() { 111586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti Inet4Address ipAddress = mYourIp; 1116f68edb16116307553059a889ef456227a9697918Lorenzo Colitti if (ipAddress.equals(Inet4Address.ANY)) { 111786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti ipAddress = mClientIp; 1118f68edb16116307553059a889ef456227a9697918Lorenzo Colitti if (ipAddress.equals(Inet4Address.ANY)) { 111986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti return null; 112086bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 112186bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 112286bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti 112386bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti int prefixLength; 112486bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti if (mSubnetMask != null) { 112586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti try { 112686bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti prefixLength = NetworkUtils.netmaskToPrefixLength(mSubnetMask); 112786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } catch (IllegalArgumentException e) { 112886bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti // Non-contiguous netmask. 112986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti return null; 113086bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 113186bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } else { 113286bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti prefixLength = NetworkUtils.getImplicitNetmask(ipAddress); 113386bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 113486bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti 113586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti DhcpResults results = new DhcpResults(); 113686bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti try { 113786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti results.ipAddress = new LinkAddress(ipAddress, prefixLength); 113886bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } catch (IllegalArgumentException e) { 113986bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti return null; 114086bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 1141025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti 1142025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti if (mGateways.size() > 0) { 1143025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti results.gateway = mGateways.get(0); 1144025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti } 1145025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti 114686bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti results.dnsServers.addAll(mDnsServers); 114786bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti results.domains = mDomainName; 114886bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti results.serverAddress = mServerIdentifier; 1149b0b3d0bcfb0af678d4c85bec63722f976ffb01cfLorenzo Colitti results.vendorInfo = mVendorInfo; 1150d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE; 115177fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0; 115277fdf23d6f7831c09fc43d206b346e273ebe266aLorenzo Colitti 115386bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti return results; 115486bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti } 115586bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti 115686bff86778d006d59a36bb10c7a577d982934402Lorenzo Colitti /** 1157d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti * Returns the parsed lease time, in milliseconds, or 0 for infinite. 1158d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti */ 1159d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti public long getLeaseTimeMillis() { 1160d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti // dhcpcd treats the lack of a lease time option as an infinite lease. 1161d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti if (mLeaseTime == null || mLeaseTime == INFINITE_LEASE) { 1162d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti return 0; 1163d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti } else if (0 <= mLeaseTime && mLeaseTime < MINIMUM_LEASE) { 1164d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti return MINIMUM_LEASE * 1000; 1165d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti } else { 1166d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti return (mLeaseTime & 0xffffffffL) * 1000; 1167d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti } 1168d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti } 1169d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti 1170d973537ee1bd013b4233d3369d66821e124a2e65Lorenzo Colitti /** 11717da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-DISCOVER packet from the required specified 11727da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * parameters. 11737da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 11747da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, 11753e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) { 11767da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpDiscoverPacket( 11773e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti transactionId, secs, clientMac, broadcast); 11787da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedParams = expectedParams; 11797da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 11807da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 11817da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 11827da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 11837da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-OFFER packet from the required specified 11847da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * parameters. 11857da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 11867da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildOfferPacket(int encap, int transactionId, 118751697effe9567a144532190ad534370a00c15996Lorenzo Colitti boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, 118851697effe9567a144532190ad534370a00c15996Lorenzo Colitti byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, 1189025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti List<Inet4Address> gateways, List<Inet4Address> dnsServers, 119051697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address dhcpServerIdentifier, String domainName) { 11917da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpOfferPacket( 1192f68edb16116307553059a889ef456227a9697918Lorenzo Colitti transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); 1193025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti pkt.mGateways = gateways; 11947da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDnsServers = dnsServers; 11957da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mLeaseTime = timeout; 11967da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDomainName = domainName; 11977da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = dhcpServerIdentifier; 11987da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mSubnetMask = netMask; 11997da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mBroadcastAddress = bcAddr; 12007da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 12017da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 12027da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 12037da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 12047da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-ACK packet from the required specified parameters. 12057da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 12067da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildAckPacket(int encap, int transactionId, 120751697effe9567a144532190ad534370a00c15996Lorenzo Colitti boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, 120851697effe9567a144532190ad534370a00c15996Lorenzo Colitti byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, 1209025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti List<Inet4Address> gateways, List<Inet4Address> dnsServers, 121051697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address dhcpServerIdentifier, String domainName) { 12117da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt DhcpPacket pkt = new DhcpAckPacket( 1212f68edb16116307553059a889ef456227a9697918Lorenzo Colitti transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); 1213025f4a5aae1660eda6406703771995010d9de990Lorenzo Colitti pkt.mGateways = gateways; 12147da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDnsServers = dnsServers; 12157da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mLeaseTime = timeout; 12167da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mDomainName = domainName; 12177da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mSubnetMask = netMask; 12187da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = dhcpServerIdentifier; 12197da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mBroadcastAddress = bcAddr; 12207da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 12217da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 12227da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 12237da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 12247da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-NAK packet from the required specified parameters. 12257da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 12267da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildNakPacket(int encap, int transactionId, 122751697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) { 12283e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti DhcpPacket pkt = new DhcpNakPacket(transactionId, (short) 0, clientIpAddr, 12297da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt serverIpAddr, serverIpAddr, serverIpAddr, mac); 12307da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mMessage = "requested address not available"; 12317da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedIp = clientIpAddr; 12327da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 12337da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 12347da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt 12357da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt /** 12367da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt * Builds a DHCP-REQUEST packet from the required specified parameters. 12377da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt */ 12387da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt public static ByteBuffer buildRequestPacket(int encap, 12393e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti int transactionId, short secs, Inet4Address clientIp, boolean broadcast, 124051697effe9567a144532190ad534370a00c15996Lorenzo Colitti byte[] clientMac, Inet4Address requestedIpAddress, 124151697effe9567a144532190ad534370a00c15996Lorenzo Colitti Inet4Address serverIdentifier, byte[] requestedParams, String hostName) { 12423e979321a5d96b9e2688f67ef0f936602c0f7e5aLorenzo Colitti DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp, 12437da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt clientMac, broadcast); 12447da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedIp = requestedIpAddress; 12457da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mServerIdentifier = serverIdentifier; 12467da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mHostName = hostName; 12477da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt pkt.mRequestedParams = requestedParams; 12487da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 12497da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt return result; 12507da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt } 12517da02ad3b7a8a0b13a2ccc84e666baa8e6370482Stan Chesnutt} 1252