Merge "Ignore DHCP packet sent from non-68 client port"
am: ef7432f245
Change-Id: I51addda2fd2db57116c2f5c472c8dc785a694b4f
This commit is contained in:
@@ -16,15 +16,14 @@
|
|||||||
|
|
||||||
package android.net.dhcp;
|
package android.net.dhcp;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.net.util.FdEventsReader;
|
import android.net.util.FdEventsReader;
|
||||||
import android.net.util.PacketReader;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,19 +34,20 @@ abstract class DhcpPacketListener extends FdEventsReader<DhcpPacketListener.Payl
|
|||||||
static final class Payload {
|
static final class Payload {
|
||||||
final byte[] bytes = new byte[DhcpPacket.MAX_LENGTH];
|
final byte[] bytes = new byte[DhcpPacket.MAX_LENGTH];
|
||||||
Inet4Address srcAddr;
|
Inet4Address srcAddr;
|
||||||
|
int srcPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DhcpPacketListener(Handler handler) {
|
public DhcpPacketListener(@NonNull Handler handler) {
|
||||||
super(handler, new Payload());
|
super(handler, new Payload());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int recvBufSize(Payload buffer) {
|
protected int recvBufSize(@NonNull Payload buffer) {
|
||||||
return buffer.bytes.length;
|
return buffer.bytes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void handlePacket(Payload recvbuf, int length) {
|
protected final void handlePacket(@NonNull Payload recvbuf, int length) {
|
||||||
if (recvbuf.srcAddr == null) {
|
if (recvbuf.srcAddr == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -55,30 +55,34 @@ abstract class DhcpPacketListener extends FdEventsReader<DhcpPacketListener.Payl
|
|||||||
try {
|
try {
|
||||||
final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf.bytes, length,
|
final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf.bytes, length,
|
||||||
DhcpPacket.ENCAP_BOOTP);
|
DhcpPacket.ENCAP_BOOTP);
|
||||||
onReceive(packet, recvbuf.srcAddr);
|
onReceive(packet, recvbuf.srcAddr, recvbuf.srcPort);
|
||||||
} catch (DhcpPacket.ParseException e) {
|
} catch (DhcpPacket.ParseException e) {
|
||||||
logParseError(recvbuf.bytes, length, e);
|
logParseError(recvbuf.bytes, length, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int readPacket(FileDescriptor fd, Payload packetBuffer) throws Exception {
|
protected int readPacket(@NonNull FileDescriptor fd, @NonNull Payload packetBuffer)
|
||||||
|
throws Exception {
|
||||||
final InetSocketAddress addr = new InetSocketAddress();
|
final InetSocketAddress addr = new InetSocketAddress();
|
||||||
final int read = Os.recvfrom(
|
final int read = Os.recvfrom(
|
||||||
fd, packetBuffer.bytes, 0, packetBuffer.bytes.length, 0 /* flags */, addr);
|
fd, packetBuffer.bytes, 0, packetBuffer.bytes.length, 0 /* flags */, addr);
|
||||||
|
|
||||||
// Buffers with null srcAddr will be dropped in handlePacket()
|
// Buffers with null srcAddr will be dropped in handlePacket()
|
||||||
packetBuffer.srcAddr = inet4AddrOrNull(addr);
|
packetBuffer.srcAddr = inet4AddrOrNull(addr);
|
||||||
|
packetBuffer.srcPort = addr.getPort();
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Inet4Address inet4AddrOrNull(InetSocketAddress addr) {
|
private static Inet4Address inet4AddrOrNull(@NonNull InetSocketAddress addr) {
|
||||||
return addr.getAddress() instanceof Inet4Address
|
return addr.getAddress() instanceof Inet4Address
|
||||||
? (Inet4Address) addr.getAddress()
|
? (Inet4Address) addr.getAddress()
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void onReceive(DhcpPacket packet, Inet4Address srcAddr);
|
protected abstract void onReceive(@NonNull DhcpPacket packet, @NonNull Inet4Address srcAddr,
|
||||||
protected abstract void logParseError(byte[] packet, int length, DhcpPacket.ParseException e);
|
int srcPort);
|
||||||
|
protected abstract void logParseError(@NonNull byte[] packet, int length,
|
||||||
|
@NonNull DhcpPacket.ParseException e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.net.dhcp;
|
|||||||
import static android.net.NetworkUtils.getBroadcastAddress;
|
import static android.net.NetworkUtils.getBroadcastAddress;
|
||||||
import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
|
import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
|
||||||
import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
|
import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
|
||||||
|
import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
|
||||||
import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
|
import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
|
||||||
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
|
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
|
||||||
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
|
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
|
||||||
@@ -238,8 +239,14 @@ public class DhcpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void processPacket(@NonNull DhcpPacket packet) {
|
void processPacket(@NonNull DhcpPacket packet, int srcPort) {
|
||||||
mLog.log("Received packet of type " + packet.getClass().getSimpleName());
|
final String packetType = packet.getClass().getSimpleName();
|
||||||
|
if (srcPort != DHCP_CLIENT) {
|
||||||
|
mLog.logf("Ignored packet of type %s sent from client port %d", packetType, srcPort);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLog.log("Received packet of type " + packetType);
|
||||||
final Inet4Address sid = packet.mServerIdentifier;
|
final Inet4Address sid = packet.mServerIdentifier;
|
||||||
if (sid != null && !sid.equals(mServingParams.serverAddr.getAddress())) {
|
if (sid != null && !sid.equals(mServingParams.serverAddr.getAddress())) {
|
||||||
mLog.log("Packet ignored due to wrong server identifier: " + sid);
|
mLog.log("Packet ignored due to wrong server identifier: " + sid);
|
||||||
@@ -469,8 +476,8 @@ public class DhcpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReceive(DhcpPacket packet, Inet4Address srcAddr) {
|
protected void onReceive(DhcpPacket packet, Inet4Address srcAddr, int srcPort) {
|
||||||
processPacket(packet);
|
processPacket(packet, srcPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.net.dhcp;
|
package android.net.dhcp;
|
||||||
|
|
||||||
|
import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
|
||||||
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
|
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
|
||||||
import static android.net.dhcp.DhcpPacket.INADDR_ANY;
|
import static android.net.dhcp.DhcpPacket.INADDR_ANY;
|
||||||
import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
|
import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
|
||||||
@@ -27,9 +28,11 @@ import static junit.framework.Assert.assertNull;
|
|||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.isNull;
|
import static org.mockito.ArgumentMatchers.isNull;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -178,7 +181,7 @@ public class DhcpServerTest {
|
|||||||
final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
|
final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
|
||||||
(short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
|
(short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
|
||||||
false /* broadcast */, INADDR_ANY /* srcIp */);
|
false /* broadcast */, INADDR_ANY /* srcIp */);
|
||||||
mServer.processPacket(discover);
|
mServer.processPacket(discover, DHCP_CLIENT);
|
||||||
|
|
||||||
assertResponseSentTo(TEST_CLIENT_ADDR);
|
assertResponseSentTo(TEST_CLIENT_ADDR);
|
||||||
final DhcpOfferPacket packet = assertOffer(getPacket());
|
final DhcpOfferPacket packet = assertOffer(getPacket());
|
||||||
@@ -194,13 +197,22 @@ public class DhcpServerTest {
|
|||||||
final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
|
final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
|
||||||
(short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
|
(short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
|
||||||
false /* broadcast */, INADDR_ANY /* srcIp */);
|
false /* broadcast */, INADDR_ANY /* srcIp */);
|
||||||
mServer.processPacket(discover);
|
mServer.processPacket(discover, DHCP_CLIENT);
|
||||||
|
|
||||||
assertResponseSentTo(INADDR_BROADCAST);
|
assertResponseSentTo(INADDR_BROADCAST);
|
||||||
final DhcpNakPacket packet = assertNak(getPacket());
|
final DhcpNakPacket packet = assertNak(getPacket());
|
||||||
assertMatchesClient(packet);
|
assertMatchesClient(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DhcpRequestPacket makeRequestSelectingPacket() {
|
||||||
|
final DhcpRequestPacket request = new DhcpRequestPacket(TEST_TRANSACTION_ID,
|
||||||
|
(short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* relayIp */,
|
||||||
|
TEST_CLIENT_MAC_BYTES, false /* broadcast */);
|
||||||
|
request.mServerIdentifier = TEST_SERVER_ADDR;
|
||||||
|
request.mRequestedIp = TEST_CLIENT_ADDR;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRequest_Selecting_Ack() throws Exception {
|
public void testRequest_Selecting_Ack() throws Exception {
|
||||||
when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
|
when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
|
||||||
@@ -208,12 +220,8 @@ public class DhcpServerTest {
|
|||||||
eq(true) /* sidSet */, isNull() /* hostname */))
|
eq(true) /* sidSet */, isNull() /* hostname */))
|
||||||
.thenReturn(TEST_LEASE);
|
.thenReturn(TEST_LEASE);
|
||||||
|
|
||||||
final DhcpRequestPacket request = new DhcpRequestPacket(TEST_TRANSACTION_ID,
|
final DhcpRequestPacket request = makeRequestSelectingPacket();
|
||||||
(short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* relayIp */,
|
mServer.processPacket(request, DHCP_CLIENT);
|
||||||
TEST_CLIENT_MAC_BYTES, false /* broadcast */);
|
|
||||||
request.mServerIdentifier = TEST_SERVER_ADDR;
|
|
||||||
request.mRequestedIp = TEST_CLIENT_ADDR;
|
|
||||||
mServer.processPacket(request);
|
|
||||||
|
|
||||||
assertResponseSentTo(TEST_CLIENT_ADDR);
|
assertResponseSentTo(TEST_CLIENT_ADDR);
|
||||||
final DhcpAckPacket packet = assertAck(getPacket());
|
final DhcpAckPacket packet = assertAck(getPacket());
|
||||||
@@ -227,24 +235,29 @@ public class DhcpServerTest {
|
|||||||
eq(true) /* sidSet */, isNull() /* hostname */))
|
eq(true) /* sidSet */, isNull() /* hostname */))
|
||||||
.thenThrow(new InvalidAddressException("Test error"));
|
.thenThrow(new InvalidAddressException("Test error"));
|
||||||
|
|
||||||
final DhcpRequestPacket request = new DhcpRequestPacket(TEST_TRANSACTION_ID,
|
final DhcpRequestPacket request = makeRequestSelectingPacket();
|
||||||
(short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* relayIp */,
|
mServer.processPacket(request, DHCP_CLIENT);
|
||||||
TEST_CLIENT_MAC_BYTES, false /* broadcast */);
|
|
||||||
request.mServerIdentifier = TEST_SERVER_ADDR;
|
|
||||||
request.mRequestedIp = TEST_CLIENT_ADDR;
|
|
||||||
mServer.processPacket(request);
|
|
||||||
|
|
||||||
assertResponseSentTo(INADDR_BROADCAST);
|
assertResponseSentTo(INADDR_BROADCAST);
|
||||||
final DhcpNakPacket packet = assertNak(getPacket());
|
final DhcpNakPacket packet = assertNak(getPacket());
|
||||||
assertMatchesClient(packet);
|
assertMatchesClient(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequest_Selecting_WrongClientPort() throws Exception {
|
||||||
|
final DhcpRequestPacket request = makeRequestSelectingPacket();
|
||||||
|
mServer.processPacket(request, 50000);
|
||||||
|
|
||||||
|
verify(mRepository, never()).requestLease(any(), any(), any(), any(), anyBoolean(), any());
|
||||||
|
verify(mDeps, never()).sendPacket(any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRelease() throws Exception {
|
public void testRelease() throws Exception {
|
||||||
final DhcpReleasePacket release = new DhcpReleasePacket(TEST_TRANSACTION_ID,
|
final DhcpReleasePacket release = new DhcpReleasePacket(TEST_TRANSACTION_ID,
|
||||||
TEST_SERVER_ADDR, TEST_CLIENT_ADDR,
|
TEST_SERVER_ADDR, TEST_CLIENT_ADDR,
|
||||||
INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES);
|
INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES);
|
||||||
mServer.processPacket(release);
|
mServer.processPacket(release, DHCP_CLIENT);
|
||||||
|
|
||||||
verify(mRepository, times(1))
|
verify(mRepository, times(1))
|
||||||
.releaseLease(isNull(), eq(TEST_CLIENT_MAC), eq(TEST_CLIENT_ADDR));
|
.releaseLease(isNull(), eq(TEST_CLIENT_MAC), eq(TEST_CLIENT_ADDR));
|
||||||
|
|||||||
Reference in New Issue
Block a user