am 5ff04590: am 4ea5bd05: Merge "Revert "netd: reduce privileges""
* commit '5ff04590386a08712d83c4f8add6d78870fe3bce':
Revert "netd: reduce privileges"
diff --git a/CommandListener.cpp b/CommandListener.cpp
index e8876b5..026797f 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -92,6 +92,11 @@
NULL,
};
+static const char* MANGLE_OUTPUT[] = {
+ SecondaryTableController::LOCAL_MANGLE_OUTPUT,
+ NULL,
+};
+
static const char* NAT_PREROUTING[] = {
OEM_IPTABLES_NAT_PREROUTING,
NULL,
@@ -99,6 +104,7 @@
static const char* NAT_POSTROUTING[] = {
NatController::LOCAL_NAT_POSTROUTING,
+ SecondaryTableController::LOCAL_NAT_POSTROUTING,
NULL,
};
@@ -176,6 +182,7 @@
createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
+ createChildChains(V4V6, "mangle", "OUTPUT", MANGLE_OUTPUT);
createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
@@ -254,10 +261,64 @@
return 0;
}
- // 0 1 2 3 4 5 6 7
- // interface route add/remove iface default/secondary dest prefix gateway
+ // 0 1 2 3 4 5 6 7
+ // interface route add/remove iface default/secondary dest prefix gateway
+ // interface route fwmark add/remove iface
+ // interface route uid add/remove iface uid_start uid_end
if (!strcmp(argv[1], "route")) {
int prefix_length = 0;
+ if (!strcmp(argv[2], "fwmark")) {
+ if (argc < 5) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+ return 0;
+ }
+ if (!strcmp(argv[3], "add")) {
+ if (!sSecondaryTableCtrl->addFwmarkRule(argv[4])) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Fwmark rule successfully added",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to add fwmark rule",
+ true);
+ }
+ } else if (!strcmp(argv[3], "remove")) {
+ if (!sSecondaryTableCtrl->removeFwmarkRule(argv[4])) {
+ cli->sendMsg(ResponseCode::CommandOkay, "Fwmark rule successfully removed",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove fwmark rule",
+ true);
+ }
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark cmd", false);
+ }
+ return 0;
+ }
+ if (!strcmp(argv[2], "uid")) {
+ if (argc < 7) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+ return 0;
+ }
+ if (!strcmp(argv[3], "add")) {
+ if (!sSecondaryTableCtrl->addUidRule(argv[4], atoi(argv[5]), atoi(argv[6]))) {
+ cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully added",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to add uid rule", true);
+ }
+ } else if (!strcmp(argv[3], "remove")) {
+ if (!sSecondaryTableCtrl->removeUidRule(argv[4],
+ atoi(argv[5]), atoi(argv[6]))) {
+ cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully removed",
+ false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove uid rule",
+ true);
+ }
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown uid cmd", false);
+ }
+ return 0;
+ }
if (argc < 8) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
@@ -462,6 +523,31 @@
"Failed to change IPv6 state", true);
}
return 0;
+ } else if (!strcmp(argv[1], "getmtu")) {
+ char *msg = NULL;
+ int mtu = 0;
+ if (sInterfaceCtrl->getMtu(argv[2], &mtu) == 0) {
+ asprintf(&msg, "MTU = %d", mtu);
+ cli->sendMsg(ResponseCode::InterfaceGetMtuResult, msg, false);
+ free(msg);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed,
+ "Failed to get MTU", true);
+ }
+ return 0;
+ } else if (!strcmp(argv[1], "setmtu")) {
+ if (argc != 4) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Usage: interface setmtu <interface> <val>", false);
+ return 0;
+ }
+ if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
+ cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
+ } else {
+ cli->sendMsg(ResponseCode::OperationFailed,
+ "Failed to get MTU", true);
+ }
+ return 0;
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
return 0;
@@ -767,9 +853,10 @@
NetdCommand("resolver") {
}
-int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
+int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
int rc = 0;
struct in_addr addr;
+ const char **argv = const_cast<const char **>(margv);
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
@@ -835,6 +922,29 @@
"Wrong number of arguments to resolver clearifaceforpid", false);
return 0;
}
+ } else if (!strcmp(argv[1], "setifaceforuidrange")) { // resolver setifaceforuid <iface> <l> <h>
+ if (argc == 5) {
+ rc = sResolverCtrl->setDnsInterfaceForUidRange(argv[2], atoi(argv[3]), atoi(argv[4]));
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Wrong number of arguments to resolver setifaceforuid", false);
+ return 0;
+ }
+ } else if (!strcmp(argv[1], "clearifaceforuidrange")) { // resolver clearifaceforuid <l> <h>
+ if (argc == 4) {
+ rc = sResolverCtrl->clearDnsInterfaceForUidRange(atoi(argv[2]), atoi(argv[3]));
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Wrong number of arguments to resolver clearifaceforuid", false);
+ return 0;
+ }
+ } else if (!strcmp(argv[1], "clearifacemapping")) {
+ if (argc == 2) {
+ rc = sResolverCtrl->clearDnsInterfaceMappings();
+ } else {
+ cli->sendMsg(ResponseCode::CommandSyntaxError,
+ "Wrong number of arugments to resolver clearifacemapping", false);
+ }
} else {
cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
return 0;
diff --git a/DnsProxyListener.cpp b/DnsProxyListener.cpp
index cee8d10..18fa267 100644
--- a/DnsProxyListener.cpp
+++ b/DnsProxyListener.cpp
@@ -50,13 +50,15 @@
char* service,
struct addrinfo* hints,
char* iface,
- pid_t pid)
+ pid_t pid,
+ uid_t uid)
: mClient(c),
mHost(host),
mService(service),
mHints(hints),
mIface(iface),
- mPid(pid) {
+ mPid(pid),
+ mUid(uid) {
}
DnsProxyListener::GetAddrInfoHandler::~GetAddrInfoHandler() {
@@ -124,7 +126,9 @@
char tmp[IF_NAMESIZE + 1];
if (mIface == NULL) {
- _resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp));
+ //fall back to the per uid interface if no per pid interface exists
+ if(!_resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp)))
+ _resolv_get_uids_associated_interface(mUid, tmp, sizeof(tmp));
}
struct addrinfo* result = NULL;
@@ -202,6 +206,7 @@
int ai_socktype = atoi(argv[5]);
int ai_protocol = atoi(argv[6]);
pid_t pid = cli->getPid();
+ uid_t uid = cli->getUid();
if (ai_flags != -1 || ai_family != -1 ||
ai_socktype != -1 || ai_protocol != -1) {
@@ -213,16 +218,16 @@
}
if (DBG) {
- ALOGD("GetAddrInfoHandler for %s / %s / %s / %d",
+ ALOGD("GetAddrInfoHandler for %s / %s / %s / %d / %d",
name ? name : "[nullhost]",
service ? service : "[nullservice]",
iface ? iface : "[nulliface]",
- pid);
+ pid, uid);
}
cli->incRef();
DnsProxyListener::GetAddrInfoHandler* handler =
- new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, iface, pid);
+ new DnsProxyListener::GetAddrInfoHandler(cli, name, service, hints, iface, pid, uid);
handler->start();
return 0;
@@ -252,6 +257,7 @@
}
pid_t pid = cli->getPid();
+ uid_t uid = cli->getUid();
char* iface = argv[1];
char* name = argv[2];
int af = atoi(argv[3]);
@@ -270,7 +276,7 @@
cli->incRef();
DnsProxyListener::GetHostByNameHandler* handler =
- new DnsProxyListener::GetHostByNameHandler(cli, pid, iface, name, af);
+ new DnsProxyListener::GetHostByNameHandler(cli, pid, uid, iface, name, af);
handler->start();
return 0;
@@ -278,11 +284,13 @@
DnsProxyListener::GetHostByNameHandler::GetHostByNameHandler(SocketClient* c,
pid_t pid,
+ uid_t uid,
char* iface,
char* name,
int af)
: mClient(c),
mPid(pid),
+ mUid(uid),
mIface(iface),
mName(name),
mAf(af) {
@@ -315,7 +323,9 @@
char iface[IF_NAMESIZE + 1];
if (mIface == NULL) {
- _resolv_get_pids_associated_interface(mPid, iface, sizeof(iface));
+ //fall back to the per uid interface if no per pid interface exists
+ if(!_resolv_get_pids_associated_interface(mPid, iface, sizeof(iface)))
+ _resolv_get_uids_associated_interface(mUid, iface, sizeof(iface));
}
struct hostent* hp;
@@ -371,6 +381,7 @@
int addrLen = atoi(argv[2]);
int addrFamily = atoi(argv[3]);
pid_t pid = cli->getPid();
+ uid_t uid = cli->getUid();
char* iface = argv[4];
if (strcmp(iface, "^") == 0) {
@@ -394,7 +405,7 @@
cli->incRef();
DnsProxyListener::GetHostByAddrHandler* handler =
- new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, iface ,pid);
+ new DnsProxyListener::GetHostByAddrHandler(cli, addr, addrLen, addrFamily, iface, pid, uid);
handler->start();
return 0;
@@ -405,13 +416,15 @@
int addressLen,
int addressFamily,
char* iface,
- pid_t pid)
+ pid_t pid,
+ uid_t uid)
: mClient(c),
mAddress(address),
mAddressLen(addressLen),
mAddressFamily(addressFamily),
mIface(iface),
- mPid(pid) {
+ mPid(pid),
+ mUid(uid) {
}
DnsProxyListener::GetHostByAddrHandler::~GetHostByAddrHandler() {
@@ -441,9 +454,10 @@
char tmp[IF_NAMESIZE + 1];
if (mIface == NULL) {
- _resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp));
+ //fall back to the per uid interface if no per pid interface exists
+ if(!_resolv_get_pids_associated_interface(mPid, tmp, sizeof(tmp)))
+ _resolv_get_uids_associated_interface(mUid, tmp, sizeof(tmp));
}
-
struct hostent* hp;
// NOTE gethostbyaddr should take a void* but bionic thinks it should be char*
diff --git a/DnsProxyListener.h b/DnsProxyListener.h
index c950c02..758ca76 100644
--- a/DnsProxyListener.h
+++ b/DnsProxyListener.h
@@ -42,7 +42,8 @@
char* service,
struct addrinfo* hints,
char* iface,
- pid_t pid);
+ pid_t pid,
+ uid_t uid);
~GetAddrInfoHandler();
static void* threadStart(void* handler);
@@ -56,6 +57,7 @@
struct addrinfo* mHints; // owned
char* mIface; // owned
pid_t mPid;
+ uid_t mUid;
};
/* ------ gethostbyname ------*/
@@ -70,6 +72,7 @@
public:
GetHostByNameHandler(SocketClient *c,
pid_t pid,
+ uid_t uid,
char *iface,
char *name,
int af);
@@ -80,6 +83,7 @@
void run();
SocketClient* mClient; //ref counted
pid_t mPid;
+ uid_t mUid;
char* mIface; // owned
char* mName; // owned
int mAf;
@@ -100,7 +104,8 @@
int addressLen,
int addressFamily,
char* iface,
- pid_t pid);
+ pid_t pid,
+ uid_t uid);
~GetHostByAddrHandler();
static void* threadStart(void* handler);
@@ -114,6 +119,7 @@
int mAddressFamily; // address family
char* mIface; // owned
pid_t mPid;
+ uid_t mUid;
};
};
diff --git a/InterfaceController.cpp b/InterfaceController.cpp
index 0d8f121..c305be9 100644
--- a/InterfaceController.cpp
+++ b/InterfaceController.cpp
@@ -46,6 +46,8 @@
const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
+const char sys_net_path[] = "/sys/class/net";
+
InterfaceController::InterfaceController()
: sendCommand_(NULL) {
// Initial IPv6 settings.
@@ -163,3 +165,26 @@
closedir(dir);
return 0;
}
+
+int InterfaceController::getMtu(const char *interface, int *mtu)
+{
+ char buf[16];
+ int size = sizeof(buf);
+ char *path;
+ asprintf(&path, "%s/%s/mtu", sys_net_path, interface);
+ int success = readFile(path, buf, &size);
+ if (!success && mtu)
+ *mtu = atoi(buf);
+ free(path);
+ return success;
+
+}
+
+int InterfaceController::setMtu(const char *interface, const char *mtu)
+{
+ char *path;
+ asprintf(&path, "%s/%s/mtu", sys_net_path, interface);
+ int success = writeFile(path, mtu, strlen(mtu));
+ free(path);
+ return success;
+}
diff --git a/InterfaceController.h b/InterfaceController.h
index 5943a9a..b8bbc92 100644
--- a/InterfaceController.h
+++ b/InterfaceController.h
@@ -35,6 +35,8 @@
int interfaceCommand(int argc, char *argv[], char **rbuf);
int setEnableIPv6(const char *interface, const int on);
int setIPv6PrivacyExtensions(const char *interface, const int on);
+ int getMtu(const char *interface, int *mtu);
+ int setMtu(const char *interface, const char *mtu);
private:
void *libh_;
diff --git a/NetdConstants.cpp b/NetdConstants.cpp
index 1ab09a5..c3c16eb 100644
--- a/NetdConstants.cpp
+++ b/NetdConstants.cpp
@@ -122,3 +122,24 @@
close(fd);
return 0;
}
+
+int readFile(const char *path, char *buf, int *sizep)
+{
+ int fd = open(path, O_RDONLY);
+ int size;
+
+ if (fd < 0) {
+ ALOGE("Failed to open %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ size = read(fd, buf, *sizep);
+ if (size < 0) {
+ ALOGE("Failed to write %s: %s", path, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ *sizep = size;
+ close(fd);
+ return 0;
+}
diff --git a/NetdConstants.h b/NetdConstants.h
index eb59af2..d686968 100644
--- a/NetdConstants.h
+++ b/NetdConstants.h
@@ -34,6 +34,7 @@
int execIptables(IptablesTarget target, ...);
int execIptablesSilently(IptablesTarget target, ...);
int writeFile(const char *path, const char *value, int size);
+int readFile(const char *path, char *buf, int *sizep);
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
diff --git a/ResolverController.cpp b/ResolverController.cpp
index 13dd930..e61fae7 100644
--- a/ResolverController.cpp
+++ b/ResolverController.cpp
@@ -38,7 +38,7 @@
}
int ResolverController::setInterfaceDnsServers(const char* iface, const char* domains,
- char** servers, int numservers) {
+ const char** servers, int numservers) {
if (DBG) {
ALOGD("setInterfaceDnsServers iface = %s\n", iface);
}
@@ -96,3 +96,30 @@
return 0;
}
+
+int ResolverController::setDnsInterfaceForUidRange(const char* iface, int uid_start, int uid_end) {
+ if (DBG) {
+ ALOGD("setDnsIfaceForUidRange iface = %s, range = [%d,%d]\n", iface, uid_start, uid_end);
+ }
+
+ return _resolv_set_iface_for_uid_range(iface, uid_start, uid_end);
+}
+
+int ResolverController::clearDnsInterfaceForUidRange(int uid_start, int uid_end) {
+ if (DBG) {
+ ALOGD("clearDnsIfaceForUidRange range = [%d,%d]\n", uid_start, uid_end);
+ }
+
+ return _resolv_clear_iface_for_uid_range(uid_start, uid_end);
+}
+
+int ResolverController::clearDnsInterfaceMappings()
+{
+ if (DBG) {
+ ALOGD("clearInterfaceMappings\n");
+ }
+ _resolv_clear_iface_uid_range_mapping();
+ _resolv_clear_iface_pid_mapping();
+
+ return 0;
+}
diff --git a/ResolverController.h b/ResolverController.h
index a21e077..e705c8f 100644
--- a/ResolverController.h
+++ b/ResolverController.h
@@ -26,13 +26,16 @@
virtual ~ResolverController() {};
int setDefaultInterface(const char* iface);
- int setInterfaceDnsServers(const char* iface, const char * domains, char** servers,
+ int setInterfaceDnsServers(const char* iface, const char * domains, const char** servers,
int numservers);
int setInterfaceAddress(const char* iface, struct in_addr* addr);
int flushDefaultDnsCache();
int flushInterfaceDnsCache(const char* iface);
int setDnsInterfaceForPid(const char* iface, int pid);
int clearDnsInterfaceForPid(int pid);
+ int setDnsInterfaceForUidRange(const char* iface, int uid_start, int uid_end);
+ int clearDnsInterfaceForUidRange(int uid_start, int uid_end);
+ int clearDnsInterfaceMappings();
};
#endif /* _RESOLVER_CONTROLLER_H_ */
diff --git a/ResponseCode.h b/ResponseCode.h
index 7689ef8..85f183a 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -45,6 +45,7 @@
static const int TetheringStatsResult = 221;
static const int DnsProxyQueryResult = 222;
static const int ClatdStatusResult = 223;
+ static const int InterfaceGetMtuResult = 224;
// 400 series - The command was accepted but the requested action
// did not take place.
diff --git a/SecondaryTableController.cpp b/SecondaryTableController.cpp
index ce23d28..222a0e0 100644
--- a/SecondaryTableController.cpp
+++ b/SecondaryTableController.cpp
@@ -36,6 +36,9 @@
#include "NetdConstants.h"
#include "SecondaryTableController.h"
+const char* SecondaryTableController::LOCAL_MANGLE_OUTPUT = "st_mangle_OUTPUT";
+const char* SecondaryTableController::LOCAL_NAT_POSTROUTING = "st_nat_POSTROUTING";
+
SecondaryTableController::SecondaryTableController() {
int i;
for (i=0; i < INTERFACES_TRACKED; i++) {
@@ -232,6 +235,93 @@
return runCmd(ARRAY_SIZE(cmd), cmd);
}
+int SecondaryTableController::addFwmarkRule(const char *iface) {
+ return setFwmarkRule(iface, true);
+}
+
+int SecondaryTableController::removeFwmarkRule(const char *iface) {
+ return setFwmarkRule(iface, false);
+}
+
+int SecondaryTableController::setFwmarkRule(const char *iface, bool add) {
+ char tableIndex_str[11];
+ int tableIndex = findTableNumber(iface);
+ if (tableIndex == -1) {
+ tableIndex = findTableNumber(""); // look for an empty slot
+ if (tableIndex == -1) {
+ ALOGE("Max number of NATed interfaces reached");
+ errno = ENODEV;
+ return -1;
+ }
+ strncpy(mInterfaceTable[tableIndex], iface, IFNAMSIZ);
+ // Ensure null termination even if truncation happened
+ mInterfaceTable[tableIndex][IFNAMSIZ] = 0;
+ }
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex +
+ BASE_TABLE_NUMBER);
+ const char *cmd[] = {
+ IP_PATH,
+ "rule",
+ add ? "add" : "del",
+ "fwmark",
+ tableIndex_str,
+ "table",
+ tableIndex_str
+ };
+ int ret = runCmd(ARRAY_SIZE(cmd), cmd);
+ if (ret) return ret;
+
+ //set up the needed source IP rewriting
+ //NOTE: Without ipv6 NAT in the kernel <3.7 only support V4 NAT
+ return execIptables(V4,
+ "-t",
+ "nat",
+ add ? "-A" : "-D",
+ LOCAL_NAT_POSTROUTING,
+ "-o",
+ iface,
+ "-m",
+ "mark",
+ "--mark",
+ tableIndex_str,
+ "-j",
+ "MASQUERADE",
+ NULL);
+
+}
+
+int SecondaryTableController::addUidRule(const char *iface, int uid_start, int uid_end) {
+ return setUidRule(iface, uid_start, uid_end, true);
+}
+
+int SecondaryTableController::removeUidRule(const char *iface, int uid_start, int uid_end) {
+ return setUidRule(iface, uid_start, uid_end, false);
+}
+
+int SecondaryTableController::setUidRule(const char *iface, int uid_start, int uid_end, bool add) {
+ int tableIndex = findTableNumber(iface);
+ if (tableIndex == -1) {
+ return -1;
+ }
+ char tableIndex_str[11] = {0};
+ snprintf(tableIndex_str, sizeof(tableIndex_str), "%d", tableIndex + BASE_TABLE_NUMBER);
+ char uid_str[24] = {0};
+ snprintf(uid_str, sizeof(uid_str), "%d-%d", uid_start, uid_end);
+ return execIptables(V4V6,
+ "-t",
+ "mangle",
+ add ? "-A" : "-D",
+ LOCAL_MANGLE_OUTPUT,
+ "-m",
+ "owner",
+ "--uid-owner",
+ uid_str,
+ "-j",
+ "MARK",
+ "--set-mark",
+ tableIndex_str,
+ NULL);
+}
int SecondaryTableController::runCmd(int argc, const char **argv) {
int ret = 0;
diff --git a/SecondaryTableController.h b/SecondaryTableController.h
index 8531900..3941ba1 100644
--- a/SecondaryTableController.h
+++ b/SecondaryTableController.h
@@ -40,8 +40,18 @@
int findTableNumber(const char *iface);
int modifyFromRule(int tableIndex, const char *action, const char *addr);
int modifyLocalRoute(int tableIndex, const char *action, const char *iface, const char *addr);
+ int addUidRule(const char *iface, int uid_start, int uid_end);
+ int removeUidRule(const char *iface, int uid_start, int uid_end);
+ int addFwmarkRule(const char *iface);
+ int removeFwmarkRule(const char *iface);
+
+ static const char* LOCAL_MANGLE_OUTPUT;
+ static const char* LOCAL_NAT_POSTROUTING;
+
private:
+ int setUidRule(const char* iface, int uid_start, int uid_end, bool add);
+ int setFwmarkRule(const char *iface, bool add);
int modifyRoute(SocketClient *cli, const char *action, char *iface, char *dest, int prefix,
char *gateway, int tableIndex);
diff --git a/SoftapController.cpp b/SoftapController.cpp
index 0b1899c..825a376 100644
--- a/SoftapController.cpp
+++ b/SoftapController.cpp
@@ -106,36 +106,53 @@
* Arguments:
* argv[2] - wlan interface
* argv[3] - SSID
- * argv[4] - Security
- * argv[5] - Key
+ * argv[4] - Broadcast/Hidden
+ * argv[5] - Channel
+ * argv[6] - Security
+ * argv[7] - Key
*/
int SoftapController::setSoftap(int argc, char *argv[]) {
char psk_str[2*SHA256_DIGEST_LENGTH+1];
int ret = ResponseCode::SoftapStatusResult;
int i = 0;
int fd;
-
- if (argc < 4) {
- ALOGE("Softap set is missing arguments. Please use: softap <wlan iface> <SSID> <wpa2?-psk|open> <passphrase>");
- return ResponseCode::CommandSyntaxError;
- }
-
+ int hidden = 0;
+ int channel = AP_CHANNEL_DEFAULT;
char *wbuf = NULL;
char *fbuf = NULL;
- asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
- "/data/misc/wifi/hostapd\nssid=%s\nchannel=6\nieee80211n=1\n"
- "hw_mode=g\n",
- argv[2], argv[3]);
+ if (argc < 5) {
+ ALOGE("Softap set is missing arguments. Please use:");
+ ALOGE("softap <wlan iface> <SSID> <hidden/broadcast> <channel> <wpa2?-psk|open> <passphrase>");
+ return ResponseCode::CommandSyntaxError;
+ }
- if (argc > 4) {
- if (!strcmp(argv[4], "wpa-psk")) {
- generatePsk(argv[3], argv[5], psk_str);
+ if (!strcasecmp(argv[4], "hidden"))
+ hidden = 1;
+
+ if (argc >= 5) {
+ channel = atoi(argv[5]);
+ if (channel <= 0)
+ channel = AP_CHANNEL_DEFAULT;
+ }
+
+ asprintf(&wbuf, "interface=%s\ndriver=nl80211\nctrl_interface="
+ "/data/misc/wifi/hostapd\nssid=%s\nchannel=%d\nieee80211n=1\n"
+ "hw_mode=g\nignore_broadcast_ssid=%d\n",
+ argv[2], argv[3], channel, hidden);
+
+ if (argc > 7) {
+ if (!strcmp(argv[6], "wpa-psk")) {
+ generatePsk(argv[3], argv[7], psk_str);
asprintf(&fbuf, "%swpa=1\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf, psk_str);
- } else if (!strcmp(argv[4], "wpa2-psk")) {
- generatePsk(argv[3], argv[5], psk_str);
+ } else if (!strcmp(argv[6], "wpa2-psk")) {
+ generatePsk(argv[3], argv[7], psk_str);
asprintf(&fbuf, "%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf, psk_str);
- } else if (!strcmp(argv[4], "open")) {
+ } else if (!strcmp(argv[6], "open")) {
+ asprintf(&fbuf, "%s", wbuf);
+ }
+ } else if (argc > 6) {
+ if (!strcmp(argv[6], "open")) {
asprintf(&fbuf, "%s", wbuf);
}
} else {
diff --git a/SoftapController.h b/SoftapController.h
index 38ff8ff..7063067 100644
--- a/SoftapController.h
+++ b/SoftapController.h
@@ -25,6 +25,7 @@
#define AP_BSS_STOP_DELAY 500000
#define AP_SET_CFG_DELAY 500000
#define AP_DRIVER_START_DELAY 800000
+#define AP_CHANNEL_DEFAULT 6
class SoftapController {
public:
diff --git a/ndc.c b/ndc.c
index 29a399a..1f76c2a 100644
--- a/ndc.c
+++ b/ndc.c
@@ -65,14 +65,23 @@
}
static int do_cmd(int sock, int argc, char **argv) {
- char *final_cmd = strdup("0 ");
- if (final_cmd == NULL) {
- perror("strdup");
- return errno;
- }
-
+ char *final_cmd;
+ char *conv_ptr;
int i;
+ /* Check if 1st arg is cmd sequence number */
+ strtol(argv[1], &conv_ptr, 10);
+ if (conv_ptr == argv[1]) {
+ final_cmd = strdup("0 ");
+ } else {
+ final_cmd = strdup("");
+ }
+ if (final_cmd == NULL) {
+ int res = errno;
+ perror("strdup failed");
+ return res;
+ }
+
for (i = 1; i < argc; i++) {
if (index(argv[i], '"')) {
perror("argument with embedded quotes not allowed");
@@ -81,22 +90,24 @@
}
bool needs_quoting = index(argv[i], ' ');
const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s";
- char *cmp;
+ char *tmp_final_cmd;
- if (asprintf(&cmp, format, final_cmd, argv[i],
- (i == (argc -1)) ? "" : " ") < 0) {
- perror("malloc");
+ if (asprintf(&tmp_final_cmd, format, final_cmd, argv[i],
+ (i == (argc - 1)) ? "" : " ") < 0) {
+ int res = errno;
+ perror("failed asprintf");
free(final_cmd);
- return errno;
+ return res;
}
free(final_cmd);
- final_cmd = cmp;
+ final_cmd = tmp_final_cmd;
}
if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {
+ int res = errno;
perror("write");
free(final_cmd);
- return errno;
+ return res;
}
free(final_cmd);
@@ -121,9 +132,10 @@
FD_SET(sock, &read_fds);
if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
+ int res = errno;
fprintf(stderr, "Error in select (%s)\n", strerror(errno));
free(buffer);
- return errno;
+ return res;
} else if (!rc) {
continue;
fprintf(stderr, "[TIMEOUT]\n");
@@ -131,6 +143,7 @@
} else if (FD_ISSET(sock, &read_fds)) {
memset(buffer, 0, 4096);
if ((rc = read(sock, buffer, 4096)) <= 0) {
+ int res = errno;
if (rc == 0)
fprintf(stderr, "Lost connection to Netd - did it crash?\n");
else
@@ -138,7 +151,7 @@
free(buffer);
if (rc == 0)
return ECONNRESET;
- return errno;
+ return res;
}
int offset = 0;
@@ -168,6 +181,6 @@
}
static void usage(char *progname) {
- fprintf(stderr, "Usage: %s [sockname] <monitor>|<cmd> [arg1] [arg2...]\n", progname);
+ fprintf(stderr, "Usage: %s [<sockname>] ([monitor] | ([<cmd_seq_num>] <cmd> [arg ...]))\n", progname);
exit(1);
}