1 // 2 // Copyright (C) 2013 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 #include "shill/connection_info_reader.h" 18 19 #include <netinet/in.h> 20 21 #include <base/files/file_util.h> 22 #include <base/files/scoped_temp_dir.h> 23 #include <base/strings/stringprintf.h> 24 #include <gmock/gmock.h> 25 #include <gtest/gtest.h> 26 27 using base::FilePath; 28 using base::ScopedTempDir; 29 using base::StringPrintf; 30 using std::string; 31 using std::vector; 32 using testing::Return; 33 34 namespace shill { 35 36 namespace { 37 38 // TODO(benchan): Test IPv6 addresses. 39 40 const char* kConnectionInfoLines[] = { 41 "udp 17 30 src=192.168.1.1 dst=192.168.1.2 sport=9000 dport=53 " 42 "[UNREPLIED] src=192.168.1.2 dst=192.168.1.1 sport=53 dport=9000 use=2", 43 "tcp 6 299 ESTABLISHED src=192.168.2.1 dst=192.168.2.3 sport=8000 " 44 "dport=7000 src=192.168.2.3 dst=192.168.2.1 sport=7000 dport=8000 [ASSURED] " 45 "use=2", 46 }; 47 48 } // namespace 49 50 class ConnectionInfoReaderUnderTest : public ConnectionInfoReader { 51 public: 52 // Mock out GetConnectionInfoFilePath to use a temporary created connection 53 // info file instead of the actual path in procfs (i.e. 54 // /proc/net/ip_conntrack). 55 MOCK_CONST_METHOD0(GetConnectionInfoFilePath, FilePath()); 56 }; 57 58 class ConnectionInfoReaderTest : public testing::Test { 59 protected: 60 IPAddress StringToIPv4Address(const string& address_string) { 61 IPAddress ip_address(IPAddress::kFamilyIPv4); 62 EXPECT_TRUE(ip_address.SetAddressFromString(address_string)); 63 return ip_address; 64 } 65 66 IPAddress StringToIPv6Address(const string& address_string) { 67 IPAddress ip_address(IPAddress::kFamilyIPv6); 68 EXPECT_TRUE(ip_address.SetAddressFromString(address_string)); 69 return ip_address; 70 } 71 72 void CreateConnectionInfoFile(const char** lines, size_t num_lines, 73 const FilePath& dir_path, FilePath* file_path) { 74 ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_path, file_path)); 75 for (size_t i = 0; i < num_lines; ++i) { 76 string line = lines[i]; 77 line += '\n'; 78 ASSERT_TRUE(base::AppendToFile(*file_path, line.data(), line.size())); 79 } 80 } 81 82 void ExpectConnectionInfoEqual(const ConnectionInfo& info1, 83 const ConnectionInfo& info2) { 84 EXPECT_EQ(info1.protocol(), info2.protocol()); 85 EXPECT_EQ(info1.time_to_expire_seconds(), info2.time_to_expire_seconds()); 86 EXPECT_EQ(info1.is_unreplied(), info2.is_unreplied()); 87 EXPECT_TRUE(info1.original_source_ip_address() 88 .Equals(info2.original_source_ip_address())); 89 EXPECT_EQ(info1.original_source_port(), info2.original_source_port()); 90 EXPECT_TRUE(info1.original_destination_ip_address() 91 .Equals(info2.original_destination_ip_address())); 92 EXPECT_EQ(info1.original_destination_port(), 93 info2.original_destination_port()); 94 EXPECT_TRUE(info1.reply_source_ip_address() 95 .Equals(info2.reply_source_ip_address())); 96 EXPECT_EQ(info1.reply_source_port(), info2.reply_source_port()); 97 EXPECT_TRUE(info1.reply_destination_ip_address() 98 .Equals(info2.reply_destination_ip_address())); 99 EXPECT_EQ(info1.reply_destination_port(), info2.reply_destination_port()); 100 } 101 102 ConnectionInfoReaderUnderTest reader_; 103 }; 104 105 TEST_F(ConnectionInfoReaderTest, LoadConnectionInfo) { 106 vector<ConnectionInfo> info_list; 107 ScopedTempDir temp_dir; 108 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 109 110 // Loading a non-existent file should fail. 111 FilePath info_file("/non-existent-file"); 112 EXPECT_CALL(reader_, GetConnectionInfoFilePath()).WillOnce(Return(info_file)); 113 EXPECT_FALSE(reader_.LoadConnectionInfo(&info_list)); 114 115 // Loading an empty file should succeed. 116 CreateConnectionInfoFile(kConnectionInfoLines, 0, temp_dir.path(), 117 &info_file); 118 EXPECT_CALL(reader_, GetConnectionInfoFilePath()).WillOnce(Return(info_file)); 119 EXPECT_TRUE(reader_.LoadConnectionInfo(&info_list)); 120 EXPECT_TRUE(info_list.empty()); 121 122 // Loading a non-empty file should succeed. 123 CreateConnectionInfoFile(kConnectionInfoLines, 124 arraysize(kConnectionInfoLines), 125 temp_dir.path(), 126 &info_file); 127 EXPECT_CALL(reader_, GetConnectionInfoFilePath()).WillOnce(Return(info_file)); 128 EXPECT_TRUE(reader_.LoadConnectionInfo(&info_list)); 129 EXPECT_EQ(arraysize(kConnectionInfoLines), info_list.size()); 130 131 ExpectConnectionInfoEqual(ConnectionInfo(IPPROTO_UDP, 132 30, 133 true, 134 StringToIPv4Address("192.168.1.1"), 135 9000, 136 StringToIPv4Address("192.168.1.2"), 137 53, 138 StringToIPv4Address("192.168.1.2"), 139 53, 140 StringToIPv4Address("192.168.1.1"), 141 9000), 142 info_list[0]); 143 ExpectConnectionInfoEqual(ConnectionInfo(IPPROTO_TCP, 144 299, 145 false, 146 StringToIPv4Address("192.168.2.1"), 147 8000, 148 StringToIPv4Address("192.168.2.3"), 149 7000, 150 StringToIPv4Address("192.168.2.3"), 151 7000, 152 StringToIPv4Address("192.168.2.1"), 153 8000), 154 info_list[1]); 155 } 156 157 TEST_F(ConnectionInfoReaderTest, ParseConnectionInfo) { 158 ConnectionInfo info; 159 160 EXPECT_FALSE(reader_.ParseConnectionInfo("", &info)); 161 162 EXPECT_TRUE(reader_.ParseConnectionInfo(kConnectionInfoLines[0], &info)); 163 ExpectConnectionInfoEqual(ConnectionInfo(IPPROTO_UDP, 164 30, 165 true, 166 StringToIPv4Address("192.168.1.1"), 167 9000, 168 StringToIPv4Address("192.168.1.2"), 169 53, 170 StringToIPv4Address("192.168.1.2"), 171 53, 172 StringToIPv4Address("192.168.1.1"), 173 9000), 174 info); 175 } 176 177 TEST_F(ConnectionInfoReaderTest, ParseProtocol) { 178 int protocol = 0; 179 180 EXPECT_FALSE(reader_.ParseProtocol("", &protocol)); 181 EXPECT_FALSE(reader_.ParseProtocol("a", &protocol)); 182 EXPECT_FALSE(reader_.ParseProtocol("-1", &protocol)); 183 EXPECT_FALSE(reader_.ParseProtocol(StringPrintf("%d", IPPROTO_MAX), 184 &protocol)); 185 186 for (int i = 0; i < IPPROTO_MAX; ++i) { 187 EXPECT_TRUE(reader_.ParseProtocol(StringPrintf("%d", i), &protocol)); 188 EXPECT_EQ(i, protocol); 189 } 190 } 191 192 TEST_F(ConnectionInfoReaderTest, ParseTimeToExpireSeconds) { 193 int64_t time_to_expire = 0; 194 195 EXPECT_FALSE(reader_.ParseTimeToExpireSeconds("", &time_to_expire)); 196 EXPECT_FALSE(reader_.ParseTimeToExpireSeconds("a", &time_to_expire)); 197 EXPECT_FALSE(reader_.ParseTimeToExpireSeconds("-1", &time_to_expire)); 198 199 EXPECT_TRUE(reader_.ParseTimeToExpireSeconds("100", &time_to_expire)); 200 EXPECT_EQ(100, time_to_expire); 201 } 202 203 TEST_F(ConnectionInfoReaderTest, ParseIPAddress) { 204 IPAddress ip_address(IPAddress::kFamilyUnknown); 205 bool is_source = false; 206 207 EXPECT_FALSE(reader_.ParseIPAddress("", &ip_address, &is_source)); 208 EXPECT_FALSE(reader_.ParseIPAddress("abc", &ip_address, &is_source)); 209 EXPECT_FALSE(reader_.ParseIPAddress("src=", &ip_address, &is_source)); 210 EXPECT_FALSE(reader_.ParseIPAddress("src=abc", &ip_address, &is_source)); 211 EXPECT_FALSE(reader_.ParseIPAddress("dst=", &ip_address, &is_source)); 212 EXPECT_FALSE(reader_.ParseIPAddress("dst=abc", &ip_address, &is_source)); 213 214 EXPECT_TRUE(reader_.ParseIPAddress("src=192.168.1.1", 215 &ip_address, &is_source)); 216 EXPECT_TRUE(ip_address.Equals(StringToIPv4Address("192.168.1.1"))); 217 EXPECT_TRUE(is_source); 218 EXPECT_TRUE(reader_.ParseIPAddress("dst=192.168.1.2", 219 &ip_address, &is_source)); 220 EXPECT_TRUE(ip_address.Equals(StringToIPv4Address("192.168.1.2"))); 221 EXPECT_FALSE(is_source); 222 } 223 224 TEST_F(ConnectionInfoReaderTest, ParsePort) { 225 uint16_t port = 0; 226 bool is_source = false; 227 228 EXPECT_FALSE(reader_.ParsePort("", &port, &is_source)); 229 EXPECT_FALSE(reader_.ParsePort("a", &port, &is_source)); 230 EXPECT_FALSE(reader_.ParsePort("0", &port, &is_source)); 231 EXPECT_FALSE(reader_.ParsePort("sport=", &port, &is_source)); 232 EXPECT_FALSE(reader_.ParsePort("sport=a", &port, &is_source)); 233 EXPECT_FALSE(reader_.ParsePort("sport=-1", &port, &is_source)); 234 EXPECT_FALSE(reader_.ParsePort("sport=65536", &port, &is_source)); 235 EXPECT_FALSE(reader_.ParsePort("dport=", &port, &is_source)); 236 EXPECT_FALSE(reader_.ParsePort("dport=a", &port, &is_source)); 237 EXPECT_FALSE(reader_.ParsePort("dport=-1", &port, &is_source)); 238 EXPECT_FALSE(reader_.ParsePort("dport=65536", &port, &is_source)); 239 240 EXPECT_TRUE(reader_.ParsePort("sport=53", &port, &is_source)); 241 EXPECT_EQ(53, port); 242 EXPECT_TRUE(is_source); 243 EXPECT_TRUE(reader_.ParsePort("dport=80", &port, &is_source)); 244 EXPECT_EQ(80, port); 245 EXPECT_FALSE(is_source); 246 } 247 248 } // namespace shill 249