SecondaryTableController.cpp revision c462177bd58e3bf0ac4f618934dae060569e3e0b
1fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt/* 2fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Copyright (C) 2008 The Android Open Source Project 3fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * 4fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 5fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * you may not use this file except in compliance with the License. 6fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * You may obtain a copy of the License at 7fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * 8fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 9fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * 10fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * Unless required by applicable law or agreed to in writing, software 11fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 12fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * See the License for the specific language governing permissions and 14fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt * limitations under the License. 15fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt */ 16fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 17fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <stdlib.h> 18fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <errno.h> 19fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <fcntl.h> 20fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <string.h> 21fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 22fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/socket.h> 23fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/stat.h> 24fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/types.h> 25fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <sys/wait.h> 26fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 27fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <netinet/in.h> 28fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <arpa/inet.h> 29fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 30fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#define LOG_TAG "SecondaryTablController" 31fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <cutils/log.h> 32fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include <cutils/properties.h> 33fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 349e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern "C" int system_nosh(const char *command); 359e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall 36fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "ResponseCode.h" 37c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt#include "NetdConstants.h" 38fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h" 39fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 40fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltSecondaryTableController::SecondaryTableController() { 41fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int i; 42fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt for (i=0; i < INTERFACES_TRACKED; i++) { 43fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceTable[i][0] = 0; 44fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt // TODO - use a hashtable or other prebuilt container class 45fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceRuleCount[i] = 0; 46fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 47fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 48fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 49fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltSecondaryTableController::~SecondaryTableController() { 50fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 51fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 52fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::findTableNumber(const char *iface) { 53fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int i; 54fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt for (i = 0; i < INTERFACES_TRACKED; i++) { 55fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (strncmp(iface, mInterfaceTable[i], MAX_IFACE_LENGTH) == 0) { 56fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return i; 57fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 58fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 59fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 60fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 61fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 62fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix, 63fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *gateway) { 64fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int tableIndex = findTableNumber(iface); 65fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 66fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt tableIndex = findTableNumber(""); // look for an empty slot 67fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 685ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Max number of NATed interfaces reached"); 69fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 70fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "Max number NATed", true); 71fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 72fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 73fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt strncpy(mInterfaceTable[tableIndex], iface, MAX_IFACE_LENGTH); 74fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 75fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 76063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt return modifyRoute(cli, ADD, iface, dest, prefix, gateway, tableIndex); 77063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt} 78063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt 79c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyRoute(SocketClient *cli, const char *action, char *iface, 80c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt char *dest, int prefix, char *gateway, int tableIndex) { 81063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt char *cmd; 82063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt 83063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt if (strcmp("::", gateway) == 0) { 84063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt // IP tool doesn't like "::" - the equiv of 0.0.0.0 that it accepts for ipv4 85063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt asprintf(&cmd, "%s route %s %s/%d dev %s table %d", 86063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt IP_PATH, action, dest, prefix, iface, tableIndex+BASE_TABLE_NUMBER); 87063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt } else { 88063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt asprintf(&cmd, "%s route %s %s/%d via %s dev %s table %d", 89063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER); 90063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt } 91063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt 92fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (runAndFree(cli, cmd)) { 935ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("ip route %s failed: %s route %s %s/%d via %s dev %s table %d", action, 94063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt IP_PATH, action, dest, prefix, gateway, iface, tableIndex+BASE_TABLE_NUMBER); 95fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 96063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "ip route modification failed", true); 97fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 98fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 99063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt 100063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt if (strcmp(action, ADD) == 0) { 101063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt mInterfaceRuleCount[tableIndex]++; 102063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt } else { 103063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt if (--mInterfaceRuleCount[tableIndex] < 1) { 104063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt mInterfaceRuleCount[tableIndex] = 0; 105063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt mInterfaceTable[tableIndex][0] = 0; 106063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt } 107063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt } 108c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt modifyRuleCount(tableIndex, action); 109063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Route modified", false); 110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return 0; 111fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 113c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltvoid SecondaryTableController::modifyRuleCount(int tableIndex, const char *action) { 114c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (strcmp(action, ADD) == 0) { 115c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt mInterfaceRuleCount[tableIndex]++; 116c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } else { 117c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (--mInterfaceRuleCount[tableIndex] < 1) { 118c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt mInterfaceRuleCount[tableIndex] = 0; 119c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt mInterfaceTable[tableIndex][0] = 0; 120c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 121c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 122c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt} 123c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 124c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::verifyTableIndex(int tableIndex) { 125c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if ((tableIndex < 0) || 126c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt (tableIndex >= INTERFACES_TRACKED) || 127c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt (mInterfaceTable[tableIndex][0] == 0)) { 128c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return -1; 129c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } else { 130c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return 0; 131c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 132c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt} 133c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 134c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltconst char *SecondaryTableController::getVersion(const char *addr) { 135c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (strchr(addr, ':') != NULL) { 136c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return "-6"; 137c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } else { 138c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return "-4"; 139c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 140c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt} 141c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 142fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix, 143fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *gateway) { 144fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int tableIndex = findTableNumber(iface); 145fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 1465ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block ALOGE("Interface not found"); 147fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 148fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 149fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 150fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 151fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 152063af322b48ab1bb0c3e09eb0b64915ba568275bRobert Greenwalt return modifyRoute(cli, DEL, iface, dest, prefix, gateway, tableIndex); 153fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 154fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 155c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyFromRule(int tableIndex, const char *action, 156c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt const char *addr) { 157c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt char *cmd; 158c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 159c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (verifyTableIndex(tableIndex)) { 160c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return -1; 161c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 162c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt asprintf(&cmd, "%s %s rule %s from %s table %d", IP_PATH, getVersion(addr), 163c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt action, addr, tableIndex + BASE_TABLE_NUMBER); 164c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (runAndFree(NULL, cmd)) { 165c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return -1; 166c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 167c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 168c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt modifyRuleCount(tableIndex, action); 169c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return 0; 170c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt} 171c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 172c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwaltint SecondaryTableController::modifyLocalRoute(int tableIndex, const char *action, 173c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt const char *iface, const char *addr) { 174c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt char *cmd; 175c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 176c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (verifyTableIndex(tableIndex)) { 177c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return -1; 178c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 179c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 180c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt modifyRuleCount(tableIndex, action); // some del's will fail as the iface is already gone. 181c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 182c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt asprintf(&cmd, "%s route %s %s dev %s table %d", IP_PATH, action, addr, iface, 183c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt tableIndex+BASE_TABLE_NUMBER); 184c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt return runAndFree(NULL, cmd); 185c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt} 186c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt 187fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::runAndFree(SocketClient *cli, char *cmd) { 188fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int ret = 0; 189fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (strlen(cmd) >= 255) { 190c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt if (cli != NULL) { 191c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt ALOGE("ip command (%s) too long", cmd); 192c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt errno = E2BIG; 193c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt cli->sendMsg(ResponseCode::CommandSyntaxError, "Too long", true); 194c462177bd58e3bf0ac4f618934dae060569e3e0bRobert Greenwalt } 195fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt free(cmd); 196fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 197fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 1989e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall ret = system_nosh(cmd); 199fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt free(cmd); 200fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return ret; 201fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 202