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

Commit ef7432f2 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN Committed by Gerrit Code Review
Browse files

Merge "Ignore DHCP packet sent from non-68 client port"

parents 64dda3cf b0762eb3
Loading
Loading
Loading
Loading
+14 −10
Original line number Original line Diff line number Diff line
@@ -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);
}
}
+11 −4
Original line number Original line Diff line number Diff line
@@ -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
+28 −15
Original line number Original line Diff line number Diff line
@@ -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));