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

Commit 29f66668 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

NetworkDiagnostics: ping default router from all global addreses.

This will hopefully allow us to determine if the router does not
have our global addresses in its neighbour cache.

Bug: 23661687
Change-Id: I46734c3c719003939cfccf038457ec309a9ff967
parent f57d9856
Loading
Loading
Loading
Loading
+51 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.connectivity;

import static android.system.OsConstants.*;

import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
@@ -27,6 +28,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.StructTimeval;
import android.text.TextUtils;
import android.util.Pair;

import com.android.internal.util.IndentingPrintWriter;

@@ -149,6 +151,8 @@ public class NetworkDiagnostics {
    }

    private final Map<InetAddress, Measurement> mIcmpChecks = new HashMap<>();
    private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
            new HashMap<>();
    private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
    private final String mDescription;

@@ -178,7 +182,11 @@ public class NetworkDiagnostics {

        for (RouteInfo route : mLinkProperties.getRoutes()) {
            if (route.hasGateway()) {
                prepareIcmpMeasurement(route.getGateway());
                InetAddress gateway = route.getGateway();
                prepareIcmpMeasurement(gateway);
                if (route.isIPv6Default()) {
                    prepareExplicitSourceIcmpMeasurements(gateway);
                }
            }
        }
        for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
@@ -213,6 +221,20 @@ public class NetworkDiagnostics {
        }
    }

    private void prepareExplicitSourceIcmpMeasurements(InetAddress target) {
        for (LinkAddress l : mLinkProperties.getLinkAddresses()) {
            InetAddress source = l.getAddress();
            if (source instanceof Inet6Address && l.isGlobalPreferred()) {
                Pair<InetAddress, InetAddress> srcTarget = new Pair<>(source, target);
                if (!mExplicitSourceIcmpChecks.containsKey(srcTarget)) {
                    Measurement measurement = new Measurement();
                    measurement.thread = new Thread(new IcmpCheck(source, target, measurement));
                    mExplicitSourceIcmpChecks.put(srcTarget, measurement);
                }
            }
        }
    }

    private void prepareDnsMeasurement(InetAddress target) {
        if (!mDnsUdpChecks.containsKey(target)) {
            Measurement measurement = new Measurement();
@@ -222,13 +244,16 @@ public class NetworkDiagnostics {
    }

    private int totalMeasurementCount() {
        return mIcmpChecks.size() + mDnsUdpChecks.size();
        return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size();
    }

    private void startMeasurements() {
        for (Measurement measurement : mIcmpChecks.values()) {
            measurement.thread.start();
        }
        for (Measurement measurement : mExplicitSourceIcmpChecks.values()) {
            measurement.thread.start();
        }
        for (Measurement measurement : mDnsUdpChecks.values()) {
            measurement.thread.start();
        }
@@ -261,6 +286,10 @@ public class NetworkDiagnostics {
                pw.println(entry.getValue().toString());
            }
        }
        for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
                mExplicitSourceIcmpChecks.entrySet()) {
            pw.println(entry.getValue().toString());
        }
        for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
            if (entry.getKey() instanceof Inet4Address) {
                pw.println(entry.getValue().toString());
@@ -276,13 +305,15 @@ public class NetworkDiagnostics {


    private class SimpleSocketCheck implements Closeable {
        protected final InetAddress mSource;  // Usually null.
        protected final InetAddress mTarget;
        protected final int mAddressFamily;
        protected final Measurement mMeasurement;
        protected FileDescriptor mFileDescriptor;
        protected SocketAddress mSocketAddress;

        protected SimpleSocketCheck(InetAddress target, Measurement measurement) {
        protected SimpleSocketCheck(
                InetAddress source, InetAddress target, Measurement measurement) {
            mMeasurement = measurement;

            if (target instanceof Inet6Address) {
@@ -301,6 +332,14 @@ public class NetworkDiagnostics {
                mTarget = target;
                mAddressFamily = AF_INET;
            }

            // We don't need to check the scope ID here because we currently only do explicit-source
            // measurements from global IPv6 addresses.
            mSource = source;
        }

        protected SimpleSocketCheck(InetAddress target, Measurement measurement) {
            this(null, target, measurement);
        }

        protected void setupSocket(
@@ -314,6 +353,9 @@ public class NetworkDiagnostics {
                    SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(readTimeout));
            // TODO: Use IP_RECVERR/IPV6_RECVERR, pending OsContants availability.
            mNetwork.bindSocket(mFileDescriptor);
            if (mSource != null) {
                Os.bind(mFileDescriptor, mSource, 0);
            }
            Os.connect(mFileDescriptor, mTarget, dstPort);
            mSocketAddress = Os.getsockname(mFileDescriptor);
        }
@@ -343,8 +385,8 @@ public class NetworkDiagnostics {
        private final int mProtocol;
        private final int mIcmpType;

        public IcmpCheck(InetAddress target, Measurement measurement) {
            super(target, measurement);
        public IcmpCheck(InetAddress source, InetAddress target, Measurement measurement) {
            super(source, target, measurement);

            if (mAddressFamily == AF_INET6) {
                mProtocol = IPPROTO_ICMPV6;
@@ -359,6 +401,10 @@ public class NetworkDiagnostics {
            mMeasurement.description += " dst{" + mTarget.getHostAddress() + "}";
        }

        public IcmpCheck(InetAddress target, Measurement measurement) {
            this(null, target, measurement);
        }

        @Override
        public void run() {
            // Check if this measurement has already failed during setup.