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

Commit 844ee77b authored by Erik Kline's avatar Erik Kline Committed by Android (Google) Code Review
Browse files

Merge "Move IPv4 address setting to IpManager" into nyc-dev

parents c71b6302 5b76623a
Loading
Loading
Loading
Loading
+60 −39
Original line number Diff line number Diff line
@@ -32,8 +32,6 @@ import android.net.LinkAddress;
import android.net.NetworkUtils;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -121,6 +119,13 @@ public class DhcpClient extends StateMachine {
     * after pre DHCP action is complete */
    public static final int CMD_PRE_DHCP_ACTION_COMPLETE    = PUBLIC_BASE + 7;

    /* Command and event notification to/from IpManager requesting the setting
     * (or clearing) of an IPv4 LinkAddress.
     */
    public static final int CMD_CLEAR_LINKADDRESS           = PUBLIC_BASE + 8;
    public static final int CMD_CONFIGURE_LINKADDRESS       = PUBLIC_BASE + 9;
    public static final int EVENT_LINKADDRESS_CONFIGURED    = PUBLIC_BASE + 10;

    /* Message.arg1 arguments to CMD_POST_DHCP notification */
    public static final int DHCP_SUCCESS = 1;
    public static final int DHCP_FAILURE = 2;
@@ -157,7 +162,6 @@ public class DhcpClient extends StateMachine {
    // System services / libraries we use.
    private final Context mContext;
    private final Random mRandom;
    private final INetworkManagementService mNMService;

    // Sockets.
    // - We use a packet socket to receive, because servers send us packets bound for IP addresses
@@ -192,7 +196,8 @@ public class DhcpClient extends StateMachine {
    private State mDhcpInitState = new DhcpInitState();
    private State mDhcpSelectingState = new DhcpSelectingState();
    private State mDhcpRequestingState = new DhcpRequestingState();
    private State mDhcpHaveAddressState = new DhcpHaveAddressState();
    private State mDhcpHaveLeaseState = new DhcpHaveLeaseState();
    private State mConfiguringInterfaceState = new ConfiguringInterfaceState();
    private State mDhcpBoundState = new DhcpBoundState();
    private State mDhcpRenewingState = new DhcpRenewingState();
    private State mDhcpRebindingState = new DhcpRebindingState();
@@ -219,19 +224,17 @@ public class DhcpClient extends StateMachine {
            addState(mWaitBeforeStartState, mDhcpState);
            addState(mDhcpSelectingState, mDhcpState);
            addState(mDhcpRequestingState, mDhcpState);
            addState(mDhcpHaveAddressState, mDhcpState);
                addState(mDhcpBoundState, mDhcpHaveAddressState);
                addState(mWaitBeforeRenewalState, mDhcpHaveAddressState);
                addState(mDhcpRenewingState, mDhcpHaveAddressState);
                addState(mDhcpRebindingState, mDhcpHaveAddressState);
            addState(mDhcpHaveLeaseState, mDhcpState);
                addState(mConfiguringInterfaceState, mDhcpHaveLeaseState);
                addState(mDhcpBoundState, mDhcpHaveLeaseState);
                addState(mWaitBeforeRenewalState, mDhcpHaveLeaseState);
                addState(mDhcpRenewingState, mDhcpHaveLeaseState);
                addState(mDhcpRebindingState, mDhcpHaveLeaseState);
            addState(mDhcpInitRebootState, mDhcpState);
            addState(mDhcpRebootingState, mDhcpState);

        setInitialState(mStoppedState);

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mNMService = INetworkManagementService.Stub.asInterface(b);

        mRandom = new Random();

        // Used to schedule packet retransmissions.
@@ -321,18 +324,6 @@ public class DhcpClient extends StateMachine {
        closeQuietly(mPacketSock);
    }

    private boolean setIpAddress(LinkAddress address) {
        InterfaceConfiguration ifcg = new InterfaceConfiguration();
        ifcg.setLinkAddress(address);
        try {
            mNMService.setInterfaceConfig(mIfaceName, ifcg);
        } catch (RemoteException|IllegalStateException e) {
            Log.e(TAG, "Error configuring IP address " + address + ": ", e);
            return false;
        }
        return true;
    }

    class ReceiveThread extends Thread {

        private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH];
@@ -382,7 +373,8 @@ public class DhcpClient extends StateMachine {
                Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
            } else {
                // It's safe to call getpeername here, because we only send unicast packets if we
                // have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
                // have an IP address, and we connect the UDP socket before
                // ConfiguringInterfaceState#exit.
                if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
                Os.write(mUdpSock, buf);
            }
@@ -460,6 +452,7 @@ public class DhcpClient extends StateMachine {
    }

    abstract class LoggingState extends State {
        @Override
        public void enter() {
            if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
            DhcpClientEvent.logStateEvent(mIfaceName, getName());
@@ -759,7 +752,7 @@ public class DhcpClient extends StateMachine {
                    mOffer = null;
                    Log.d(TAG, "Confirmed lease: " + mDhcpLease);
                    setDhcpLeaseExpiry(packet);
                    transitionTo(mDhcpBoundState);
                    transitionTo(mConfiguringInterfaceState);
                }
            } else if (packet instanceof DhcpNakPacket) {
                // TODO: Wait a while before returning into INIT state.
@@ -776,24 +769,52 @@ public class DhcpClient extends StateMachine {
        }
    }

    class DhcpHaveAddressState extends LoggingState {
    class DhcpHaveLeaseState extends LoggingState {
        @Override
        public void enter() {
            super.enter();
            if (!setIpAddress(mDhcpLease.ipAddress) ||
                    (mDhcpLease.serverAddress != null &&
                            !connectUdpSock((mDhcpLease.serverAddress)))) {
                notifyFailure();
                // There's likely no point in going into DhcpInitState here, we'll probably just
                // repeat the transaction, get the same IP address as before, and fail.
                transitionTo(mStoppedState);
            }
        }

        @Override
        public void exit() {
            if (DBG) Log.d(TAG, "Clearing IP address");
            setIpAddress(new LinkAddress("0.0.0.0/0"));
            // Tell IpManager to clear the IPv4 address. There is no need to
            // wait for confirmation since any subsequent packets are sent from
            // INADDR_ANY anyway (DISCOVER, REQUEST).
            mController.sendMessage(CMD_CLEAR_LINKADDRESS);
        }
    }

    class ConfiguringInterfaceState extends LoggingState {
        @Override
        public void enter() {
            super.enter();
            mController.sendMessage(CMD_CONFIGURE_LINKADDRESS, mDhcpLease.ipAddress);
        }

        @Override
        public boolean processMessage(Message message) {
            super.processMessage(message);
            switch (message.what) {
                case EVENT_LINKADDRESS_CONFIGURED:
                    if (mDhcpLease.serverAddress != null &&
                            !connectUdpSock(mDhcpLease.serverAddress)) {
                        // There's likely no point in going into DhcpInitState here, we'll probably
                        // just repeat the transaction, get the same IP address as before, and fail.
                        //
                        // NOTE: It is observed that connectUdpSock() basically never fails, due to
                        // SO_BINDTODEVICE. Examining the local socket address shows it will happily
                        // return an IPv4 address from another interface, or even return "0.0.0.0".
                        //
                        // TODO: Consider deleting this check, following testing on several kernels.
                        notifyFailure();
                        transitionTo(mStoppedState);
                    } else {
                        transitionTo(mDhcpBoundState);
                    }
                    return HANDLED;
                default:
                    return NOT_HANDLED;
            }
        }
    }

@@ -803,8 +824,8 @@ public class DhcpClient extends StateMachine {
            super.enter();
            mOneshotTimeoutAlarm.cancel();
            notifySuccess();
            // TODO: DhcpStateMachine only supported renewing at 50% of the lease time, and did not
            // support rebinding. Once the legacy DHCP client is gone, fix this.
            // TODO: DhcpStateMachine only supported renewing at 50% of the lease time,
            // and did not support rebinding. Now that the legacy DHCP client is gone, fix this.
            scheduleRenew();
        }

+29 −17
Original line number Diff line number Diff line
@@ -770,6 +770,19 @@ public class IpManager extends StateMachine {
        return (delta != ProvisioningChange.LOST_PROVISIONING);
    }

    private boolean setIPv4Address(LinkAddress address) {
        final InterfaceConfiguration ifcg = new InterfaceConfiguration();
        ifcg.setLinkAddress(address);
        try {
            mNwService.setInterfaceConfig(mInterfaceName, ifcg);
            if (VDBG) Log.d(mTag, "IPv4 configuration succeeded");
        } catch (IllegalStateException | RemoteException e) {
            Log.e(mTag, "IPv4 configuration failed: ", e);
            return false;
        }
        return true;
    }

    private void clearIPv4Address() {
        try {
            final InterfaceConfiguration ifcg = new InterfaceConfiguration();
@@ -794,7 +807,6 @@ public class IpManager extends StateMachine {
    }

    private void handleIPv4Failure() {
        // TODO: Figure out to de-dup this and the same code in DhcpClient.
        clearIPv4Address();
        mDhcpResults = null;
        final LinkProperties newLp = assembleLinkProperties();
@@ -944,7 +956,7 @@ public class IpManager extends StateMachine {
            // If we have a StaticIpConfiguration attempt to apply it and
            // handle the result accordingly.
            if (mConfiguration.mStaticIpConfig != null) {
                if (applyStaticIpConfig()) {
                if (setIPv4Address(mConfiguration.mStaticIpConfig.ipAddress)) {
                    handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
                } else {
                    if (VDBG) { Log.d(mTag, "onProvisioningFailure()"); }
@@ -1050,6 +1062,21 @@ public class IpManager extends StateMachine {
                    }
                    break;

                case DhcpClient.CMD_CLEAR_LINKADDRESS:
                    clearIPv4Address();
                    break;

                case DhcpClient.CMD_CONFIGURE_LINKADDRESS: {
                    final LinkAddress ipAddress = (LinkAddress) msg.obj;
                    if (setIPv4Address(ipAddress)) {
                        mDhcpClient.sendMessage(DhcpClient.EVENT_LINKADDRESS_CONFIGURED);
                    } else {
                        Log.e(mTag, "Failed to set IPv4 address!");
                        transitionTo(mStoppingState);
                    }
                    break;
                }

                case DhcpClient.CMD_POST_DHCP_ACTION: {
                    // Note that onPostDhcpAction() is likely to be
                    // asynchronous, and thus there is no guarantee that we
@@ -1082,20 +1109,5 @@ public class IpManager extends StateMachine {
            }
            return HANDLED;
        }

        private boolean applyStaticIpConfig() {
            final InterfaceConfiguration ifcg = new InterfaceConfiguration();
            ifcg.setLinkAddress(mConfiguration.mStaticIpConfig.ipAddress);
            ifcg.setInterfaceUp();
            try {
                mNwService.setInterfaceConfig(mInterfaceName, ifcg);
                if (DBG) Log.d(mTag, "Static IP configuration succeeded");
            } catch (IllegalStateException | RemoteException e) {
                Log.e(mTag, "Static IP configuration failed: ", e);
                return false;
            }

            return true;
        }
    }
}