1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.dhcp; 18 19 import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; 20 21 import android.net.MacAddress; 22 import android.os.SystemClock; 23 import android.text.TextUtils; 24 25 import androidx.annotation.NonNull; 26 import androidx.annotation.Nullable; 27 28 import com.android.internal.util.HexDump; 29 30 import java.net.Inet4Address; 31 import java.util.Arrays; 32 import java.util.Objects; 33 34 /** 35 * An IPv4 address assignment done through DHCPv4. 36 * @hide 37 */ 38 public class DhcpLease { 39 public static final long EXPIRATION_NEVER = Long.MAX_VALUE; 40 public static final String HOSTNAME_NONE = null; 41 42 @Nullable 43 private final byte[] mClientId; 44 @NonNull 45 private final MacAddress mHwAddr; 46 @NonNull 47 private final Inet4Address mNetAddr; 48 private final int mPrefixLength; 49 /** 50 * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}. 51 */ 52 private final long mExpTime; 53 @Nullable 54 private final String mHostname; 55 DhcpLease(@ullable byte[] clientId, @NonNull MacAddress hwAddr, @NonNull Inet4Address netAddr, int prefixLength, long expTime, @Nullable String hostname)56 public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr, 57 @NonNull Inet4Address netAddr, int prefixLength, long expTime, 58 @Nullable String hostname) { 59 mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length)); 60 mHwAddr = hwAddr; 61 mNetAddr = netAddr; 62 mPrefixLength = prefixLength; 63 mExpTime = expTime; 64 mHostname = hostname; 65 } 66 67 /** 68 * Get the clientId associated with this lease, if any. 69 * 70 * <p>If the lease is not associated to a clientId, this returns null. 71 */ 72 @Nullable getClientId()73 public byte[] getClientId() { 74 if (mClientId == null) { 75 return null; 76 } 77 return Arrays.copyOf(mClientId, mClientId.length); 78 } 79 80 @NonNull getHwAddr()81 public MacAddress getHwAddr() { 82 return mHwAddr; 83 } 84 85 @Nullable getHostname()86 public String getHostname() { 87 return mHostname; 88 } 89 90 @NonNull getNetAddr()91 public Inet4Address getNetAddr() { 92 return mNetAddr; 93 } 94 getPrefixLength()95 public int getPrefixLength() { 96 return mPrefixLength; 97 } 98 getExpTime()99 public long getExpTime() { 100 return mExpTime; 101 } 102 103 /** 104 * Push back the expiration time of this lease. If the provided time is sooner than the original 105 * expiration time, the lease time will not be updated. 106 * 107 * <p>The lease hostname is updated with the provided one if set. 108 * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime) 109 */ renewedLease(long expTime, @Nullable String hostname)110 public DhcpLease renewedLease(long expTime, @Nullable String hostname) { 111 return new DhcpLease(mClientId, mHwAddr, mNetAddr, mPrefixLength, 112 Math.max(expTime, mExpTime), 113 (hostname == null ? mHostname : hostname)); 114 } 115 116 /** 117 * Determine whether this lease matches a client with the specified parameters. 118 * @param clientId clientId of the client if any, or null otherwise. 119 * @param hwAddr Hardware address of the client. 120 */ matchesClient(@ullable byte[] clientId, @NonNull MacAddress hwAddr)121 public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) { 122 if (mClientId != null) { 123 return Arrays.equals(mClientId, clientId); 124 } else { 125 return clientId == null && mHwAddr.equals(hwAddr); 126 } 127 } 128 129 @Override equals(Object obj)130 public boolean equals(Object obj) { 131 if (!(obj instanceof DhcpLease)) { 132 return false; 133 } 134 final DhcpLease other = (DhcpLease) obj; 135 return Arrays.equals(mClientId, other.mClientId) 136 && mHwAddr.equals(other.mHwAddr) 137 && mNetAddr.equals(other.mNetAddr) 138 && mPrefixLength == other.mPrefixLength 139 && mExpTime == other.mExpTime 140 && TextUtils.equals(mHostname, other.mHostname); 141 } 142 143 @Override hashCode()144 public int hashCode() { 145 return Objects.hash(mClientId, mHwAddr, mNetAddr, mPrefixLength, mHostname, mExpTime); 146 } 147 clientIdToString(byte[] bytes)148 static String clientIdToString(byte[] bytes) { 149 if (bytes == null) { 150 return "null"; 151 } 152 return HexDump.toHexString(bytes); 153 } 154 inet4AddrToString(@ullable Inet4Address addr)155 static String inet4AddrToString(@Nullable Inet4Address addr) { 156 return (addr == null) ? "null" : addr.getHostAddress(); 157 } 158 159 @Override toString()160 public String toString() { 161 return String.format("clientId: %s, hwAddr: %s, netAddr: %s/%d, expTime: %d," 162 + "hostname: %s", 163 clientIdToString(mClientId), mHwAddr.toString(), inet4AddrToString(mNetAddr), 164 mPrefixLength, mExpTime, mHostname); 165 } 166 167 /** 168 * Create a {@link DhcpLeaseParcelable} containing the information held in this lease. 169 */ toParcelable()170 public DhcpLeaseParcelable toParcelable() { 171 final DhcpLeaseParcelable p = new DhcpLeaseParcelable(); 172 p.clientId = mClientId == null ? null : Arrays.copyOf(mClientId, mClientId.length); 173 p.hwAddr = mHwAddr.toByteArray(); 174 p.netAddr = inet4AddressToIntHTH(mNetAddr); 175 p.prefixLength = mPrefixLength; 176 p.expTime = mExpTime; 177 p.hostname = mHostname; 178 179 return p; 180 } 181 } 182