Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright 2016 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  * IptablesBaseTest.cpp - utility class for tests that use iptables
     17  */
     18 
     19 #include <deque>
     20 #include <string>
     21 #include <vector>
     22 
     23 #include <gtest/gtest.h>
     24 
     25 #include <android-base/stringprintf.h>
     26 
     27 #include "IptablesBaseTest.h"
     28 #include "NetdConstants.h"
     29 
     30 #define LOG_TAG "IptablesBaseTest"
     31 #include <cutils/log.h>
     32 
     33 IptablesBaseTest::IptablesBaseTest() {
     34     sCmds.clear();
     35     sRestoreCmds.clear();
     36 }
     37 
     38 int IptablesBaseTest::fake_android_fork_exec(int argc, char* argv[], int *status, bool, bool) {
     39     std::string cmd = argv[0];
     40     for (int i = 1; i < argc; i++) {
     41         if (argv[i] == NULL) break;  // NatController likes to pass in invalid argc values.
     42         cmd += " ";
     43         cmd += argv[i];
     44     }
     45     sCmds.push_back(cmd);
     46     if (status) {
     47         *status = 0;
     48     }
     49     return 0;
     50 }
     51 
     52 int IptablesBaseTest::fakeExecIptables(IptablesTarget target, ...) {
     53     std::string cmd = " -w";
     54     va_list args;
     55     va_start(args, target);
     56     const char *arg;
     57     do {
     58         arg = va_arg(args, const char *);
     59         if (arg != nullptr) {
     60             cmd += " ";
     61             cmd += arg;
     62         }
     63     } while (arg);
     64 
     65     if (target == V4 || target == V4V6) {
     66         sCmds.push_back(IPTABLES_PATH + cmd);
     67     }
     68     if (target == V6 || target == V4V6) {
     69         sCmds.push_back(IP6TABLES_PATH + cmd);
     70     }
     71 
     72     return 0;
     73 }
     74 
     75 FILE *IptablesBaseTest::fake_popen(const char * /* cmd */, const char *type) {
     76     if (sPopenContents.empty() || strcmp(type, "r") != 0) {
     77         return NULL;
     78     }
     79 
     80     std::string realCmd = android::base::StringPrintf("echo '%s'", sPopenContents.front().c_str());
     81     sPopenContents.pop_front();
     82     return popen(realCmd.c_str(), "r");
     83 }
     84 
     85 int IptablesBaseTest::fakeExecIptablesRestore(IptablesTarget target, const std::string& commands) {
     86     sRestoreCmds.push_back({ target, commands });
     87     return 0;
     88 }
     89 
     90 int IptablesBaseTest::expectIptablesCommand(IptablesTarget target, int pos,
     91                                             const std::string& cmd) {
     92 
     93     if ((unsigned) pos >= sCmds.size()) {
     94         ADD_FAILURE() << "Expected too many iptables commands, want command "
     95                << pos + 1 << "/" << sCmds.size();
     96         return -1;
     97     }
     98 
     99     if (target == V4 || target == V4V6) {
    100         EXPECT_EQ("/system/bin/iptables -w " + cmd, sCmds[pos++]);
    101     }
    102     if (target == V6 || target == V4V6) {
    103         EXPECT_EQ("/system/bin/ip6tables -w " + cmd, sCmds[pos++]);
    104     }
    105 
    106     return target == V4V6 ? 2 : 1;
    107 }
    108 
    109 void IptablesBaseTest::expectIptablesCommands(const std::vector<std::string>& expectedCmds) {
    110     ExpectedIptablesCommands expected;
    111     for (auto cmd : expectedCmds) {
    112         expected.push_back({ V4V6, cmd });
    113     }
    114     expectIptablesCommands(expected);
    115 }
    116 
    117 void IptablesBaseTest::expectIptablesCommands(const ExpectedIptablesCommands& expectedCmds) {
    118     size_t pos = 0;
    119     for (size_t i = 0; i < expectedCmds.size(); i ++) {
    120         auto target = expectedCmds[i].first;
    121         auto cmd = expectedCmds[i].second;
    122         int numConsumed = expectIptablesCommand(target, pos, cmd);
    123         if (numConsumed < 0) {
    124             // Read past the end of the array.
    125             break;
    126         }
    127         pos += numConsumed;
    128     }
    129 
    130     EXPECT_EQ(pos, sCmds.size());
    131     sCmds.clear();
    132 }
    133 
    134 void IptablesBaseTest::expectIptablesCommands(
    135         const std::vector<ExpectedIptablesCommands>& snippets) {
    136     ExpectedIptablesCommands expected;
    137     for (const auto& snippet: snippets) {
    138         expected.insert(expected.end(), snippet.begin(), snippet.end());
    139     }
    140     expectIptablesCommands(expected);
    141 }
    142 
    143 void IptablesBaseTest::expectIptablesRestoreCommands(const std::vector<std::string>& expectedCmds) {
    144     ExpectedIptablesCommands expected;
    145     for (auto cmd : expectedCmds) {
    146         expected.push_back({ V4V6, cmd });
    147     }
    148     expectIptablesRestoreCommands(expected);
    149 }
    150 
    151 void IptablesBaseTest::expectIptablesRestoreCommands(const ExpectedIptablesCommands& expectedCmds) {
    152     EXPECT_EQ(expectedCmds.size(), sRestoreCmds.size());
    153     for (size_t i = 0; i < expectedCmds.size(); i++) {
    154         EXPECT_EQ(expectedCmds[i], sRestoreCmds[i]) <<
    155             "iptables-restore command " << i << " differs";
    156     }
    157     sRestoreCmds.clear();
    158 }
    159 
    160 std::vector<std::string> IptablesBaseTest::sCmds = {};
    161 IptablesBaseTest::ExpectedIptablesCommands IptablesBaseTest::sRestoreCmds = {};
    162 std::deque<std::string> IptablesBaseTest::sPopenContents = {};
    163