Merge "Don't accept RAs in link-local only mode."
diff --git a/common/moduleutils/src/android/net/util/SharedLog.java b/common/moduleutils/src/android/net/util/SharedLog.java
index 4fabf10..9c3cbd3 100644
--- a/common/moduleutils/src/android/net/util/SharedLog.java
+++ b/common/moduleutils/src/android/net/util/SharedLog.java
@@ -19,11 +19,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.text.TextUtils;
-import android.util.LocalLog;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.time.LocalDateTime;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.StringJoiner;
@@ -43,7 +45,7 @@
ERROR,
MARK,
WARN,
- };
+ }
private final LocalLog mLocalLog;
// The tag to use for output to the system log. This is not output to the
@@ -89,7 +91,7 @@
* <p>This method may be called on any thread.
*/
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
- mLocalLog.readOnlyLocalLog().dump(fd, writer, args);
+ mLocalLog.dump(writer);
}
//////
@@ -181,7 +183,7 @@
private String record(Category category, String msg) {
final String entry = logLine(category, msg);
- mLocalLog.log(entry);
+ mLocalLog.append(entry);
return entry;
}
@@ -198,4 +200,33 @@
private boolean isRootLogInstance() {
return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
}
+
+ private static final class LocalLog {
+ private final Deque<String> mLog;
+ private final int mMaxLines;
+
+ LocalLog(int maxLines) {
+ mMaxLines = Math.max(0, maxLines);
+ mLog = new ArrayDeque<>(mMaxLines);
+ }
+
+ synchronized void append(String logLine) {
+ if (mMaxLines <= 0) return;
+ while (mLog.size() >= mMaxLines) {
+ mLog.remove();
+ }
+ mLog.add(LocalDateTime.now() + " - " + logLine);
+ }
+
+ /**
+ * Dumps the content of local log to print writer with each log entry
+ *
+ * @param pw printer writer to write into
+ */
+ synchronized void dump(PrintWriter pw) {
+ for (final String s : mLog) {
+ pw.println(s);
+ }
+ }
+ }
}
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index ff0aafe..a94a2d6 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -18,8 +18,11 @@
import static android.net.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION;
import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNSPEC;
+import static android.system.OsConstants.IFF_LOOPBACK;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
+import static com.android.net.module.util.netlink.NetlinkConstants.IFF_LOWER_UP;
import android.app.AlarmManager;
import android.content.Context;
@@ -37,6 +40,8 @@
import com.android.net.module.util.netlink.NduseroptMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.RtNetlinkLinkMessage;
+import com.android.net.module.util.netlink.StructIfinfoMsg;
import com.android.net.module.util.netlink.StructNdOptPref64;
import com.android.net.module.util.netlink.StructNdOptRdnss;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
@@ -137,9 +142,9 @@
mInterfaceLinkState = true; // Assume up by default
mDnsServerRepository = new DnsServerRepository(config.minRdnssLifetime);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ mDependencies = deps;
mNetlinkMonitor = new MyNetlinkMonitor(h, log, mTag);
mHandler.post(mNetlinkMonitor::start);
- mDependencies = deps;
}
public void shutdown() {
@@ -183,12 +188,10 @@
@Override
public void onInterfaceLinkStateChanged(String iface, boolean state) {
- if (mInterfaceName.equals(iface)) {
- maybeLog("interfaceLinkStateChanged", iface + (state ? " up" : " down"));
- synchronized (this) {
- setInterfaceLinkStateLocked(state);
- }
- }
+ if (isNetlinkEventParsingEnabled()) return;
+ if (!mInterfaceName.equals(iface)) return;
+ maybeLog("interfaceLinkStateChanged", iface + (state ? " up" : " down"));
+ updateInterfaceLinkStateChanged(state);
}
@Override
@@ -259,11 +262,15 @@
public void onInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
if (isNetlinkEventParsingEnabled()) return;
if (!mInterfaceName.equals(iface)) return;
- maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
updateInterfaceDnsServerInfo(lifetime, addresses);
}
+ private synchronized void updateInterfaceLinkStateChanged(boolean state) {
+ setInterfaceLinkStateLocked(state);
+ }
+
private void updateInterfaceDnsServerInfo(long lifetime, final String[] addresses) {
+ maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
final boolean changed = mDnsServerRepository.addServers(lifetime, addresses);
final boolean linkState;
if (changed) {
@@ -314,14 +321,17 @@
}
/**
- * Simple NetlinkMonitor. Currently only listens for PREF64 events.
+ * Simple NetlinkMonitor. Listen for netlink events from kernel.
* All methods except the constructor must be called on the handler thread.
*/
private class MyNetlinkMonitor extends NetlinkMonitor {
private final Handler mHandler;
MyNetlinkMonitor(Handler h, SharedLog log, String tag) {
- super(h, log, tag, OsConstants.NETLINK_ROUTE, NetlinkConstants.RTMGRP_ND_USEROPT);
+ super(h, log, tag, OsConstants.NETLINK_ROUTE,
+ !isNetlinkEventParsingEnabled()
+ ? NetlinkConstants.RTMGRP_ND_USEROPT
+ : (NetlinkConstants.RTMGRP_ND_USEROPT | NetlinkConstants.RTMGRP_LINK));
mHandler = h;
}
@@ -451,10 +461,39 @@
}
}
+ private void processRtNetlinkLinkMessage(RtNetlinkLinkMessage msg) {
+ if (!isNetlinkEventParsingEnabled()) return;
+
+ final StructIfinfoMsg ifinfoMsg = msg.getIfinfoHeader();
+ if (ifinfoMsg.family != AF_UNSPEC || ifinfoMsg.index != mIfindex) return;
+ if ((ifinfoMsg.flags & IFF_LOOPBACK) != 0) return;
+
+ switch (msg.getHeader().nlmsg_type) {
+ case NetlinkConstants.RTM_NEWLINK:
+ final boolean state = (ifinfoMsg.flags & IFF_LOWER_UP) != 0;
+ maybeLog("interfaceLinkStateChanged", "ifindex " + mIfindex
+ + (state ? " up" : " down"));
+ updateInterfaceLinkStateChanged(state);
+ break;
+
+ case NetlinkConstants.RTM_DELLINK:
+ break;
+
+ default:
+ Log.e(mTag, "Unknown rtnetlink link msg type " + msg.getHeader().nlmsg_type);
+ break;
+ }
+ }
+
@Override
protected void processNetlinkMessage(NetlinkMessage nlMsg, long whenMs) {
- if (!(nlMsg instanceof NduseroptMessage)) return;
- processNduseroptMessage((NduseroptMessage) nlMsg, whenMs);
+ if (nlMsg instanceof NduseroptMessage) {
+ processNduseroptMessage((NduseroptMessage) nlMsg, whenMs);
+ } else if (nlMsg instanceof RtNetlinkLinkMessage) {
+ processRtNetlinkLinkMessage((RtNetlinkLinkMessage) nlMsg);
+ } else {
+ Log.e(mTag, "Unknown netlink message: " + nlMsg);
+ }
}
}
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java
index a37d259..173a9e1 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -16,6 +16,7 @@
package android.net.ip;
+import static android.net.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static org.junit.Assert.assertArrayEquals;
@@ -25,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -164,6 +166,8 @@
when(mDependencies.getIpMemoryStore(mContext, mNetworkStackServiceManager))
.thenReturn(mIpMemoryStore);
when(mDependencies.getIpConnectivityLog()).thenReturn(mMetricsLog);
+ when(mDependencies.isFeatureEnabled(eq(mContext),
+ eq(IPCLIENT_PARSE_NETLINK_EVENTS_VERSION), anyBoolean())).thenReturn(false);
mIfParams = null;
}