1 /* 2 * Copyright (C) 2024 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 com.android.server.connectivity; 18 19 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF; 20 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; 21 import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; 22 23 import static org.junit.Assert.assertArrayEquals; 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertTrue; 27 28 import android.annotation.NonNull; 29 import android.net.DnsResolver; 30 import android.net.LinkProperties; 31 import android.net.Network; 32 import android.net.shared.PrivateDnsConfig; 33 34 import com.android.net.module.util.SharedLog; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 import org.mockito.Mock; 41 import org.mockito.MockitoAnnotations; 42 43 import java.net.InetAddress; 44 import java.util.concurrent.Executor; 45 46 @RunWith(JUnit4.class) 47 public final class DdrTrackerTest { 48 private static final int OFF_MODE = PRIVATE_DNS_MODE_OFF; 49 private static final int OPPORTUNISTIC_MODE = PRIVATE_DNS_MODE_OPPORTUNISTIC; 50 private static final int STRICT_MODE = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; 51 52 private DdrTracker mDdrTracker; 53 private @Mock DnsResolver mDnsResolver; 54 private @Mock Network mCleartextDnsNetwork; 55 private @Mock TestCallback mCallback; 56 private @Mock Executor mExecutor; 57 private @Mock SharedLog mValidationLogger; 58 59 // TODO(b/240259333): Fake DNS responses on mDnsResolver to test startSvcbLookup. 60 private static class TestCallback implements DdrTracker.Callback { 61 @Override onSvcbLookupComplete(@onNull PrivateDnsConfig result)62 public void onSvcbLookupComplete(@NonNull PrivateDnsConfig result) {} 63 } 64 65 private static class PrivateDnsConfigBuilder { 66 private int mMode = OFF_MODE; 67 private String mHostname = null; 68 private InetAddress[] mIps = null; 69 private final String mDohName = null; 70 private final InetAddress[] mDohIps = null; 71 private final String mDohPath = null; 72 private final int mDohPort = -1; 73 setMode(int mode)74 PrivateDnsConfigBuilder setMode(int mode) { 75 mMode = mode; 76 return this; 77 } setHostname(String value)78 PrivateDnsConfigBuilder setHostname(String value) { 79 mHostname = value; 80 return this; 81 } setIps(InetAddress[] value)82 PrivateDnsConfigBuilder setIps(InetAddress[] value) { 83 mIps = value; 84 return this; 85 } build()86 PrivateDnsConfig build() { 87 return new PrivateDnsConfig(mMode, mHostname, mIps, 88 false /* ddrEnabled */, mDohName, mDohIps, mDohPath, mDohPort); 89 } 90 } 91 92 @Before setUp()93 public void setUp() throws Exception { 94 MockitoAnnotations.initMocks(this); 95 mDdrTracker = new DdrTracker(mCleartextDnsNetwork, mDnsResolver, mExecutor, mCallback, 96 mValidationLogger); 97 } 98 99 // TODO: check that if DeviceConfigUtils#isFeatureSupported returns false, DDR is disabled. testNotifyPrivateDnsSettingsChangedHelper(int mode, @NonNull String dnsProvider)100 private void testNotifyPrivateDnsSettingsChangedHelper(int mode, @NonNull String dnsProvider) 101 throws Exception { 102 final PrivateDnsConfig cfg = 103 new PrivateDnsConfigBuilder().setMode(mode).setHostname(dnsProvider).build(); 104 105 assertTrue(mDdrTracker.notifyPrivateDnsSettingsChanged(cfg)); 106 assertEquals(mode, mDdrTracker.getPrivateDnsMode()); 107 assertEquals(dnsProvider, mDdrTracker.getStrictModeHostname()); 108 assertFalse(mDdrTracker.notifyPrivateDnsSettingsChanged(cfg)); 109 } 110 111 @Test testNotifyPrivateDnsSettingsChanged()112 public void testNotifyPrivateDnsSettingsChanged() throws Exception { 113 // Tests the initial private DNS setting in DdrTracker. 114 assertEquals(OFF_MODE, mDdrTracker.getPrivateDnsMode()); 115 assertEquals("", mDdrTracker.getStrictModeHostname()); 116 assertFalse(mDdrTracker.notifyPrivateDnsSettingsChanged(new PrivateDnsConfigBuilder() 117 .setMode(OFF_MODE).build())); 118 119 testNotifyPrivateDnsSettingsChangedHelper(OPPORTUNISTIC_MODE, ""); 120 testNotifyPrivateDnsSettingsChangedHelper(STRICT_MODE, "example1.com"); 121 testNotifyPrivateDnsSettingsChangedHelper(STRICT_MODE, "example2.com"); 122 testNotifyPrivateDnsSettingsChangedHelper(OFF_MODE, ""); 123 } 124 testNotifyLinkPropertiesChangedHelper(InetAddress[] ips)125 private void testNotifyLinkPropertiesChangedHelper(InetAddress[] ips) { 126 final LinkProperties lp = new LinkProperties(); 127 for (InetAddress ip : ips) { 128 assertTrue(lp.addDnsServer(ip)); 129 } 130 assertTrue(mDdrTracker.notifyLinkPropertiesChanged(lp)); 131 assertArrayEquals(ips, mDdrTracker.getDnsServers().toArray()); 132 assertFalse(mDdrTracker.notifyLinkPropertiesChanged(lp)); 133 } 134 135 @Test testNotifyLinkPropertiesChanged()136 public void testNotifyLinkPropertiesChanged() throws Exception { 137 final InetAddress ip1 = InetAddress.parseNumericAddress("1.2.3.4"); 138 final InetAddress ip2 = InetAddress.parseNumericAddress("2001:db8::1"); 139 140 // Tests the initial value in DdrTracker. 141 assertTrue(mDdrTracker.getDnsServers().isEmpty()); 142 143 testNotifyLinkPropertiesChangedHelper(new InetAddress[] {ip1}); 144 testNotifyLinkPropertiesChangedHelper(new InetAddress[] {ip1, ip2}); 145 testNotifyLinkPropertiesChangedHelper(new InetAddress[] {ip2, ip1}); 146 } 147 assertPrivateDnsConfigEquals(PrivateDnsConfig a, PrivateDnsConfig b)148 private void assertPrivateDnsConfigEquals(PrivateDnsConfig a, PrivateDnsConfig b) { 149 assertEquals(a.mode, b.mode); 150 assertEquals(a.hostname, b.hostname); 151 assertArrayEquals(a.ips, b.ips); 152 assertEquals(a.dohName, b.dohName); 153 assertArrayEquals(a.dohIps, b.dohIps); 154 assertEquals(a.dohPath, b.dohPath); 155 assertEquals(a.dohPort, b.dohPort); 156 } 157 158 @Test testSetStrictModeHostnameResolutionResult()159 public void testSetStrictModeHostnameResolutionResult() throws Exception { 160 final String dnsProvider = "example1.com"; 161 final InetAddress[] ips = new InetAddress[] { 162 InetAddress.parseNumericAddress("1.2.3.4"), 163 InetAddress.parseNumericAddress("2001:db8::1"), 164 }; 165 final PrivateDnsConfigBuilder builder = 166 new PrivateDnsConfigBuilder().setMode(STRICT_MODE).setHostname(dnsProvider); 167 168 assertTrue(mDdrTracker.notifyPrivateDnsSettingsChanged(builder.build())); 169 assertPrivateDnsConfigEquals(builder.build(), mDdrTracker.getResultForReporting()); 170 171 mDdrTracker.setStrictModeHostnameResolutionResult(ips); 172 assertPrivateDnsConfigEquals(builder.setIps(ips).build(), 173 mDdrTracker.getResultForReporting()); 174 175 mDdrTracker.resetStrictModeHostnameResolutionResult(); 176 assertPrivateDnsConfigEquals(builder.setIps(new InetAddress[0]).build(), 177 mDdrTracker.getResultForReporting()); 178 } 179 } 180