#include "ResponseCode.h"
#include "BandwidthController.h"
#include "IdletimerController.h"
+#include "InterfaceController.h"
#include "oem_iptables_hook.h"
#include "NetdConstants.h"
#include "FirewallController.h"
return 0;
}
int enable = !strncmp(argv[3], "enable", 7);
- if (gCtls->interfaceCtrl.setIPv6PrivacyExtensions(argv[2], enable) == 0) {
+ if (InterfaceController::setIPv6PrivacyExtensions(argv[2], enable) == 0) {
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed,
}
int enable = !strncmp(argv[3], "enable", 7);
- if (gCtls->interfaceCtrl.setEnableIPv6(argv[2], enable) == 0) {
+ if (InterfaceController::setEnableIPv6(argv[2], enable) == 0) {
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed,
return 0;
}
int enable = !strncmp(argv[3], "enable", 7);
- if (gCtls->interfaceCtrl.setIPv6NdOffload(argv[2], enable) == 0) {
+ if (InterfaceController::setIPv6NdOffload(argv[2], enable) == 0) {
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed,
"Usage: interface setmtu <interface> <val>", false);
return 0;
}
- if (gCtls->interfaceCtrl.setMtu(argv[2], argv[3]) == 0) {
+ if (InterfaceController::setMtu(argv[2], argv[3]) == 0) {
cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
} else {
cli->sendMsg(ResponseCode::OperationFailed,
return 0;
} else if (argc == 3) {
if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
- InterfaceCollection *ilist = gCtls->tetherCtrl.getTetheredInterfaceList();
- InterfaceCollection::iterator it;
- for (it = ilist->begin(); it != ilist->end(); ++it) {
- cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
+ for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
+ cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
}
} else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
char netIdStr[UINT32_STRLEN];
snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
- for (const auto &fwdr : *(gCtls->tetherCtrl.getDnsForwarders())) {
+ for (const auto &fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
}
}
namespace android {
namespace net {
-Controllers::Controllers() : clatdCtrl(&netCtrl) {}
+Controllers::Controllers() : clatdCtrl(&netCtrl) {
+ InterfaceController::initializeAll();
+}
Controllers* gCtls = nullptr;
IdletimerController idletimerCtrl;
ResolverController resolverCtrl;
FirewallController firewallCtrl;
- InterfaceController interfaceCtrl;
ClatdController clatdCtrl;
StrictController strictCtrl;
};
} // namespace
-InterfaceController::InterfaceController() {
- // Initial IPv6 settings.
- // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
- // This causes RAs to work or not work based on whether forwarding is on, and causes routes
- // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
- // by always setting accept_ra to 2.
- setAcceptRA("2");
+void InterfaceController::initializeAll() {
+ // Initial IPv6 settings.
+ // By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
+ // This causes RAs to work or not work based on whether forwarding is on, and causes routes
+ // learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
+ // by always setting accept_ra to 2.
+ setAcceptRA("2");
- setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
+ setAcceptRARouteTable(-RouteController::ROUTE_TABLE_OFFSET_FROM_INDEX);
- // Enable optimistic DAD for IPv6 addresses on all interfaces.
- setIPv6OptimisticMode("1");
+ // Enable optimistic DAD for IPv6 addresses on all interfaces.
+ setIPv6OptimisticMode("1");
- // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
- setBaseReachableTimeMs(15 * 1000);
+ // Reduce the ARP/ND base reachable time from the default (30sec) to 15sec.
+ setBaseReachableTimeMs(15 * 1000);
- // When sending traffic via a given interface use only addresses configured
- // on that interface as possible source addresses.
- setIPv6UseOutgoingInterfaceAddrsOnly("1");
-}
-
-InterfaceController::~InterfaceController() {
+ // When sending traffic via a given interface use only addresses configured
+ // on that interface as possible source addresses.
+ setIPv6UseOutgoingInterfaceAddrsOnly("1");
}
int InterfaceController::setEnableIPv6(const char *interface, const int on) {
return writeValueToPath(ipv6_proc_path, interface, "disable_ipv6", disable_ipv6);
}
+int InterfaceController::setAcceptIPv6Ra(const char *interface, const int on) {
+ if (!isIfaceName(interface)) {
+ errno = ENOENT;
+ return -1;
+ }
+ // Because forwarding can be enabled even when tethering is off, we always
+ // use mode "2" (accept RAs, even if forwarding is enabled).
+ const char *accept_ra = on ? "2" : "0";
+ return writeValueToPath(ipv6_proc_path, interface, "accept_ra", accept_ra);
+}
+
+int InterfaceController::setAcceptIPv6Dad(const char *interface, const int on) {
+ if (!isIfaceName(interface)) {
+ errno = ENOENT;
+ return -1;
+ }
+ const char *accept_dad = on ? "1" : "0";
+ return writeValueToPath(ipv6_proc_path, interface, "accept_dad", accept_dad);
+}
+
int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) {
if (!isIfaceName(interface)) {
errno = ENOENT;
#define _INTERFACE_CONTROLLER_H
class InterfaceController {
- public:
- InterfaceController();
- virtual ~InterfaceController();
- int setEnableIPv6(const char *interface, const int on);
- int setIPv6PrivacyExtensions(const char *interface, const int on);
- int setIPv6NdOffload(char* interface, const int on);
- int setMtu(const char *interface, const char *mtu);
+public:
+ static void initializeAll();
- private:
- void setAcceptRA(const char* value);
- void setAcceptRARouteTable(int tableOrOffset);
- void setBaseReachableTimeMs(unsigned int millis);
- void setIPv6OptimisticMode(const char *value);
+ static int setEnableIPv6(const char *interface, const int on);
+ static int setAcceptIPv6Ra(const char *interface, const int on);
+ static int setAcceptIPv6Dad(const char *interface, const int on);
+ static int setIPv6PrivacyExtensions(const char *interface, const int on);
+ static int setIPv6NdOffload(char* interface, const int on);
+ static int setMtu(const char *interface, const char *mtu);
+
+private:
+ static void setAcceptRA(const char* value);
+ static void setAcceptRARouteTable(int tableOrOffset);
+ static void setBaseReachableTimeMs(unsigned int millis);
+ static void setIPv6OptimisticMode(const char *value);
+
+ InterfaceController() = delete;
+ ~InterfaceController() = delete;
};
#endif
#include "Fwmark.h"
#include "NetdConstants.h"
#include "Permission.h"
+#include "InterfaceController.h"
#include "TetherController.h"
namespace {
-static const char BP_TOOLS_MODE[] = "bp-tools";
-static const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
-static const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
-static const char SEPARATOR[] = "|";
+const char BP_TOOLS_MODE[] = "bp-tools";
+const char IPV4_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv4/ip_forward";
+const char IPV6_FORWARDING_PROC_FILE[] = "/proc/sys/net/ipv6/conf/all/forwarding";
+const char SEPARATOR[] = "|";
bool writeToFile(const char* filename, const char* value) {
int fd = open(filename, O_WRONLY);
return true;
}
+bool configureForIPv6Router(const char *interface) {
+ return (InterfaceController::setEnableIPv6(interface, 0) == 0)
+ && (InterfaceController::setAcceptIPv6Ra(interface, 0) == 0)
+ && (InterfaceController::setEnableIPv6(interface, 1) == 0);
+}
+
+void configureForIPv6Client(const char *interface) {
+ InterfaceController::setAcceptIPv6Ra(interface, 1);
+ InterfaceController::setEnableIPv6(interface, 0);
+}
+
bool inBpToolsMode() {
// In BP tools mode, do not disable IP forwarding
char bootmode[PROPERTY_VALUE_MAX] = {0};
} // namespace
TetherController::TetherController() {
- mInterfaces = new InterfaceCollection();
mDnsNetId = 0;
- mDnsForwarders = new NetAddressCollection();
mDaemonFd = -1;
mDaemonPid = 0;
if (inBpToolsMode()) {
}
TetherController::~TetherController() {
- InterfaceCollection::iterator it;
-
- for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
- free(*it);
- }
- mInterfaces->clear();
-
- mDnsForwarders->clear();
+ mInterfaces.clear();
+ mDnsForwarders.clear();
mForwardingRequests.clear();
}
snprintf(daemonCmd, sizeof(daemonCmd), "update_dns%s0x%x", SEPARATOR, fwmark.intValue);
int cmdLen = strlen(daemonCmd);
- mDnsForwarders->clear();
+ mDnsForwarders.clear();
for (i = 0; i < numServers; i++) {
ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
freeaddrinfo(res);
if (ret) {
ALOGE("Failed to parse DNS server '%s'", servers[i]);
- mDnsForwarders->clear();
+ mDnsForwarders.clear();
errno = EINVAL;
return -1;
}
strcat(daemonCmd, SEPARATOR);
strcat(daemonCmd, servers[i]);
- mDnsForwarders->push_back(servers[i]);
+ mDnsForwarders.push_back(servers[i]);
}
mDnsNetId = netId;
ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
- mDnsForwarders->clear();
+ mDnsForwarders.clear();
errno = EREMOTEIO;
return -1;
}
return mDnsNetId;
}
-NetAddressCollection *TetherController::getDnsForwarders() {
+const std::list<std::string> &TetherController::getDnsForwarders() const {
return mDnsForwarders;
}
-int TetherController::applyDnsInterfaces() {
+bool TetherController::applyDnsInterfaces() {
char daemonCmd[MAX_CMD_SIZE];
strcpy(daemonCmd, "update_ifaces");
int cmdLen = strlen(daemonCmd);
- InterfaceCollection::iterator it;
bool haveInterfaces = false;
- for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
- cmdLen += (strlen(*it) + 1);
+ for (const auto &ifname : mInterfaces) {
+ cmdLen += (ifname.size() + 1);
if (cmdLen + 1 >= MAX_CMD_SIZE) {
ALOGD("Too many DNS ifaces listed");
break;
}
strcat(daemonCmd, SEPARATOR);
- strcat(daemonCmd, *it);
+ strcat(daemonCmd, ifname.c_str());
haveInterfaces = true;
}
ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
- return -1;
+ return false;
}
}
- return 0;
+ return true;
}
int TetherController::tetherInterface(const char *interface) {
errno = ENOENT;
return -1;
}
- mInterfaces->push_back(strdup(interface));
-
- if (applyDnsInterfaces()) {
- InterfaceCollection::iterator it;
- for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
- if (!strcmp(interface, *it)) {
- free(*it);
- mInterfaces->erase(it);
- break;
- }
- }
+
+ if (!configureForIPv6Router(interface)) {
+ configureForIPv6Client(interface);
+ return -1;
+ }
+ mInterfaces.push_back(interface);
+
+ if (!applyDnsInterfaces()) {
+ mInterfaces.pop_back();
+ configureForIPv6Client(interface);
return -1;
} else {
return 0;
}
int TetherController::untetherInterface(const char *interface) {
- InterfaceCollection::iterator it;
-
ALOGD("untetherInterface(%s)", interface);
- for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
- if (!strcmp(interface, *it)) {
- free(*it);
- mInterfaces->erase(it);
+ for (auto it = mInterfaces.cbegin(); it != mInterfaces.cend(); ++it) {
+ if (!strcmp(interface, it->c_str())) {
+ mInterfaces.erase(it);
- return applyDnsInterfaces();
+ configureForIPv6Client(interface);
+ return applyDnsInterfaces() ? 0 : -1;
}
}
errno = ENOENT;
return -1;
}
-InterfaceCollection *TetherController::getTetheredInterfaceList() {
+const std::list<std::string> &TetherController::getTetheredInterfaceList() const {
return mInterfaces;
}
#include <set>
#include <string>
-typedef std::list<char *> InterfaceCollection;
-typedef std::list<std::string> NetAddressCollection;
class TetherController {
- InterfaceCollection *mInterfaces;
+private:
+ std::list<std::string> mInterfaces;
// NetId to use for forwarded DNS queries. This may not be the default
// network, e.g., in the case where we are tethering to a DUN APN.
- unsigned mDnsNetId;
- NetAddressCollection *mDnsForwarders;
- pid_t mDaemonPid;
- int mDaemonFd;
- std::set<std::string> mForwardingRequests;
+ unsigned mDnsNetId;
+ std::list<std::string> mDnsForwarders;
+ pid_t mDaemonPid;
+ int mDaemonFd;
+ std::set<std::string> mForwardingRequests;
public:
TetherController();
unsigned getDnsNetId();
int setDnsForwarders(unsigned netId, char **servers, int numServers);
- NetAddressCollection *getDnsForwarders();
+ const std::list<std::string> &getDnsForwarders() const;
int tetherInterface(const char *interface);
int untetherInterface(const char *interface);
- InterfaceCollection *getTetheredInterfaceList();
+ const std::list<std::string> &getTetheredInterfaceList() const;
private:
- int applyDnsInterfaces();
+ bool applyDnsInterfaces();
bool setIpFwdEnabled();
};