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