19b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil/*
29b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * Copyright (C) 2017 The Android Open Source Project
39b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil *
49b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * Licensed under the Apache License, Version 2.0 (the "License");
59b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * you may not use this file except in compliance with the License.
69b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * You may obtain a copy of the License at
79b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil *
89b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil *      http://www.apache.org/licenses/LICENSE-2.0
99b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil *
109b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * Unless required by applicable law or agreed to in writing, software
119b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * distributed under the License is distributed on an "AS IS" BASIS,
129b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * See the License for the specific language governing permissions and
149b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil * limitations under the License.
159b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil */
169b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
172dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#include <regex>
182dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#include <string>
192dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
209b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#include <libgen.h>
219b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#include <stdio.h>
229b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#include <stdlib.h>
239b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#include <string.h>
249b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#include <unistd.h>
259b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
262dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#include <android-base/strings.h>
272dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
282dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define LOG_TAG "NetUtilsWrapper"
292dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#include <cutils/log.h>
302dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
312dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#include "NetUtilsWrapper.h"
322dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
339b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil#define SYSTEM_DIRNAME  "/system/bin/"
349b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
352dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define OEM_IFACE "[^ ]*oem[0-9]+"
362dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define RMNET_IFACE "(r_)?rmnet_(data)?[0-9]+"
372dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define VENDOR_IFACE "(" OEM_IFACE "|" RMNET_IFACE ")"
382dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define VENDOR_CHAIN "(oem_.*|nm_.*|qcom_.*)"
392dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
409b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil// List of net utils wrapped by this program
419b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil// The list MUST be in descending order of string length
429b9e9770dbac53fec5afab127af38067adab2952Sandeep Patilconst char *netcmds[] = {
439b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    "ip6tables",
449b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    "iptables",
459b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    "ndc",
469b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    "tc",
479b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    "ip",
489b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    NULL,
499b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil};
509b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
512dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti// List of regular expressions of expected commands.
522dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitticonst char *EXPECTED_REGEXPS[] = {
532dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#define CMD "^" SYSTEM_DIRNAME
542dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // Create, delete, and manage OEM networks.
552dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc network (create|destroy) oem[0-9]+( |$)",
562dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc network interface (add|remove) oem[0-9]+ " VENDOR_IFACE,
572dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc network route (add|remove) oem[0-9]+ ",
582dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc ipfwd (enable|disable) ",
592dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc ipfwd (add|remove) .*" VENDOR_IFACE,
602dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
612dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // Manage vendor iptables rules.
622dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip(6)?tables -w.* (-A|-D|-F|-I|-N|-X) " VENDOR_CHAIN,
632dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip(6)?tables -w.* (-i|-o) " VENDOR_IFACE,
642dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
652dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // Manage IPsec state.
662dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip xfrm .*",
672dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
682dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // Manage vendor interfaces.
692dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "tc .* dev " VENDOR_IFACE,
702dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip( -4| -6)? (addr|address) (add|del|delete|flush).* dev " VENDOR_IFACE,
712dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
722dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // Other activities observed on current devices. In future releases, these should be supported
732dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    // in a way that is less likely to interfere with general Android networking behaviour.
742dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "tc qdisc del dev root",
752dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip( -4| -6)? rule .* goto 13000 prio 11999",
762dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip( -4| -6)? rule .* prio 25000",
772dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ip(6)?tables -w .* -j " VENDOR_CHAIN,
782dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "iptables -w -t mangle -[AD] PREROUTING -m socket --nowildcard --restore-skmark -j ACCEPT",
792dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    CMD "ndc network interface (add|remove) oem[0-9]+$",  // Invalid command: no interface removed.
802dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti#undef CMD
812dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti};
822dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
832dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colittibool checkExpectedCommand(int argc, char **argv) {
84339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti    static bool loggedError = false;
852dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    std::vector<const char*> allArgs(argc);
862dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    for (int i = 0; i < argc; i++) {
872dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti        allArgs[i] = argv[i];
882dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    }
892dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    std::string fullCmd = android::base::Join(allArgs, ' ');
902dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    for (size_t i = 0; i < ARRAY_SIZE(EXPECTED_REGEXPS); i++) {
912dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti        const std::regex expectedRegexp(EXPECTED_REGEXPS[i], std::regex_constants::extended);
922dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti        if (std::regex_search(fullCmd, expectedRegexp)) {
932dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti            return true;
942dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti        }
952dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    }
96339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti    if (!loggedError) {
97339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti        ALOGI("Unexpected command: %s", fullCmd.c_str());
98ab9c653aaf67575ba22c5e6d3eebe3f2fa8191d6Lorenzo Colitti        fprintf(stderr, LOG_TAG ": Unexpected command: %s\n", fullCmd.c_str());
99339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti        loggedError = true;
100339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti    }
1012dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti    return false;
1022dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti}
1032dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
1042dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colitti
1059b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil// This is the only gateway for vendor programs to reach net utils.
1062dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0Lorenzo Colittiint doMain(int argc, char **argv) {
1079b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    char *progname = argv[0];
1089b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    char *basename = NULL;
1099b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
1109b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    basename = strrchr(progname, '/');
1119b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    basename = basename ? basename + 1 : progname;
1129b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
1139b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    for (int i = 0; netcmds[i]; ++i) {
1149b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil        size_t len = strlen(netcmds[i]);
1159b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil        if (!strncmp(basename, netcmds[i], len)) {
1169b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            // truncate to match netcmds[i]
1179b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            basename[len] = '\0';
1189b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
1199b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            // hardcode the path to /system so it cannot be overwritten
1209b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            char *cmd;
1219b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            if (asprintf(&cmd, "%s%s", SYSTEM_DIRNAME, basename) == -1) {
1229b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil                perror("asprintf");
1239b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil                exit(EXIT_FAILURE);
1249b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            }
1259b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil            argv[0] = cmd;
126339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti            if (checkExpectedCommand(argc, argv)) {
127339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti                execv(cmd, argv);
128339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti            }
1299b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil        }
1309b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    }
1319b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil
132339478675c5c8cc3b9e0ac720591e46b4c691a72Lorenzo Colitti    // Invalid command. Reject and fail.
1339b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil    exit(EXIT_FAILURE);
1349b9e9770dbac53fec5afab127af38067adab2952Sandeep Patil}
135