1 package android.net.dhcp; 2 3 import android.net.DhcpResults; 4 import android.net.LinkAddress; 5 import android.net.NetworkUtils; 6 import android.net.metrics.DhcpErrorEvent; 7 import android.os.Build; 8 import android.os.SystemProperties; 9 import android.system.OsConstants; 10 import com.android.internal.annotations.VisibleForTesting; 11 12 import java.io.UnsupportedEncodingException; 13 import java.net.Inet4Address; 14 import java.net.UnknownHostException; 15 import java.nio.BufferUnderflowException; 16 import java.nio.ByteBuffer; 17 import java.nio.ByteOrder; 18 import java.nio.ShortBuffer; 19 import java.nio.charset.StandardCharsets; 20 import java.util.ArrayList; 21 import java.util.Arrays; 22 import java.util.List; 23 24 /** 25 * Defines basic data and operations needed to build and use packets for the 26 * DHCP protocol. Subclasses create the specific packets used at each 27 * stage of the negotiation. 28 */ 29 abstract class DhcpPacket { 30 protected static final String TAG = "DhcpPacket"; 31 32 // dhcpcd has a minimum lease of 20 seconds, but DhcpStateMachine would refuse to wake up the 33 // CPU for anything shorter than 5 minutes. For sanity's sake, this must be higher than the 34 // DHCP client timeout. 35 public static final int MINIMUM_LEASE = 60; 36 public static final int INFINITE_LEASE = (int) 0xffffffff; 37 38 public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY; 39 public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL; 40 public static final byte[] ETHER_BROADCAST = new byte[] { 41 (byte) 0xff, (byte) 0xff, (byte) 0xff, 42 (byte) 0xff, (byte) 0xff, (byte) 0xff, 43 }; 44 45 /** 46 * Packet encapsulations. 47 */ 48 public static final int ENCAP_L2 = 0; // EthernetII header included 49 public static final int ENCAP_L3 = 1; // IP/UDP header included 50 public static final int ENCAP_BOOTP = 2; // BOOTP contents only 51 52 /** 53 * Minimum length of a DHCP packet, excluding options, in the above encapsulations. 54 */ 55 public static final int MIN_PACKET_LENGTH_BOOTP = 236; // See diagram in RFC 2131, section 2. 56 public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8; 57 public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14; 58 59 public static final int HWADDR_LEN = 16; 60 public static final int MAX_OPTION_LEN = 255; 61 62 /** 63 * The minimum and maximum MTU that we are prepared to use. We set the minimum to the minimum 64 * IPv6 MTU because the IPv6 stack enters unusual codepaths when the link MTU drops below 1280, 65 * and does not recover if the MTU is brought above 1280 again. We set the maximum to 1500 66 * because in general it is risky to assume that the hardware is able to send/receive packets 67 * larger than 1500 bytes even if the network supports it. 68 */ 69 private static final int MIN_MTU = 1280; 70 private static final int MAX_MTU = 1500; 71 72 /** 73 * IP layer definitions. 74 */ 75 private static final byte IP_TYPE_UDP = (byte) 0x11; 76 77 /** 78 * IP: Version 4, Header Length 20 bytes 79 */ 80 private static final byte IP_VERSION_HEADER_LEN = (byte) 0x45; 81 82 /** 83 * IP: Flags 0, Fragment Offset 0, Don't Fragment 84 */ 85 private static final short IP_FLAGS_OFFSET = (short) 0x4000; 86 87 /** 88 * IP: TOS 89 */ 90 private static final byte IP_TOS_LOWDELAY = (byte) 0x10; 91 92 /** 93 * IP: TTL -- use default 64 from RFC1340 94 */ 95 private static final byte IP_TTL = (byte) 0x40; 96 97 /** 98 * The client DHCP port. 99 */ 100 static final short DHCP_CLIENT = (short) 68; 101 102 /** 103 * The server DHCP port. 104 */ 105 static final short DHCP_SERVER = (short) 67; 106 107 /** 108 * The message op code indicating a request from a client. 109 */ 110 protected static final byte DHCP_BOOTREQUEST = (byte) 1; 111 112 /** 113 * The message op code indicating a response from the server. 114 */ 115 protected static final byte DHCP_BOOTREPLY = (byte) 2; 116 117 /** 118 * The code type used to identify an Ethernet MAC address in the 119 * Client-ID field. 120 */ 121 protected static final byte CLIENT_ID_ETHER = (byte) 1; 122 123 /** 124 * The maximum length of a packet that can be constructed. 125 */ 126 protected static final int MAX_LENGTH = 1500; 127 128 /** 129 * The magic cookie that identifies this as a DHCP packet instead of BOOTP. 130 */ 131 private static final int DHCP_MAGIC_COOKIE = 0x63825363; 132 133 /** 134 * DHCP Optional Type: DHCP Subnet Mask 135 */ 136 protected static final byte DHCP_SUBNET_MASK = 1; 137 protected Inet4Address mSubnetMask; 138 139 /** 140 * DHCP Optional Type: DHCP Router 141 */ 142 protected static final byte DHCP_ROUTER = 3; 143 protected List <Inet4Address> mGateways; 144 145 /** 146 * DHCP Optional Type: DHCP DNS Server 147 */ 148 protected static final byte DHCP_DNS_SERVER = 6; 149 protected List<Inet4Address> mDnsServers; 150 151 /** 152 * DHCP Optional Type: DHCP Host Name 153 */ 154 protected static final byte DHCP_HOST_NAME = 12; 155 protected String mHostName; 156 157 /** 158 * DHCP Optional Type: DHCP DOMAIN NAME 159 */ 160 protected static final byte DHCP_DOMAIN_NAME = 15; 161 protected String mDomainName; 162 163 /** 164 * DHCP Optional Type: DHCP Interface MTU 165 */ 166 protected static final byte DHCP_MTU = 26; 167 protected Short mMtu; 168 169 /** 170 * DHCP Optional Type: DHCP BROADCAST ADDRESS 171 */ 172 protected static final byte DHCP_BROADCAST_ADDRESS = 28; 173 protected Inet4Address mBroadcastAddress; 174 175 /** 176 * DHCP Optional Type: Vendor specific information 177 */ 178 protected static final byte DHCP_VENDOR_INFO = 43; 179 protected String mVendorInfo; 180 181 /** 182 * DHCP Optional Type: DHCP Requested IP Address 183 */ 184 protected static final byte DHCP_REQUESTED_IP = 50; 185 protected Inet4Address mRequestedIp; 186 187 /** 188 * DHCP Optional Type: DHCP Lease Time 189 */ 190 protected static final byte DHCP_LEASE_TIME = 51; 191 protected Integer mLeaseTime; 192 193 /** 194 * DHCP Optional Type: DHCP Message Type 195 */ 196 protected static final byte DHCP_MESSAGE_TYPE = 53; 197 // the actual type values 198 protected static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1; 199 protected static final byte DHCP_MESSAGE_TYPE_OFFER = 2; 200 protected static final byte DHCP_MESSAGE_TYPE_REQUEST = 3; 201 protected static final byte DHCP_MESSAGE_TYPE_DECLINE = 4; 202 protected static final byte DHCP_MESSAGE_TYPE_ACK = 5; 203 protected static final byte DHCP_MESSAGE_TYPE_NAK = 6; 204 protected static final byte DHCP_MESSAGE_TYPE_INFORM = 8; 205 206 /** 207 * DHCP Optional Type: DHCP Server Identifier 208 */ 209 protected static final byte DHCP_SERVER_IDENTIFIER = 54; 210 protected Inet4Address mServerIdentifier; 211 212 /** 213 * DHCP Optional Type: DHCP Parameter List 214 */ 215 protected static final byte DHCP_PARAMETER_LIST = 55; 216 protected byte[] mRequestedParams; 217 218 /** 219 * DHCP Optional Type: DHCP MESSAGE 220 */ 221 protected static final byte DHCP_MESSAGE = 56; 222 protected String mMessage; 223 224 /** 225 * DHCP Optional Type: Maximum DHCP Message Size 226 */ 227 protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; 228 protected Short mMaxMessageSize; 229 230 /** 231 * DHCP Optional Type: DHCP Renewal Time Value 232 */ 233 protected static final byte DHCP_RENEWAL_TIME = 58; 234 protected Integer mT1; 235 236 /** 237 * DHCP Optional Type: Rebinding Time Value 238 */ 239 protected static final byte DHCP_REBINDING_TIME = 59; 240 protected Integer mT2; 241 242 /** 243 * DHCP Optional Type: Vendor Class Identifier 244 */ 245 protected static final byte DHCP_VENDOR_CLASS_ID = 60; 246 protected String mVendorId; 247 248 /** 249 * DHCP Optional Type: DHCP Client Identifier 250 */ 251 protected static final byte DHCP_CLIENT_IDENTIFIER = 61; 252 253 /** 254 * DHCP zero-length option code: pad 255 */ 256 protected static final byte DHCP_OPTION_PAD = 0x00; 257 258 /** 259 * DHCP zero-length option code: end of options 260 */ 261 protected static final byte DHCP_OPTION_END = (byte) 0xff; 262 263 /** 264 * The transaction identifier used in this particular DHCP negotiation 265 */ 266 protected final int mTransId; 267 268 /** 269 * The seconds field in the BOOTP header. Per RFC, should be nonzero in client requests only. 270 */ 271 protected final short mSecs; 272 273 /** 274 * The IP address of the client host. This address is typically 275 * proposed by the client (from an earlier DHCP negotiation) or 276 * supplied by the server. 277 */ 278 protected final Inet4Address mClientIp; 279 protected final Inet4Address mYourIp; 280 private final Inet4Address mNextIp; 281 private final Inet4Address mRelayIp; 282 283 /** 284 * Does the client request a broadcast response? 285 */ 286 protected boolean mBroadcast; 287 288 /** 289 * The six-octet MAC of the client. 290 */ 291 protected final byte[] mClientMac; 292 293 /** 294 * Asks the packet object to create a ByteBuffer serialization of 295 * the packet for transmission. 296 */ 297 public abstract ByteBuffer buildPacket(int encap, short destUdp, 298 short srcUdp); 299 300 /** 301 * Allows the concrete class to fill in packet-type-specific details, 302 * typically optional parameters at the end of the packet. 303 */ 304 abstract void finishPacket(ByteBuffer buffer); 305 306 // Set in unit tests, to ensure that the test does not break when run on different devices and 307 // on different releases. 308 static String testOverrideVendorId = null; 309 static String testOverrideHostname = null; 310 311 protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp, 312 Inet4Address nextIp, Inet4Address relayIp, 313 byte[] clientMac, boolean broadcast) { 314 mTransId = transId; 315 mSecs = secs; 316 mClientIp = clientIp; 317 mYourIp = yourIp; 318 mNextIp = nextIp; 319 mRelayIp = relayIp; 320 mClientMac = clientMac; 321 mBroadcast = broadcast; 322 } 323 324 /** 325 * Returns the transaction ID. 326 */ 327 public int getTransactionId() { 328 return mTransId; 329 } 330 331 /** 332 * Returns the client MAC. 333 */ 334 public byte[] getClientMac() { 335 return mClientMac; 336 } 337 338 /** 339 * Returns the client ID. This follows RFC 2132 and is based on the hardware address. 340 */ 341 public byte[] getClientId() { 342 byte[] clientId = new byte[mClientMac.length + 1]; 343 clientId[0] = CLIENT_ID_ETHER; 344 System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length); 345 return clientId; 346 } 347 348 /** 349 * Creates a new L3 packet (including IP header) containing the 350 * DHCP udp packet. This method relies upon the delegated method 351 * finishPacket() to insert the per-packet contents. 352 */ 353 protected void fillInPacket(int encap, Inet4Address destIp, 354 Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf, 355 byte requestCode, boolean broadcast) { 356 byte[] destIpArray = destIp.getAddress(); 357 byte[] srcIpArray = srcIp.getAddress(); 358 int ipHeaderOffset = 0; 359 int ipLengthOffset = 0; 360 int ipChecksumOffset = 0; 361 int endIpHeader = 0; 362 int udpHeaderOffset = 0; 363 int udpLengthOffset = 0; 364 int udpChecksumOffset = 0; 365 366 buf.clear(); 367 buf.order(ByteOrder.BIG_ENDIAN); 368 369 if (encap == ENCAP_L2) { 370 buf.put(ETHER_BROADCAST); 371 buf.put(mClientMac); 372 buf.putShort((short) OsConstants.ETH_P_IP); 373 } 374 375 // if a full IP packet needs to be generated, put the IP & UDP 376 // headers in place, and pre-populate with artificial values 377 // needed to seed the IP checksum. 378 if (encap <= ENCAP_L3) { 379 ipHeaderOffset = buf.position(); 380 buf.put(IP_VERSION_HEADER_LEN); 381 buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY 382 ipLengthOffset = buf.position(); 383 buf.putShort((short)0); // length 384 buf.putShort((short)0); // id 385 buf.putShort(IP_FLAGS_OFFSET); // ip offset: don't fragment 386 buf.put(IP_TTL); // TTL: use default 64 from RFC1340 387 buf.put(IP_TYPE_UDP); 388 ipChecksumOffset = buf.position(); 389 buf.putShort((short) 0); // checksum 390 391 buf.put(srcIpArray); 392 buf.put(destIpArray); 393 endIpHeader = buf.position(); 394 395 // UDP header 396 udpHeaderOffset = buf.position(); 397 buf.putShort(srcUdp); 398 buf.putShort(destUdp); 399 udpLengthOffset = buf.position(); 400 buf.putShort((short) 0); // length 401 udpChecksumOffset = buf.position(); 402 buf.putShort((short) 0); // UDP checksum -- initially zero 403 } 404 405 // DHCP payload 406 buf.put(requestCode); 407 buf.put((byte) 1); // Hardware Type: Ethernet 408 buf.put((byte) mClientMac.length); // Hardware Address Length 409 buf.put((byte) 0); // Hop Count 410 buf.putInt(mTransId); // Transaction ID 411 buf.putShort(mSecs); // Elapsed Seconds 412 413 if (broadcast) { 414 buf.putShort((short) 0x8000); // Flags 415 } else { 416 buf.putShort((short) 0x0000); // Flags 417 } 418 419 buf.put(mClientIp.getAddress()); 420 buf.put(mYourIp.getAddress()); 421 buf.put(mNextIp.getAddress()); 422 buf.put(mRelayIp.getAddress()); 423 buf.put(mClientMac); 424 buf.position(buf.position() + 425 (HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes 426 + 64 // empty server host name (64 bytes) 427 + 128); // empty boot file name (128 bytes) 428 buf.putInt(DHCP_MAGIC_COOKIE); // magic number 429 finishPacket(buf); 430 431 // round up to an even number of octets 432 if ((buf.position() & 1) == 1) { 433 buf.put((byte) 0); 434 } 435 436 // If an IP packet is being built, the IP & UDP checksums must be 437 // computed. 438 if (encap <= ENCAP_L3) { 439 // fix UDP header: insert length 440 short udpLen = (short)(buf.position() - udpHeaderOffset); 441 buf.putShort(udpLengthOffset, udpLen); 442 // fix UDP header: checksum 443 // checksum for UDP at udpChecksumOffset 444 int udpSeed = 0; 445 446 // apply IPv4 pseudo-header. Read IP address src and destination 447 // values from the IP header and accumulate checksum. 448 udpSeed += intAbs(buf.getShort(ipChecksumOffset + 2)); 449 udpSeed += intAbs(buf.getShort(ipChecksumOffset + 4)); 450 udpSeed += intAbs(buf.getShort(ipChecksumOffset + 6)); 451 udpSeed += intAbs(buf.getShort(ipChecksumOffset + 8)); 452 453 // accumulate extra data for the pseudo-header 454 udpSeed += IP_TYPE_UDP; 455 udpSeed += udpLen; 456 // and compute UDP checksum 457 buf.putShort(udpChecksumOffset, (short) checksum(buf, udpSeed, 458 udpHeaderOffset, 459 buf.position())); 460 // fix IP header: insert length 461 buf.putShort(ipLengthOffset, (short)(buf.position() - ipHeaderOffset)); 462 // fixup IP-header checksum 463 buf.putShort(ipChecksumOffset, 464 (short) checksum(buf, 0, ipHeaderOffset, endIpHeader)); 465 } 466 } 467 468 /** 469 * Converts a signed short value to an unsigned int value. Needed 470 * because Java does not have unsigned types. 471 */ 472 private static int intAbs(short v) { 473 return v & 0xFFFF; 474 } 475 476 /** 477 * Performs an IP checksum (used in IP header and across UDP 478 * payload) on the specified portion of a ByteBuffer. The seed 479 * allows the checksum to commence with a specified value. 480 */ 481 private int checksum(ByteBuffer buf, int seed, int start, int end) { 482 int sum = seed; 483 int bufPosition = buf.position(); 484 485 // set position of original ByteBuffer, so that the ShortBuffer 486 // will be correctly initialized 487 buf.position(start); 488 ShortBuffer shortBuf = buf.asShortBuffer(); 489 490 // re-set ByteBuffer position 491 buf.position(bufPosition); 492 493 short[] shortArray = new short[(end - start) / 2]; 494 shortBuf.get(shortArray); 495 496 for (short s : shortArray) { 497 sum += intAbs(s); 498 } 499 500 start += shortArray.length * 2; 501 502 // see if a singleton byte remains 503 if (end != start) { 504 short b = buf.get(start); 505 506 // make it unsigned 507 if (b < 0) { 508 b += 256; 509 } 510 511 sum += b * 256; 512 } 513 514 sum = ((sum >> 16) & 0xFFFF) + (sum & 0xFFFF); 515 sum = ((sum + ((sum >> 16) & 0xFFFF)) & 0xFFFF); 516 int negated = ~sum; 517 return intAbs((short) negated); 518 } 519 520 /** 521 * Adds an optional parameter containing a single byte value. 522 */ 523 protected static void addTlv(ByteBuffer buf, byte type, byte value) { 524 buf.put(type); 525 buf.put((byte) 1); 526 buf.put(value); 527 } 528 529 /** 530 * Adds an optional parameter containing an array of bytes. 531 */ 532 protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) { 533 if (payload != null) { 534 if (payload.length > MAX_OPTION_LEN) { 535 throw new IllegalArgumentException("DHCP option too long: " 536 + payload.length + " vs. " + MAX_OPTION_LEN); 537 } 538 buf.put(type); 539 buf.put((byte) payload.length); 540 buf.put(payload); 541 } 542 } 543 544 /** 545 * Adds an optional parameter containing an IP address. 546 */ 547 protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) { 548 if (addr != null) { 549 addTlv(buf, type, addr.getAddress()); 550 } 551 } 552 553 /** 554 * Adds an optional parameter containing a list of IP addresses. 555 */ 556 protected static void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) { 557 if (addrs == null || addrs.size() == 0) return; 558 559 int optionLen = 4 * addrs.size(); 560 if (optionLen > MAX_OPTION_LEN) { 561 throw new IllegalArgumentException("DHCP option too long: " 562 + optionLen + " vs. " + MAX_OPTION_LEN); 563 } 564 565 buf.put(type); 566 buf.put((byte)(optionLen)); 567 568 for (Inet4Address addr : addrs) { 569 buf.put(addr.getAddress()); 570 } 571 } 572 573 /** 574 * Adds an optional parameter containing a short integer 575 */ 576 protected static void addTlv(ByteBuffer buf, byte type, Short value) { 577 if (value != null) { 578 buf.put(type); 579 buf.put((byte) 2); 580 buf.putShort(value.shortValue()); 581 } 582 } 583 584 /** 585 * Adds an optional parameter containing a simple integer 586 */ 587 protected static void addTlv(ByteBuffer buf, byte type, Integer value) { 588 if (value != null) { 589 buf.put(type); 590 buf.put((byte) 4); 591 buf.putInt(value.intValue()); 592 } 593 } 594 595 /** 596 * Adds an optional parameter containing an ASCII string. 597 */ 598 protected static void addTlv(ByteBuffer buf, byte type, String str) { 599 try { 600 addTlv(buf, type, str.getBytes("US-ASCII")); 601 } catch (UnsupportedEncodingException e) { 602 throw new IllegalArgumentException("String is not US-ASCII: " + str); 603 } 604 } 605 606 /** 607 * Adds the special end-of-optional-parameters indicator. 608 */ 609 protected static void addTlvEnd(ByteBuffer buf) { 610 buf.put((byte) 0xFF); 611 } 612 613 private String getVendorId() { 614 if (testOverrideVendorId != null) return testOverrideVendorId; 615 return "android-dhcp-" + Build.VERSION.RELEASE; 616 } 617 618 private String getHostname() { 619 if (testOverrideHostname != null) return testOverrideHostname; 620 return SystemProperties.get("net.hostname"); 621 } 622 623 /** 624 * Adds common client TLVs. 625 * 626 * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket 627 * methods to take them. 628 */ 629 protected void addCommonClientTlvs(ByteBuffer buf) { 630 addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); 631 addTlv(buf, DHCP_VENDOR_CLASS_ID, getVendorId()); 632 addTlv(buf, DHCP_HOST_NAME, getHostname()); 633 } 634 635 /** 636 * Converts a MAC from an array of octets to an ASCII string. 637 */ 638 public static String macToString(byte[] mac) { 639 String macAddr = ""; 640 641 for (int i = 0; i < mac.length; i++) { 642 String hexString = "0" + Integer.toHexString(mac[i]); 643 644 // substring operation grabs the last 2 digits: this 645 // allows signed bytes to be converted correctly. 646 macAddr += hexString.substring(hexString.length() - 2); 647 648 if (i != (mac.length - 1)) { 649 macAddr += ":"; 650 } 651 } 652 653 return macAddr; 654 } 655 656 public String toString() { 657 String macAddr = macToString(mClientMac); 658 659 return macAddr; 660 } 661 662 /** 663 * Reads a four-octet value from a ByteBuffer and construct 664 * an IPv4 address from that value. 665 */ 666 private static Inet4Address readIpAddress(ByteBuffer packet) { 667 Inet4Address result = null; 668 byte[] ipAddr = new byte[4]; 669 packet.get(ipAddr); 670 671 try { 672 result = (Inet4Address) Inet4Address.getByAddress(ipAddr); 673 } catch (UnknownHostException ex) { 674 // ipAddr is numeric, so this should not be 675 // triggered. However, if it is, just nullify 676 result = null; 677 } 678 679 return result; 680 } 681 682 /** 683 * Reads a string of specified length from the buffer. 684 */ 685 private static String readAsciiString(ByteBuffer buf, int byteCount, boolean nullOk) { 686 byte[] bytes = new byte[byteCount]; 687 buf.get(bytes); 688 int length = bytes.length; 689 if (!nullOk) { 690 // Stop at the first null byte. This is because some DHCP options (e.g., the domain 691 // name) are passed to netd via FrameworkListener, which refuses arguments containing 692 // null bytes. We don't do this by default because vendorInfo is an opaque string which 693 // could in theory contain null bytes. 694 for (length = 0; length < bytes.length; length++) { 695 if (bytes[length] == 0) { 696 break; 697 } 698 } 699 } 700 return new String(bytes, 0, length, StandardCharsets.US_ASCII); 701 } 702 703 private static boolean isPacketToOrFromClient(short udpSrcPort, short udpDstPort) { 704 return (udpSrcPort == DHCP_CLIENT) || (udpDstPort == DHCP_CLIENT); 705 } 706 707 private static boolean isPacketServerToServer(short udpSrcPort, short udpDstPort) { 708 return (udpSrcPort == DHCP_SERVER) && (udpDstPort == DHCP_SERVER); 709 } 710 711 public static class ParseException extends Exception { 712 public final int errorCode; 713 public ParseException(int errorCode, String msg, Object... args) { 714 super(String.format(msg, args)); 715 this.errorCode = errorCode; 716 } 717 } 718 719 /** 720 * Creates a concrete DhcpPacket from the supplied ByteBuffer. The 721 * buffer may have an L2 encapsulation (which is the full EthernetII 722 * format starting with the source-address MAC) or an L3 encapsulation 723 * (which starts with the IP header). 724 * <br> 725 * A subset of the optional parameters are parsed and are stored 726 * in object fields. 727 */ 728 @VisibleForTesting 729 static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException 730 { 731 // bootp parameters 732 int transactionId; 733 short secs; 734 Inet4Address clientIp; 735 Inet4Address yourIp; 736 Inet4Address nextIp; 737 Inet4Address relayIp; 738 byte[] clientMac; 739 List<Inet4Address> dnsServers = new ArrayList<>(); 740 List<Inet4Address> gateways = new ArrayList<>(); // aka router 741 Inet4Address serverIdentifier = null; 742 Inet4Address netMask = null; 743 String message = null; 744 String vendorId = null; 745 String vendorInfo = null; 746 byte[] expectedParams = null; 747 String hostName = null; 748 String domainName = null; 749 Inet4Address ipSrc = null; 750 Inet4Address ipDst = null; 751 Inet4Address bcAddr = null; 752 Inet4Address requestedIp = null; 753 754 // The following are all unsigned integers. Internally we store them as signed integers of 755 // the same length because that way we're guaranteed that they can't be out of the range of 756 // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need 757 // to cast it. 758 Short mtu = null; 759 Short maxMessageSize = null; 760 Integer leaseTime = null; 761 Integer T1 = null; 762 Integer T2 = null; 763 764 // dhcp options 765 byte dhcpType = (byte) 0xFF; 766 767 packet.order(ByteOrder.BIG_ENDIAN); 768 769 // check to see if we need to parse L2, IP, and UDP encaps 770 if (pktType == ENCAP_L2) { 771 if (packet.remaining() < MIN_PACKET_LENGTH_L2) { 772 throw new ParseException(DhcpErrorEvent.L2_TOO_SHORT, 773 "L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2); 774 } 775 776 byte[] l2dst = new byte[6]; 777 byte[] l2src = new byte[6]; 778 779 packet.get(l2dst); 780 packet.get(l2src); 781 782 short l2type = packet.getShort(); 783 784 if (l2type != OsConstants.ETH_P_IP) { 785 throw new ParseException(DhcpErrorEvent.L2_WRONG_ETH_TYPE, 786 "Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP); 787 } 788 } 789 790 if (pktType <= ENCAP_L3) { 791 if (packet.remaining() < MIN_PACKET_LENGTH_L3) { 792 throw new ParseException(DhcpErrorEvent.L3_TOO_SHORT, 793 "L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3); 794 } 795 796 byte ipTypeAndLength = packet.get(); 797 int ipVersion = (ipTypeAndLength & 0xf0) >> 4; 798 if (ipVersion != 4) { 799 throw new ParseException( 800 DhcpErrorEvent.L3_NOT_IPV4, "Invalid IP version %d", ipVersion); 801 } 802 803 // System.out.println("ipType is " + ipType); 804 byte ipDiffServicesField = packet.get(); 805 short ipTotalLength = packet.getShort(); 806 short ipIdentification = packet.getShort(); 807 byte ipFlags = packet.get(); 808 byte ipFragOffset = packet.get(); 809 byte ipTTL = packet.get(); 810 byte ipProto = packet.get(); 811 short ipChksm = packet.getShort(); 812 813 ipSrc = readIpAddress(packet); 814 ipDst = readIpAddress(packet); 815 816 if (ipProto != IP_TYPE_UDP) { 817 throw new ParseException( 818 DhcpErrorEvent.L4_NOT_UDP, "Protocol not UDP: %d", ipProto); 819 } 820 821 // Skip options. This cannot cause us to read beyond the end of the buffer because the 822 // IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than 823 // MIN_PACKET_LENGTH_L3. 824 int optionWords = ((ipTypeAndLength & 0x0f) - 5); 825 for (int i = 0; i < optionWords; i++) { 826 packet.getInt(); 827 } 828 829 // assume UDP 830 short udpSrcPort = packet.getShort(); 831 short udpDstPort = packet.getShort(); 832 short udpLen = packet.getShort(); 833 short udpChkSum = packet.getShort(); 834 835 // Only accept packets to or from the well-known client port (expressly permitting 836 // packets from ports other than the well-known server port; http://b/24687559), and 837 // server-to-server packets, e.g. for relays. 838 if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) && 839 !isPacketServerToServer(udpSrcPort, udpDstPort)) { 840 // This should almost never happen because we use SO_ATTACH_FILTER on the packet 841 // socket to drop packets that don't have the right source ports. However, it's 842 // possible that a packet arrives between when the socket is bound and when the 843 // filter is set. http://b/26696823 . 844 throw new ParseException(DhcpErrorEvent.L4_WRONG_PORT, 845 "Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort); 846 } 847 } 848 849 // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. 850 if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { 851 throw new ParseException(DhcpErrorEvent.BOOTP_TOO_SHORT, 852 "Invalid type or BOOTP packet too short, %d < %d", 853 packet.remaining(), MIN_PACKET_LENGTH_BOOTP); 854 } 855 856 byte type = packet.get(); 857 byte hwType = packet.get(); 858 int addrLen = packet.get() & 0xff; 859 byte hops = packet.get(); 860 transactionId = packet.getInt(); 861 secs = packet.getShort(); 862 short bootpFlags = packet.getShort(); 863 boolean broadcast = (bootpFlags & 0x8000) != 0; 864 byte[] ipv4addr = new byte[4]; 865 866 try { 867 packet.get(ipv4addr); 868 clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 869 packet.get(ipv4addr); 870 yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 871 packet.get(ipv4addr); 872 nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 873 packet.get(ipv4addr); 874 relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); 875 } catch (UnknownHostException ex) { 876 throw new ParseException(DhcpErrorEvent.L3_INVALID_IP, 877 "Invalid IPv4 address: %s", Arrays.toString(ipv4addr)); 878 } 879 880 // Some DHCP servers have been known to announce invalid client hardware address values such 881 // as 0xff. The legacy DHCP client accepted these becuause it does not check the length at 882 // all but only checks that the interface MAC address matches the first bytes of the address 883 // in the packets. We're a bit stricter: if the length is obviously invalid (i.e., bigger 884 // than the size of the field), we fudge it to 6 (Ethernet). http://b/23725795 885 // TODO: evaluate whether to make this test more liberal. 886 if (addrLen > HWADDR_LEN) { 887 addrLen = ETHER_BROADCAST.length; 888 } 889 890 clientMac = new byte[addrLen]; 891 packet.get(clientMac); 892 893 // skip over address padding (16 octets allocated) 894 packet.position(packet.position() + (16 - addrLen) 895 + 64 // skip server host name (64 chars) 896 + 128); // skip boot file name (128 chars) 897 898 // Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211 899 if (packet.remaining() < 4) { 900 throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message"); 901 } 902 903 int dhcpMagicCookie = packet.getInt(); 904 if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) { 905 throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE, 906 "Bad magic cookie 0x%08x, should be 0x%08x", 907 dhcpMagicCookie, DHCP_MAGIC_COOKIE); 908 } 909 910 // parse options 911 boolean notFinishedOptions = true; 912 913 while ((packet.position() < packet.limit()) && notFinishedOptions) { 914 final byte optionType = packet.get(); // cannot underflow because position < limit 915 try { 916 if (optionType == DHCP_OPTION_END) { 917 notFinishedOptions = false; 918 } else if (optionType == DHCP_OPTION_PAD) { 919 // The pad option doesn't have a length field. Nothing to do. 920 } else { 921 int optionLen = packet.get() & 0xFF; 922 int expectedLen = 0; 923 924 switch(optionType) { 925 case DHCP_SUBNET_MASK: 926 netMask = readIpAddress(packet); 927 expectedLen = 4; 928 break; 929 case DHCP_ROUTER: 930 for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { 931 gateways.add(readIpAddress(packet)); 932 } 933 break; 934 case DHCP_DNS_SERVER: 935 for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { 936 dnsServers.add(readIpAddress(packet)); 937 } 938 break; 939 case DHCP_HOST_NAME: 940 expectedLen = optionLen; 941 hostName = readAsciiString(packet, optionLen, false); 942 break; 943 case DHCP_MTU: 944 expectedLen = 2; 945 mtu = packet.getShort(); 946 break; 947 case DHCP_DOMAIN_NAME: 948 expectedLen = optionLen; 949 domainName = readAsciiString(packet, optionLen, false); 950 break; 951 case DHCP_BROADCAST_ADDRESS: 952 bcAddr = readIpAddress(packet); 953 expectedLen = 4; 954 break; 955 case DHCP_REQUESTED_IP: 956 requestedIp = readIpAddress(packet); 957 expectedLen = 4; 958 break; 959 case DHCP_LEASE_TIME: 960 leaseTime = Integer.valueOf(packet.getInt()); 961 expectedLen = 4; 962 break; 963 case DHCP_MESSAGE_TYPE: 964 dhcpType = packet.get(); 965 expectedLen = 1; 966 break; 967 case DHCP_SERVER_IDENTIFIER: 968 serverIdentifier = readIpAddress(packet); 969 expectedLen = 4; 970 break; 971 case DHCP_PARAMETER_LIST: 972 expectedParams = new byte[optionLen]; 973 packet.get(expectedParams); 974 expectedLen = optionLen; 975 break; 976 case DHCP_MESSAGE: 977 expectedLen = optionLen; 978 message = readAsciiString(packet, optionLen, false); 979 break; 980 case DHCP_MAX_MESSAGE_SIZE: 981 expectedLen = 2; 982 maxMessageSize = Short.valueOf(packet.getShort()); 983 break; 984 case DHCP_RENEWAL_TIME: 985 expectedLen = 4; 986 T1 = Integer.valueOf(packet.getInt()); 987 break; 988 case DHCP_REBINDING_TIME: 989 expectedLen = 4; 990 T2 = Integer.valueOf(packet.getInt()); 991 break; 992 case DHCP_VENDOR_CLASS_ID: 993 expectedLen = optionLen; 994 // Embedded nulls are safe as this does not get passed to netd. 995 vendorId = readAsciiString(packet, optionLen, true); 996 break; 997 case DHCP_CLIENT_IDENTIFIER: { // Client identifier 998 byte[] id = new byte[optionLen]; 999 packet.get(id); 1000 expectedLen = optionLen; 1001 } break; 1002 case DHCP_VENDOR_INFO: 1003 expectedLen = optionLen; 1004 // Embedded nulls are safe as this does not get passed to netd. 1005 vendorInfo = readAsciiString(packet, optionLen, true); 1006 break; 1007 default: 1008 // ignore any other parameters 1009 for (int i = 0; i < optionLen; i++) { 1010 expectedLen++; 1011 byte throwaway = packet.get(); 1012 } 1013 } 1014 1015 if (expectedLen != optionLen) { 1016 final int errorCode = DhcpErrorEvent.errorCodeWithOption( 1017 DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType); 1018 throw new ParseException(errorCode, 1019 "Invalid length %d for option %d, expected %d", 1020 optionLen, optionType, expectedLen); 1021 } 1022 } 1023 } catch (BufferUnderflowException e) { 1024 final int errorCode = DhcpErrorEvent.errorCodeWithOption( 1025 DhcpErrorEvent.BUFFER_UNDERFLOW, optionType); 1026 throw new ParseException(errorCode, "BufferUnderflowException"); 1027 } 1028 } 1029 1030 DhcpPacket newPacket; 1031 1032 switch(dhcpType) { 1033 case (byte) 0xFF: 1034 throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE, 1035 "No DHCP message type option"); 1036 case DHCP_MESSAGE_TYPE_DISCOVER: 1037 newPacket = new DhcpDiscoverPacket( 1038 transactionId, secs, clientMac, broadcast); 1039 break; 1040 case DHCP_MESSAGE_TYPE_OFFER: 1041 newPacket = new DhcpOfferPacket( 1042 transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); 1043 break; 1044 case DHCP_MESSAGE_TYPE_REQUEST: 1045 newPacket = new DhcpRequestPacket( 1046 transactionId, secs, clientIp, clientMac, broadcast); 1047 break; 1048 case DHCP_MESSAGE_TYPE_DECLINE: 1049 newPacket = new DhcpDeclinePacket( 1050 transactionId, secs, clientIp, yourIp, nextIp, relayIp, 1051 clientMac); 1052 break; 1053 case DHCP_MESSAGE_TYPE_ACK: 1054 newPacket = new DhcpAckPacket( 1055 transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac); 1056 break; 1057 case DHCP_MESSAGE_TYPE_NAK: 1058 newPacket = new DhcpNakPacket( 1059 transactionId, secs, clientIp, yourIp, nextIp, relayIp, 1060 clientMac); 1061 break; 1062 case DHCP_MESSAGE_TYPE_INFORM: 1063 newPacket = new DhcpInformPacket( 1064 transactionId, secs, clientIp, yourIp, nextIp, relayIp, 1065 clientMac); 1066 break; 1067 default: 1068 throw new ParseException(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE, 1069 "Unimplemented DHCP type %d", dhcpType); 1070 } 1071 1072 newPacket.mBroadcastAddress = bcAddr; 1073 newPacket.mDnsServers = dnsServers; 1074 newPacket.mDomainName = domainName; 1075 newPacket.mGateways = gateways; 1076 newPacket.mHostName = hostName; 1077 newPacket.mLeaseTime = leaseTime; 1078 newPacket.mMessage = message; 1079 newPacket.mMtu = mtu; 1080 newPacket.mRequestedIp = requestedIp; 1081 newPacket.mRequestedParams = expectedParams; 1082 newPacket.mServerIdentifier = serverIdentifier; 1083 newPacket.mSubnetMask = netMask; 1084 newPacket.mMaxMessageSize = maxMessageSize; 1085 newPacket.mT1 = T1; 1086 newPacket.mT2 = T2; 1087 newPacket.mVendorId = vendorId; 1088 newPacket.mVendorInfo = vendorInfo; 1089 return newPacket; 1090 } 1091 1092 /** 1093 * Parse a packet from an array of bytes, stopping at the given length. 1094 */ 1095 public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType) 1096 throws ParseException { 1097 ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN); 1098 try { 1099 return decodeFullPacket(buffer, pktType); 1100 } catch (ParseException e) { 1101 throw e; 1102 } catch (Exception e) { 1103 throw new ParseException(DhcpErrorEvent.PARSING_ERROR, e.getMessage()); 1104 } 1105 } 1106 1107 /** 1108 * Construct a DhcpResults object from a DHCP reply packet. 1109 */ 1110 public DhcpResults toDhcpResults() { 1111 Inet4Address ipAddress = mYourIp; 1112 if (ipAddress.equals(Inet4Address.ANY)) { 1113 ipAddress = mClientIp; 1114 if (ipAddress.equals(Inet4Address.ANY)) { 1115 return null; 1116 } 1117 } 1118 1119 int prefixLength; 1120 if (mSubnetMask != null) { 1121 try { 1122 prefixLength = NetworkUtils.netmaskToPrefixLength(mSubnetMask); 1123 } catch (IllegalArgumentException e) { 1124 // Non-contiguous netmask. 1125 return null; 1126 } 1127 } else { 1128 prefixLength = NetworkUtils.getImplicitNetmask(ipAddress); 1129 } 1130 1131 DhcpResults results = new DhcpResults(); 1132 try { 1133 results.ipAddress = new LinkAddress(ipAddress, prefixLength); 1134 } catch (IllegalArgumentException e) { 1135 return null; 1136 } 1137 1138 if (mGateways.size() > 0) { 1139 results.gateway = mGateways.get(0); 1140 } 1141 1142 results.dnsServers.addAll(mDnsServers); 1143 results.domains = mDomainName; 1144 results.serverAddress = mServerIdentifier; 1145 results.vendorInfo = mVendorInfo; 1146 results.leaseDuration = (mLeaseTime != null) ? mLeaseTime : INFINITE_LEASE; 1147 results.mtu = (mMtu != null && MIN_MTU <= mMtu && mMtu <= MAX_MTU) ? mMtu : 0; 1148 1149 return results; 1150 } 1151 1152 /** 1153 * Returns the parsed lease time, in milliseconds, or 0 for infinite. 1154 */ 1155 public long getLeaseTimeMillis() { 1156 // dhcpcd treats the lack of a lease time option as an infinite lease. 1157 if (mLeaseTime == null || mLeaseTime == INFINITE_LEASE) { 1158 return 0; 1159 } else if (0 <= mLeaseTime && mLeaseTime < MINIMUM_LEASE) { 1160 return MINIMUM_LEASE * 1000; 1161 } else { 1162 return (mLeaseTime & 0xffffffffL) * 1000; 1163 } 1164 } 1165 1166 /** 1167 * Builds a DHCP-DISCOVER packet from the required specified 1168 * parameters. 1169 */ 1170 public static ByteBuffer buildDiscoverPacket(int encap, int transactionId, 1171 short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams) { 1172 DhcpPacket pkt = new DhcpDiscoverPacket( 1173 transactionId, secs, clientMac, broadcast); 1174 pkt.mRequestedParams = expectedParams; 1175 return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 1176 } 1177 1178 /** 1179 * Builds a DHCP-OFFER packet from the required specified 1180 * parameters. 1181 */ 1182 public static ByteBuffer buildOfferPacket(int encap, int transactionId, 1183 boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, 1184 byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, 1185 List<Inet4Address> gateways, List<Inet4Address> dnsServers, 1186 Inet4Address dhcpServerIdentifier, String domainName) { 1187 DhcpPacket pkt = new DhcpOfferPacket( 1188 transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); 1189 pkt.mGateways = gateways; 1190 pkt.mDnsServers = dnsServers; 1191 pkt.mLeaseTime = timeout; 1192 pkt.mDomainName = domainName; 1193 pkt.mServerIdentifier = dhcpServerIdentifier; 1194 pkt.mSubnetMask = netMask; 1195 pkt.mBroadcastAddress = bcAddr; 1196 return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 1197 } 1198 1199 /** 1200 * Builds a DHCP-ACK packet from the required specified parameters. 1201 */ 1202 public static ByteBuffer buildAckPacket(int encap, int transactionId, 1203 boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, 1204 byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, 1205 List<Inet4Address> gateways, List<Inet4Address> dnsServers, 1206 Inet4Address dhcpServerIdentifier, String domainName) { 1207 DhcpPacket pkt = new DhcpAckPacket( 1208 transactionId, (short) 0, broadcast, serverIpAddr, INADDR_ANY, clientIpAddr, mac); 1209 pkt.mGateways = gateways; 1210 pkt.mDnsServers = dnsServers; 1211 pkt.mLeaseTime = timeout; 1212 pkt.mDomainName = domainName; 1213 pkt.mSubnetMask = netMask; 1214 pkt.mServerIdentifier = dhcpServerIdentifier; 1215 pkt.mBroadcastAddress = bcAddr; 1216 return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 1217 } 1218 1219 /** 1220 * Builds a DHCP-NAK packet from the required specified parameters. 1221 */ 1222 public static ByteBuffer buildNakPacket(int encap, int transactionId, 1223 Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) { 1224 DhcpPacket pkt = new DhcpNakPacket(transactionId, (short) 0, clientIpAddr, 1225 serverIpAddr, serverIpAddr, serverIpAddr, mac); 1226 pkt.mMessage = "requested address not available"; 1227 pkt.mRequestedIp = clientIpAddr; 1228 return pkt.buildPacket(encap, DHCP_CLIENT, DHCP_SERVER); 1229 } 1230 1231 /** 1232 * Builds a DHCP-REQUEST packet from the required specified parameters. 1233 */ 1234 public static ByteBuffer buildRequestPacket(int encap, 1235 int transactionId, short secs, Inet4Address clientIp, boolean broadcast, 1236 byte[] clientMac, Inet4Address requestedIpAddress, 1237 Inet4Address serverIdentifier, byte[] requestedParams, String hostName) { 1238 DhcpPacket pkt = new DhcpRequestPacket(transactionId, secs, clientIp, 1239 clientMac, broadcast); 1240 pkt.mRequestedIp = requestedIpAddress; 1241 pkt.mServerIdentifier = serverIdentifier; 1242 pkt.mHostName = hostName; 1243 pkt.mRequestedParams = requestedParams; 1244 ByteBuffer result = pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); 1245 return result; 1246 } 1247 } 1248