Home | History | Annotate | Download | only in shill
      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