SecondaryTableController.cpp revision fc97b82e02979f246d56a4bfd60e4aab8686d3f6
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 34fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "ResponseCode.h" 35fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt#include "SecondaryTableController.h" 36fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 37fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltstatic char IP_PATH[] = "/system/bin/ip"; 38fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 39fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltSecondaryTableController::SecondaryTableController() { 40fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int i; 41fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt for (i=0; i < INTERFACES_TRACKED; i++) { 42fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceTable[i][0] = 0; 43fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt // TODO - use a hashtable or other prebuilt container class 44fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceRuleCount[i] = 0; 45fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 46fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 47fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 48fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert GreenwaltSecondaryTableController::~SecondaryTableController() { 49fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 50fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 51fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::findTableNumber(const char *iface) { 52fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int i; 53fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt for (i = 0; i < INTERFACES_TRACKED; i++) { 54fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (strncmp(iface, mInterfaceTable[i], MAX_IFACE_LENGTH) == 0) { 55fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return i; 56fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 57fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 58fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 59fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 60fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 61fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::addRoute(SocketClient *cli, char *iface, char *dest, int prefix, 62fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *gateway) { 63fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *cmd; 64fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 65fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int tableIndex = findTableNumber(iface); 66fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 67fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt tableIndex = findTableNumber(""); // look for an empty slot 68fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 69fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt LOGE("Max number of NATed interfaces reached"); 70fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 71fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "Max number NATed", true); 72fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 73fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 74fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt strncpy(mInterfaceTable[tableIndex], iface, MAX_IFACE_LENGTH); 75fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 76fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 77fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt asprintf(&cmd, "%s route add %s/%d via %s table %d", 78fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt IP_PATH, dest, prefix, gateway, tableIndex+BASE_TABLE_NUMBER); 79fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (runAndFree(cli, cmd)) { 80fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt LOGE("ip route add failed: %s", cmd); 81fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 82fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "ip route add failed", true); 83fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 84fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 85fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceRuleCount[tableIndex]++; 86fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Route added", false); 87fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return 0; 88fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 89fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 90fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::removeRoute(SocketClient *cli, char *iface, char *dest, int prefix, 91fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *gateway) { 92fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt char *cmd; 93fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int tableIndex = findTableNumber(iface); 94fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (tableIndex == -1) { 95fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt LOGE("Interface not found"); 96fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 97fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true); 98fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 99fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 100fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 101fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt asprintf(&cmd, "%s route del %s/%d via %s table %d", 102fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt IP_PATH, dest, prefix, gateway, tableIndex+BASE_TABLE_NUMBER); 103fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (runAndFree(cli, cmd)) { 104fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt LOGE("ip route del failed"); 105fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = ENODEV; 106fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::OperationFailed, "ip route del failed", true); 107fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 108fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 109fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (--mInterfaceRuleCount[tableIndex]<1) { 110fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt mInterfaceTable[tableIndex][0]=0; 111fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 112fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::CommandOkay, "Route removed", false); 113fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return 0; 114fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 115fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt 116fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwaltint SecondaryTableController::runAndFree(SocketClient *cli, char *cmd) { 117fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt int ret = 0; 118fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt if (strlen(cmd) >= 255) { 119fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt LOGE("ip command (%s) too long", cmd); 120fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt errno = E2BIG; 121fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt cli->sendMsg(ResponseCode::CommandSyntaxError, "Too long", true); 122fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt free(cmd); 123fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return -1; 124fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt } 125fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt ret = system(cmd); 126fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt free(cmd); 127fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt return ret; 128fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt} 129