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