Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c77f04f9 authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android Partner Code Review
Browse files

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.
parents 30d4ec62 c8a0f49f
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
/*
 * 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();
}
+3 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import android.util.Log;
 *
 * @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 @@ public class DhcpStateMachine extends StateMachine {
     * 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 @@ public class DhcpStateMachine extends StateMachine {
     *
     * @hide
     */
    @Override
    public void doQuit() {
        quit();
    }
+7 −0
Original line number Diff line number Diff line
@@ -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;
@@ -138,6 +140,11 @@ public class NetworkUtils {
     */
    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
+0 −74
Original line number Diff line number Diff line
/*
 * 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);
}
+50 −0
Original line number Diff line number Diff line
@@ -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 @@ char *dhcp_get_errmsg();

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 @@ static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
    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 @@ static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint
    return (jboolean) !protectFromVpn(socket);
}


// ----------------------------------------------------------------------------

/*
@@ -261,6 +310,7 @@ static JNINativeMethod gNetworkUtilMethods[] = {
    { "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)
Loading