Merge changes from topic 'dhcpclient' into m-wireless-dev

* changes:
  DHCP: Minor cleanups to the packet code.
  DHCP: Move the packet code to frameworks/base/services.
  DHCP: Add a native method for making a DHCP socket.
  DHCP: Add a superclass for DhcpStateMachine.
diff --git a/core/java/android/net/BaseDhcpStateMachine.java b/core/java/android/net/BaseDhcpStateMachine.java
new file mode 100644
index 0000000..a25847d
--- /dev/null
+++ b/core/java/android/net/BaseDhcpStateMachine.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import com.android.internal.util.StateMachine;
+
+/**
+ * Interface that must be implemented by DHCP state machines.
+ *
+ * This is an abstract class instead of a Java interface so that callers can just declare an object
+ * of this type and be able to call all the methods defined by either StateMachine or this class.
+ *
+ * @hide
+ */
+public abstract class BaseDhcpStateMachine extends StateMachine {
+    protected BaseDhcpStateMachine(String tag) {
+        super(tag);
+    }
+    public abstract void registerForPreDhcpNotification();
+    public abstract void doQuit();
+}
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 5151a04..1b8adc8 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -47,7 +47,7 @@
  *
  * @hide
  */
-public class DhcpStateMachine extends StateMachine {
+public class DhcpStateMachine extends BaseDhcpStateMachine {
 
     private static final String TAG = "DhcpStateMachine";
     private static final boolean DBG = false;
@@ -161,6 +161,7 @@
      * This is used by Wifi at this time for the purpose of doing BT-Wifi coex
      * handling during Dhcp
      */
+    @Override
     public void registerForPreDhcpNotification() {
         mRegisteredForPreDhcpNotification = true;
     }
@@ -170,6 +171,7 @@
      *
      * @hide
      */
+    @Override
     public void doQuit() {
         quit();
     }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 4f35a22..01704e5 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,9 +16,11 @@
 
 package android.net;
 
+import java.io.FileDescriptor;
 import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
+import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.Locale;
@@ -139,6 +141,11 @@
     public native static String getDhcpError();
 
     /**
+     * Attaches a socket filter that accepts DHCP packets to the given socket.
+     */
+    public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
+
+    /**
      * Binds the current process to the network designated by {@code netId}.  All sockets created
      * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
      * {@link Network#getSocketFactory}) will be bound to this network.  Note that if this
diff --git a/core/java/android/net/dhcp/DhcpStateMachine.java b/core/java/android/net/dhcp/DhcpStateMachine.java
deleted file mode 100644
index bc9a798..0000000
--- a/core/java/android/net/dhcp/DhcpStateMachine.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.dhcp;
-
-import java.net.InetAddress;
-import java.util.List;
-
-/**
- * This class defines the "next steps" which occur after a given DHCP
- * packet has been received.
- */
-interface DhcpStateMachine {
-    /**
-     * Signals that an offer packet has been received with the specified
-     * parameters.
-     */
-    public void onOfferReceived(boolean broadcast, int transactionId,
-        byte[] myMac, InetAddress offeredIpAddress,
-        InetAddress serverIpAddress);
-
-    /**
-     * Signals that a NAK packet has been received.
-     */
-    public void onNakReceived();
-
-    /**
-     * Signals that the final ACK has been received from the server.
-     */
-    public void onAckReceived(InetAddress myIpAddress, InetAddress myNetMask,
-        InetAddress myGateway, List<InetAddress> myDnsServers,
-        InetAddress myDhcpServer, int leaseTime);
-
-    /**
-     * Signals that a client's DISCOVER packet has been received with the
-     * specified parameters.
-     */
-    public void onDiscoverReceived(boolean broadcast, int transactionId,
-        byte[] clientMac, byte[] requestedParameterList);
-
-    /**
-     * Signals that a client's REQUEST packet has been received with the
-     * specified parameters.
-     */
-    public void onRequestReceived(boolean broadcast, int transactionId,
-        byte[] clientMac, InetAddress requestedIp, byte[] requestedParams,
-        String clientHostName);
-
-    /**
-     * Signals that a client's INFORM packet has been received with the
-     * specified parameters.
-     */
-    public void onInformReceived(int transactionId, byte[] clientMac,
-        InetAddress preassignedIp, byte[] requestedParams);
-
-    /**
-     * Signals that a client's DECLINE packet has been received with the
-     * specified parameters.
-     */
-    public void onDeclineReceived(byte[] clientMac, InetAddress declinedIp);
-}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index e64f1de..2ba8e8c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -24,6 +24,14 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/Log.h>
 #include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/filter.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <net/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
 #include <cutils/properties.h>
 
 extern "C" {
@@ -53,6 +61,8 @@
 
 namespace android {
 
+static const uint16_t kDhcpClientPort = 68;
+
 /*
  * The following remembers the jfieldID's of the fields
  * of the DhcpInfo Java object, so that we don't have
@@ -215,6 +225,44 @@
     return env->NewStringUTF(::dhcp_get_errmsg());
 }
 
+static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
+{
+    int fd = jniGetFDFromFileDescriptor(env, javaFd);
+    uint32_t ip_offset = sizeof(ether_header);
+    uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
+    uint32_t flags_offset = ip_offset +  offsetof(iphdr, frag_off);
+    uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
+    struct sock_filter filter_code[] = {
+        // Check the protocol is UDP.
+        BPF_STMT(BPF_LD  | BPF_B   | BPF_ABS,  proto_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K,    IPPROTO_UDP, 0, 6),
+
+        // Check this is not a fragment.
+        BPF_STMT(BPF_LD  | BPF_H    | BPF_ABS, flags_offset),
+        BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K,   0x1fff, 4, 0),
+
+        // Get the IP header length.
+        BPF_STMT(BPF_LDX | BPF_B    | BPF_MSH, ip_offset),
+
+        // Check the destination port.
+        BPF_STMT(BPF_LD  | BPF_H    | BPF_IND, dport_indirect_offset),
+        BPF_JUMP(BPF_JMP | BPF_JEQ  | BPF_K,   kDhcpClientPort, 0, 1),
+
+        // Accept or reject.
+        BPF_STMT(BPF_RET | BPF_K,              0xffff),
+        BPF_STMT(BPF_RET | BPF_K,              0)
+    };
+    struct sock_fprog filter = {
+        sizeof(filter_code) / sizeof(filter_code[0]),
+        filter_code,
+    };
+
+    if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+        jniThrowExceptionFmt(env, "java/net/SocketException",
+                "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+    }
+}
+
 static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
 {
     return (jboolean) !setNetworkForProcess(netId);
@@ -242,6 +290,7 @@
     return (jboolean) !protectFromVpn(socket);
 }
 
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -261,6 +310,7 @@
     { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
     { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
+    { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
 };
 
 int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/services/Android.mk b/services/Android.mk
index 3c94f43..e4b0cbb 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@
     appwidget \
     backup \
     devicepolicy \
+    net \
     print \
     restrictions \
     usage \
diff --git a/services/net/Android.mk b/services/net/Android.mk
new file mode 100644
index 0000000..336bc45
--- /dev/null
+++ b/services/net/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.net
+
+LOCAL_SRC_FILES += \
+    $(call all-java-files-under,java)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/core/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpAckPacket.java
rename to services/net/java/android/net/dhcp/DhcpAckPacket.java
index 7b8be9c..25b8093 100644
--- a/core/java/android/net/dhcp/DhcpAckPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java
@@ -16,7 +16,6 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
@@ -28,12 +27,11 @@
     /**
      * The address of the server which sent this packet.
      */
-    private final InetAddress mSrcIp;
+    private final Inet4Address mSrcIp;
 
-    DhcpAckPacket(int transId, boolean broadcast, InetAddress serverAddress,
-                  InetAddress clientIp, byte[] clientMac) {
-        super(transId, Inet4Address.ANY, clientIp, serverAddress,
-            Inet4Address.ANY, clientMac, broadcast);
+    DhcpAckPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+                  Inet4Address clientIp, byte[] clientMac) {
+        super(transId, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast);
         mBroadcast = broadcast;
         mSrcIp = serverAddress;
     }
@@ -42,7 +40,7 @@
         String s = super.toString();
         String dnsServers = " DNS servers: ";
 
-        for (InetAddress dnsServer: mDnsServers) {
+        for (Inet4Address dnsServer: mDnsServers) {
             dnsServers += dnsServer.toString() + " ";
         }
 
@@ -57,8 +55,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
-        InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+        Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp;
+        Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp;
 
         fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
             DHCP_BOOTREPLY, mBroadcast);
@@ -98,12 +96,4 @@
             return v.intValue();
         }
     }
-
-    /**
-     * Notifies the specified state machine of the ACK packet parameters.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        machine.onAckReceived(mYourIp, mSubnetMask, mGateway, mDnsServers,
-            mServerIdentifier, getInt(mLeaseTime));
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
similarity index 81%
rename from core/java/android/net/dhcp/DhcpDeclinePacket.java
rename to services/net/java/android/net/dhcp/DhcpDeclinePacket.java
index 7646eb4..9d985ac 100644
--- a/core/java/android/net/dhcp/DhcpDeclinePacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java
@@ -16,7 +16,7 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
 /**
@@ -26,8 +26,8 @@
     /**
      * Generates a DECLINE packet with the specified parameters.
      */
-    DhcpDeclinePacket(int transId, InetAddress clientIp, InetAddress yourIp,
-                      InetAddress nextIp, InetAddress relayIp,
+    DhcpDeclinePacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+                      Inet4Address nextIp, Inet4Address relayIp,
                       byte[] clientMac) {
         super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
     }
@@ -55,11 +55,4 @@
     void finishPacket(ByteBuffer buffer) {
         // None needed
     }
-
-    /**
-     * Informs the state machine of the arrival of a DECLINE packet.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        machine.onDeclineReceived(mClientMac, mRequestedIp);
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
similarity index 73%
rename from core/java/android/net/dhcp/DhcpDiscoverPacket.java
rename to services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
index 0e2d39b..fba43e6 100644
--- a/core/java/android/net/dhcp/DhcpDiscoverPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java
@@ -16,7 +16,6 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
@@ -28,8 +27,7 @@
      * Generates a DISCOVER packet with the specified parameters.
      */
     DhcpDiscoverPacket(int transId, byte[] clientMac, boolean broadcast) {
-        super(transId, Inet4Address.ANY, Inet4Address.ANY, Inet4Address.ANY,
-            Inet4Address.ANY, clientMac, broadcast);
+        super(transId, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
     }
 
     public String toString() {
@@ -43,10 +41,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        InetAddress destIp = Inet4Address.ALL;
-
-        fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
-            result, DHCP_BOOTREQUEST, true);
+        fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp,
+                srcUdp, result, DHCP_BOOTREQUEST, true);
         result.flip();
         return result;
     }
@@ -59,13 +55,4 @@
         addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
         addTlvEnd(buffer);
     }
-
-    /**
-     * Informs the state machine of the arrival of a DISCOVER packet.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        // currently omitted: host name
-        machine.onDiscoverReceived(mBroadcast, mTransId, mClientMac,
-            mRequestedParams);
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpInformPacket.java
rename to services/net/java/android/net/dhcp/DhcpInformPacket.java
index da73216..8bc7cdd 100644
--- a/core/java/android/net/dhcp/DhcpInformPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpInformPacket.java
@@ -16,7 +16,7 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
 /**
@@ -26,8 +26,8 @@
     /**
      * Generates an INFORM packet with the specified parameters.
      */
-    DhcpInformPacket(int transId, InetAddress clientIp, InetAddress yourIp,
-                     InetAddress nextIp, InetAddress relayIp,
+    DhcpInformPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+                     Inet4Address nextIp, Inet4Address relayIp,
                      byte[] clientMac) {
         super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false);
     }
@@ -62,15 +62,4 @@
         addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams);
         addTlvEnd(buffer);
     }
-
-    /**
-     * Informs the state machine of the arrival of an INFORM packet.  Not
-     * used currently.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        InetAddress clientRequest =
-            mRequestedIp == null ? mClientIp : mRequestedIp;
-        machine.onInformReceived(mTransId, mClientMac, clientRequest,
-            mRequestedParams);
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java
similarity index 78%
rename from core/java/android/net/dhcp/DhcpNakPacket.java
rename to services/net/java/android/net/dhcp/DhcpNakPacket.java
index 1f340ad..1390ea7 100644
--- a/core/java/android/net/dhcp/DhcpNakPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java
@@ -16,7 +16,6 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
@@ -27,10 +26,10 @@
     /**
      * Generates a NAK packet with the specified parameters.
      */
-    DhcpNakPacket(int transId, InetAddress clientIp, InetAddress yourIp,
-                  InetAddress nextIp, InetAddress relayIp,
+    DhcpNakPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+                  Inet4Address nextIp, Inet4Address relayIp,
                   byte[] clientMac) {
-        super(transId, Inet4Address.ANY, Inet4Address.ANY, nextIp, relayIp,
+        super(transId, INADDR_ANY, INADDR_ANY, nextIp, relayIp,
             clientMac, false);
     }
 
@@ -44,8 +43,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        InetAddress destIp = mClientIp;
-        InetAddress srcIp = mYourIp;
+        Inet4Address destIp = mClientIp;
+        Inet4Address srcIp = mYourIp;
 
         fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
             DHCP_BOOTREPLY, mBroadcast);
@@ -62,11 +61,4 @@
         addTlv(buffer, DHCP_MESSAGE, mMessage);
         addTlvEnd(buffer);
     }
-
-    /**
-     * Notifies the specified state machine of the newly-arrived NAK packet.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        machine.onNakReceived();
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
similarity index 77%
rename from core/java/android/net/dhcp/DhcpOfferPacket.java
rename to services/net/java/android/net/dhcp/DhcpOfferPacket.java
index f1c30e1..b1f3bbd 100644
--- a/core/java/android/net/dhcp/DhcpOfferPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java
@@ -16,7 +16,6 @@
 
 package android.net.dhcp;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
@@ -27,15 +26,14 @@
     /**
      * The IP address of the server which sent this packet.
      */
-    private final InetAddress mSrcIp;
+    private final Inet4Address mSrcIp;
 
     /**
      * Generates a OFFER packet with the specified parameters.
      */
-    DhcpOfferPacket(int transId, boolean broadcast, InetAddress serverAddress,
-                    InetAddress clientIp, byte[] clientMac) {
-        super(transId, Inet4Address.ANY, clientIp, Inet4Address.ANY,
-            Inet4Address.ANY, clientMac, broadcast);
+    DhcpOfferPacket(int transId, boolean broadcast, Inet4Address serverAddress,
+                    Inet4Address clientIp, byte[] clientMac) {
+        super(transId, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
         mSrcIp = serverAddress;
     }
 
@@ -44,7 +42,7 @@
         String dnsServers = ", DNS servers: ";
 
         if (mDnsServers != null) {
-            for (InetAddress dnsServer: mDnsServers) {
+            for (Inet4Address dnsServer: mDnsServers) {
                 dnsServers += dnsServer + " ";
             }
         }
@@ -59,8 +57,8 @@
      */
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
-        InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp;
-        InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp;
+        Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp;
+        Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp;
 
         fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result,
             DHCP_BOOTREPLY, mBroadcast);
@@ -89,12 +87,4 @@
         addTlv(buffer, DHCP_DNS_SERVER, mDnsServers);
         addTlvEnd(buffer);
     }
-
-    /**
-     * Notifies the state machine of the OFFER packet parameters.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        machine.onOfferReceived(mBroadcast, mTransId, mClientMac, mYourIp,
-            mServerIdentifier);
-    }
 }
diff --git a/core/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
similarity index 90%
rename from core/java/android/net/dhcp/DhcpPacket.java
rename to services/net/java/android/net/dhcp/DhcpPacket.java
index c7c25f0..2384848 100644
--- a/core/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1,6 +1,6 @@
 package android.net.dhcp;
 
-import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -8,6 +8,7 @@
 import java.nio.ShortBuffer;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -18,6 +19,9 @@
 abstract class DhcpPacket {
     protected static final String TAG = "DhcpPacket";
 
+    public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY;
+    public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL;
+
     /**
      * Packet encapsulations.
      */
@@ -85,19 +89,19 @@
      * DHCP Optional Type: DHCP Subnet Mask
      */
     protected static final byte DHCP_SUBNET_MASK = 1;
-    protected InetAddress mSubnetMask;
+    protected Inet4Address mSubnetMask;
 
     /**
      * DHCP Optional Type: DHCP Router
      */
     protected static final byte DHCP_ROUTER = 3;
-    protected InetAddress mGateway;
+    protected Inet4Address mGateway;
 
     /**
      * DHCP Optional Type: DHCP DNS Server
      */
     protected static final byte DHCP_DNS_SERVER = 6;
-    protected List<InetAddress> mDnsServers;
+    protected List<Inet4Address> mDnsServers;
 
     /**
      * DHCP Optional Type: DHCP Host Name
@@ -115,13 +119,13 @@
      * DHCP Optional Type: DHCP BROADCAST ADDRESS
      */
     protected static final byte DHCP_BROADCAST_ADDRESS = 28;
-    protected InetAddress mBroadcastAddress;
+    protected Inet4Address mBroadcastAddress;
 
     /**
      * DHCP Optional Type: DHCP Requested IP Address
      */
     protected static final byte DHCP_REQUESTED_IP = 50;
-    protected InetAddress mRequestedIp;
+    protected Inet4Address mRequestedIp;
 
     /**
      * DHCP Optional Type: DHCP Lease Time
@@ -146,7 +150,7 @@
      * DHCP Optional Type: DHCP Server Identifier
      */
     protected static final byte DHCP_SERVER_IDENTIFIER = 54;
-    protected InetAddress mServerIdentifier;
+    protected Inet4Address mServerIdentifier;
 
     /**
      * DHCP Optional Type: DHCP Parameter List
@@ -185,10 +189,10 @@
      * proposed by the client (from an earlier DHCP negotiation) or
      * supplied by the server.
      */
-    protected final InetAddress mClientIp;
-    protected final InetAddress mYourIp;
-    private final InetAddress mNextIp;
-    private final InetAddress mRelayIp;
+    protected final Inet4Address mClientIp;
+    protected final Inet4Address mYourIp;
+    private final Inet4Address mNextIp;
+    private final Inet4Address mRelayIp;
 
     /**
      * Does the client request a broadcast response?
@@ -201,13 +205,6 @@
     protected final byte[] mClientMac;
 
     /**
-     * Asks the packet object to signal the next operation in the DHCP
-     * protocol.  The available actions are methods defined in the
-     * DhcpStateMachine interface.
-     */
-    public abstract void doNextOp(DhcpStateMachine stateMachine);
-
-    /**
      * Asks the packet object to create a ByteBuffer serialization of
      * the packet for transmission.
      */
@@ -220,8 +217,8 @@
      */
     abstract void finishPacket(ByteBuffer buffer);
 
-    protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp,
-                         InetAddress nextIp, InetAddress relayIp,
+    protected DhcpPacket(int transId, Inet4Address clientIp, Inet4Address yourIp,
+                         Inet4Address nextIp, Inet4Address relayIp,
                          byte[] clientMac, boolean broadcast) {
         mTransId = transId;
         mClientIp = clientIp;
@@ -244,8 +241,8 @@
      * DHCP udp packet.  This method relies upon the delegated method
      * finishPacket() to insert the per-packet contents.
      */
-    protected void fillInPacket(int encap, InetAddress destIp,
-        InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf,
+    protected void fillInPacket(int encap, Inet4Address destIp,
+        Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf,
         byte requestCode, boolean broadcast) {
         byte[] destIpArray = destIp.getAddress();
         byte[] srcIpArray = srcIp.getAddress();
@@ -432,7 +429,7 @@
     /**
      * Adds an optional parameter containing an IP address.
      */
-    protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) {
+    protected void addTlv(ByteBuffer buf, byte type, Inet4Address addr) {
         if (addr != null) {
             addTlv(buf, type, addr.getAddress());
         }
@@ -441,12 +438,12 @@
     /**
      * Adds an optional parameter containing a list of IP addresses.
      */
-    protected void addTlv(ByteBuffer buf, byte type, List<InetAddress> addrs) {
+    protected void addTlv(ByteBuffer buf, byte type, List<Inet4Address> addrs) {
         if (addrs != null && addrs.size() > 0) {
             buf.put(type);
             buf.put((byte)(4 * addrs.size()));
 
-            for (InetAddress addr : addrs) {
+            for (Inet4Address addr : addrs) {
                 buf.put(addr.getAddress());
             }
         }
@@ -515,13 +512,13 @@
      * Reads a four-octet value from a ByteBuffer and construct
      * an IPv4 address from that value.
      */
-    private static InetAddress readIpAddress(ByteBuffer packet) {
-        InetAddress result = null;
+    private static Inet4Address readIpAddress(ByteBuffer packet) {
+        Inet4Address result = null;
         byte[] ipAddr = new byte[4];
         packet.get(ipAddr);
 
         try {
-            result = InetAddress.getByAddress(ipAddr);
+            result = (Inet4Address) Inet4Address.getByAddress(ipAddr);
         } catch (UnknownHostException ex) {
             // ipAddr is numeric, so this should not be
             // triggered.  However, if it is, just nullify
@@ -553,25 +550,25 @@
     {
         // bootp parameters
         int transactionId;
-        InetAddress clientIp;
-        InetAddress yourIp;
-        InetAddress nextIp;
-        InetAddress relayIp;
+        Inet4Address clientIp;
+        Inet4Address yourIp;
+        Inet4Address nextIp;
+        Inet4Address relayIp;
         byte[] clientMac;
-        List<InetAddress> dnsServers = new ArrayList<InetAddress>();
-        InetAddress gateway = null; // aka router
+        List<Inet4Address> dnsServers = new ArrayList<Inet4Address>();
+        Inet4Address gateway = null; // aka router
         Integer leaseTime = null;
-        InetAddress serverIdentifier = null;
-        InetAddress netMask = null;
+        Inet4Address serverIdentifier = null;
+        Inet4Address netMask = null;
         String message = null;
         String vendorId = null;
         byte[] expectedParams = null;
         String hostName = null;
         String domainName = null;
-        InetAddress ipSrc = null;
-        InetAddress ipDst = null;
-        InetAddress bcAddr = null;
-        InetAddress requestedIp = null;
+        Inet4Address ipSrc = null;
+        Inet4Address ipDst = null;
+        Inet4Address bcAddr = null;
+        Inet4Address requestedIp = null;
 
         // dhcp options
         byte dhcpType = (byte) 0xFF;
@@ -635,13 +632,13 @@
 
         try {
             packet.get(ipv4addr);
-            clientIp = InetAddress.getByAddress(ipv4addr);
+            clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
             packet.get(ipv4addr);
-            yourIp = InetAddress.getByAddress(ipv4addr);
+            yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
             packet.get(ipv4addr);
-            nextIp = InetAddress.getByAddress(ipv4addr);
+            nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
             packet.get(ipv4addr);
-            relayIp = InetAddress.getByAddress(ipv4addr);
+            relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
         } catch (UnknownHostException ex) {
             return null;
         }
@@ -828,10 +825,10 @@
      * parameters.
      */
     public static ByteBuffer buildOfferPacket(int encap, int transactionId,
-        boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
-        byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
-        InetAddress gateway, List<InetAddress> dnsServers,
-        InetAddress dhcpServerIdentifier, String domainName) {
+        boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
+        byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
+        Inet4Address gateway, List<Inet4Address> dnsServers,
+        Inet4Address dhcpServerIdentifier, String domainName) {
         DhcpPacket pkt = new DhcpOfferPacket(
             transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
         pkt.mGateway = gateway;
@@ -848,10 +845,10 @@
      * Builds a DHCP-ACK packet from the required specified parameters.
      */
     public static ByteBuffer buildAckPacket(int encap, int transactionId,
-        boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr,
-        byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr,
-        InetAddress gateway, List<InetAddress> dnsServers,
-        InetAddress dhcpServerIdentifier, String domainName) {
+        boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr,
+        byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr,
+        Inet4Address gateway, List<Inet4Address> dnsServers,
+        Inet4Address dhcpServerIdentifier, String domainName) {
         DhcpPacket pkt = new DhcpAckPacket(
             transactionId, broadcast, serverIpAddr, clientIpAddr, mac);
         pkt.mGateway = gateway;
@@ -868,7 +865,7 @@
      * Builds a DHCP-NAK packet from the required specified parameters.
      */
     public static ByteBuffer buildNakPacket(int encap, int transactionId,
-        InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) {
+        Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) {
         DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr,
             serverIpAddr, serverIpAddr, serverIpAddr, mac);
         pkt.mMessage = "requested address not available";
@@ -880,9 +877,9 @@
      * Builds a DHCP-REQUEST packet from the required specified parameters.
      */
     public static ByteBuffer buildRequestPacket(int encap,
-        int transactionId, InetAddress clientIp, boolean broadcast,
-        byte[] clientMac, InetAddress requestedIpAddress,
-        InetAddress serverIdentifier, byte[] requestedParams, String hostName) {
+        int transactionId, Inet4Address clientIp, boolean broadcast,
+        byte[] clientMac, Inet4Address requestedIpAddress,
+        Inet4Address serverIdentifier, byte[] requestedParams, String hostName) {
         DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp,
             clientMac, broadcast);
         pkt.mRequestedIp = requestedIpAddress;
diff --git a/core/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
similarity index 73%
rename from core/java/android/net/dhcp/DhcpRequestPacket.java
rename to services/net/java/android/net/dhcp/DhcpRequestPacket.java
index cf32957..337fdf0 100644
--- a/core/java/android/net/dhcp/DhcpRequestPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java
@@ -18,7 +18,6 @@
 
 import android.util.Log;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.ByteBuffer;
 
@@ -29,10 +28,9 @@
     /**
      * Generates a REQUEST packet with the specified parameters.
      */
-    DhcpRequestPacket(int transId, InetAddress clientIp, byte[] clientMac,
+    DhcpRequestPacket(int transId, Inet4Address clientIp, byte[] clientMac,
                       boolean broadcast) {
-        super(transId, clientIp, Inet4Address.ANY, Inet4Address.ANY,
-          Inet4Address.ANY, clientMac, broadcast);
+        super(transId, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast);
     }
 
     public String toString() {
@@ -48,7 +46,7 @@
     public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) {
         ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH);
 
-        fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp,
+        fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, srcUdp,
             result, DHCP_BOOTREQUEST, mBroadcast);
         result.flip();
         return result;
@@ -71,16 +69,4 @@
         addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId);
         addTlvEnd(buffer);
     }
-
-    /**
-     * Notifies the specified state machine of the REQUEST packet parameters.
-     */
-    public void doNextOp(DhcpStateMachine machine) {
-        InetAddress clientRequest =
-            mRequestedIp == null ? mClientIp : mRequestedIp;
-        Log.v(TAG, "requested IP is " + mRequestedIp + " and client IP is " +
-            mClientIp);
-        machine.onRequestReceived(mBroadcast, mTransId, mClientMac,
-            clientRequest, mRequestedParams, mHostName);
-    }
 }