Loading services/net/java/android/net/dhcp/DhcpClient.java +60 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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(); Loading @@ -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. Loading Loading @@ -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]; Loading Loading @@ -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); } Loading Loading @@ -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()); Loading Loading @@ -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. Loading @@ -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; } } } Loading @@ -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(); } Loading services/net/java/android/net/ip/IpManager.java +29 −17 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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()"); } Loading Loading @@ -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 Loading Loading @@ -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; } } } Loading
services/net/java/android/net/dhcp/DhcpClient.java +60 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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(); Loading @@ -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. Loading Loading @@ -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]; Loading Loading @@ -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); } Loading Loading @@ -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()); Loading Loading @@ -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. Loading @@ -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; } } } Loading @@ -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(); } Loading
services/net/java/android/net/ip/IpManager.java +29 −17 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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(); Loading Loading @@ -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()"); } Loading Loading @@ -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 Loading Loading @@ -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; } } }