/* * Copyright (C) 2018 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 static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; import android.net.MacAddress; import android.os.SystemClock; import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.util.HexDump; import java.net.Inet4Address; import java.util.Arrays; import java.util.Objects; /** * An IPv4 address assignment done through DHCPv4. * @hide */ public class DhcpLease { public static final long EXPIRATION_NEVER = Long.MAX_VALUE; public static final String HOSTNAME_NONE = null; @Nullable private final byte[] mClientId; @NonNull private final MacAddress mHwAddr; @NonNull private final Inet4Address mNetAddr; private final int mPrefixLength; /** * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}. */ private final long mExpTime; @Nullable private final String mHostname; public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr, @NonNull Inet4Address netAddr, int prefixLength, long expTime, @Nullable String hostname) { mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length)); mHwAddr = hwAddr; mNetAddr = netAddr; mPrefixLength = prefixLength; mExpTime = expTime; mHostname = hostname; } /** * Get the clientId associated with this lease, if any. * *

If the lease is not associated to a clientId, this returns null. */ @Nullable public byte[] getClientId() { if (mClientId == null) { return null; } return Arrays.copyOf(mClientId, mClientId.length); } @NonNull public MacAddress getHwAddr() { return mHwAddr; } @Nullable public String getHostname() { return mHostname; } @NonNull public Inet4Address getNetAddr() { return mNetAddr; } public int getPrefixLength() { return mPrefixLength; } public long getExpTime() { return mExpTime; } /** * Push back the expiration time of this lease. If the provided time is sooner than the original * expiration time, the lease time will not be updated. * *

The lease hostname is updated with the provided one if set. * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime) */ public DhcpLease renewedLease(long expTime, @Nullable String hostname) { return new DhcpLease(mClientId, mHwAddr, mNetAddr, mPrefixLength, Math.max(expTime, mExpTime), (hostname == null ? mHostname : hostname)); } /** * Determine whether this lease matches a client with the specified parameters. * @param clientId clientId of the client if any, or null otherwise. * @param hwAddr Hardware address of the client. */ public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) { if (mClientId != null) { return Arrays.equals(mClientId, clientId); } else { return clientId == null && mHwAddr.equals(hwAddr); } } @Override public boolean equals(Object obj) { if (!(obj instanceof DhcpLease)) { return false; } final DhcpLease other = (DhcpLease) obj; return Arrays.equals(mClientId, other.mClientId) && mHwAddr.equals(other.mHwAddr) && mNetAddr.equals(other.mNetAddr) && mPrefixLength == other.mPrefixLength && mExpTime == other.mExpTime && TextUtils.equals(mHostname, other.mHostname); } @Override public int hashCode() { return Objects.hash(mClientId, mHwAddr, mNetAddr, mPrefixLength, mHostname, mExpTime); } static String clientIdToString(byte[] bytes) { if (bytes == null) { return "null"; } return HexDump.toHexString(bytes); } static String inet4AddrToString(@Nullable Inet4Address addr) { return (addr == null) ? "null" : addr.getHostAddress(); } @Override public String toString() { return String.format("clientId: %s, hwAddr: %s, netAddr: %s/%d, expTime: %d," + "hostname: %s", clientIdToString(mClientId), mHwAddr.toString(), inet4AddrToString(mNetAddr), mPrefixLength, mExpTime, mHostname); } /** * Create a {@link DhcpLeaseParcelable} containing the information held in this lease. */ public DhcpLeaseParcelable toParcelable() { final DhcpLeaseParcelable p = new DhcpLeaseParcelable(); p.clientId = mClientId == null ? null : Arrays.copyOf(mClientId, mClientId.length); p.hwAddr = mHwAddr.toByteArray(); p.netAddr = inet4AddressToIntHTH(mNetAddr); p.prefixLength = mPrefixLength; p.expTime = mExpTime; p.hostname = mHostname; return p; } }