Home | History | Annotate | Download | only in netutils_wrappers
      1 /*
      2  * Copyright (C) 2017 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 <regex>
     18 #include <string>
     19 
     20 #include <libgen.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include <android-base/strings.h>
     27 
     28 #define LOG_TAG "NetUtilsWrapper"
     29 #include <cutils/log.h>
     30 
     31 #include "NetUtilsWrapper.h"
     32 
     33 #define SYSTEM_DIRNAME  "/system/bin/"
     34 
     35 #define OEM_IFACE "[^ ]*oem[0-9]+"
     36 #define RMNET_IFACE "(r_)?rmnet_(data)?[0-9]+"
     37 #define VENDOR_IFACE "(" OEM_IFACE "|" RMNET_IFACE ")"
     38 #define VENDOR_CHAIN "(oem_.*|nm_.*|qcom_.*)"
     39 
     40 // List of net utils wrapped by this program
     41 // The list MUST be in descending order of string length
     42 const char *netcmds[] = {
     43     "ip6tables",
     44     "iptables",
     45     "ndc",
     46     "tc",
     47     "ip",
     48     NULL,
     49 };
     50 
     51 // List of regular expressions of expected commands.
     52 const char *EXPECTED_REGEXPS[] = {
     53 #define CMD "^" SYSTEM_DIRNAME
     54     // Create, delete, and manage OEM networks.
     55     CMD "ndc network (create|destroy) (oem|handle)[0-9]+( |$)",
     56     CMD "ndc network interface (add|remove) (oem|handle)[0-9]+ " VENDOR_IFACE,
     57     CMD "ndc network route (add|remove) (oem|handle)[0-9]+ ",
     58     CMD "ndc ipfwd (enable|disable) ",
     59     CMD "ndc ipfwd (add|remove) .*" VENDOR_IFACE,
     60 
     61     // Manage vendor iptables rules.
     62     CMD "ip(6)?tables -w.* (-A|-D|-F|-I|-N|-X) " VENDOR_CHAIN,
     63     CMD "ip(6)?tables -w.* (-i|-o) " VENDOR_IFACE,
     64 
     65     // Manage IPsec state.
     66     CMD "ip xfrm .*",
     67 
     68     // Manage vendor interfaces.
     69     CMD "tc .* dev " VENDOR_IFACE,
     70     CMD "ip( -4| -6)? (addr|address) (add|del|delete|flush).* dev " VENDOR_IFACE,
     71 
     72     // Other activities observed on current devices. In future releases, these should be supported
     73     // in a way that is less likely to interfere with general Android networking behaviour.
     74     CMD "tc qdisc del dev root",
     75     CMD "ip( -4| -6)? rule .* goto 13000 prio 11999",
     76     CMD "ip( -4| -6)? rule .* prio 25000",
     77     CMD "ip(6)?tables -w .* -j " VENDOR_CHAIN,
     78     CMD "iptables -w -t mangle -[AD] PREROUTING -m socket --nowildcard --restore-skmark -j ACCEPT",
     79     CMD "ndc network interface (add|remove) oem[0-9]+$",  // Invalid command: no interface removed.
     80 #undef CMD
     81 };
     82 
     83 bool checkExpectedCommand(int argc, char **argv) {
     84     static bool loggedError = false;
     85     std::vector<const char*> allArgs(argc);
     86     for (int i = 0; i < argc; i++) {
     87         allArgs[i] = argv[i];
     88     }
     89     std::string fullCmd = android::base::Join(allArgs, ' ');
     90     for (size_t i = 0; i < ARRAY_SIZE(EXPECTED_REGEXPS); i++) {
     91         const std::regex expectedRegexp(EXPECTED_REGEXPS[i], std::regex_constants::extended);
     92         if (std::regex_search(fullCmd, expectedRegexp)) {
     93             return true;
     94         }
     95     }
     96     if (!loggedError) {
     97         ALOGI("Unexpected command: %s", fullCmd.c_str());
     98         fprintf(stderr, LOG_TAG ": Unexpected command: %s\n", fullCmd.c_str());
     99         loggedError = true;
    100     }
    101     return false;
    102 }
    103 
    104 
    105 // This is the only gateway for vendor programs to reach net utils.
    106 int doMain(int argc, char **argv) {
    107     char *progname = argv[0];
    108     char *basename = NULL;
    109 
    110     basename = strrchr(progname, '/');
    111     basename = basename ? basename + 1 : progname;
    112 
    113     for (int i = 0; netcmds[i]; ++i) {
    114         size_t len = strlen(netcmds[i]);
    115         if (!strncmp(basename, netcmds[i], len)) {
    116             // truncate to match netcmds[i]
    117             basename[len] = '\0';
    118 
    119             // hardcode the path to /system so it cannot be overwritten
    120             char *cmd;
    121             if (asprintf(&cmd, "%s%s", SYSTEM_DIRNAME, basename) == -1) {
    122                 perror("asprintf");
    123                 exit(EXIT_FAILURE);
    124             }
    125             argv[0] = cmd;
    126             if (checkExpectedCommand(argc, argv)) {
    127                 execv(cmd, argv);
    128             }
    129         }
    130     }
    131 
    132     // Invalid command. Reject and fail.
    133     exit(EXIT_FAILURE);
    134 }
    135