NDC migration to binder ver.
Make ndc communicating with netd via binder
Bug: 65862741
Test: built, flashed, booted
system/netd/tests/runtests.sh pass
manual test ndc commands
Change-Id: I9edfda61d8c3a4d7b404a428e7dbb4d08eff62a9
diff --git a/server/Android.bp b/server/Android.bp
index 5f2f373..bd30f47 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -138,7 +138,6 @@
"libnetd_resolv_headers",
],
srcs: [
- "CommandListener.cpp",
"DummyNetwork.cpp",
"EventReporter.cpp",
"FwmarkServer.cpp",
@@ -163,8 +162,28 @@
cc_binary {
name: "ndc",
defaults: ["netd_defaults"],
- shared_libs: ["libcutils"],
- srcs: ["ndc.cpp"],
+ include_dirs: [
+ "system/netd/include",
+ ],
+ header_libs: [
+ "libnetd_client_headers",
+ ],
+ shared_libs: [
+ "libbase",
+ "libnetdutils",
+ "libnetutils",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libbinder",
+ "dnsresolver_aidl_interface-cpp",
+ "netd_aidl_interface-cpp",
+ ],
+ srcs: [
+ "ndc.cpp",
+ "UidRanges.cpp",
+ "NdcDispatcher.cpp",
+ ],
}
cc_test {
diff --git a/server/CommandListener.h b/server/CommandListener.h
deleted file mode 100644
index d0e8c7e..0000000
--- a/server/CommandListener.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _COMMANDLISTENER_H__
-#define _COMMANDLISTENER_H__
-
-#include <mutex>
-
-#include <android/net/INetd.h>
-#include <sysutils/FrameworkListener.h>
-#include "binder/IServiceManager.h"
-
-#include "BandwidthController.h"
-#include "ClatdController.h"
-#include "FirewallController.h"
-#include "IdletimerController.h"
-#include "InterfaceController.h"
-#include "NetdCommand.h"
-#include "NetdConstants.h"
-
-namespace android {
-namespace net {
-
-class CommandListener : public FrameworkListener {
- public:
- CommandListener();
- virtual ~CommandListener() {}
-
- static constexpr const char* SOCKET_NAME = "netd";
- static sp<INetd> mNetd;
-
- private:
- class InterfaceCmd : public NetdCommand {
- public:
- InterfaceCmd();
- virtual ~InterfaceCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class IpFwdCmd : public NetdCommand {
- public:
- IpFwdCmd();
- virtual ~IpFwdCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class TetherCmd : public NetdCommand {
- public:
- TetherCmd();
- virtual ~TetherCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class NatCmd : public NetdCommand {
- public:
- NatCmd();
- virtual ~NatCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class BandwidthControlCmd : public NetdCommand {
- public:
- BandwidthControlCmd();
- virtual ~BandwidthControlCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- protected:
- void sendGenericOkFail(SocketClient *cli, int cond);
- void sendGenericOpFailed(SocketClient *cli, const char *errMsg);
- void sendGenericSyntaxError(SocketClient *cli, const char *usageMsg);
- };
-
- class IdletimerControlCmd : public NetdCommand {
- public:
- IdletimerControlCmd();
- virtual ~IdletimerControlCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class FirewallCmd: public NetdCommand {
- public:
- FirewallCmd();
- virtual ~FirewallCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- protected:
- int sendGenericOkFail(SocketClient *cli, int cond);
- static int parseRule(const char* arg);
- static int parseFirewallType(const char* arg);
- static int parseChildChain(const char* arg);
- };
-
- class ClatdCmd : public NetdCommand {
- public:
- ClatdCmd();
- virtual ~ClatdCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
- class StrictCmd : public NetdCommand {
- public:
- StrictCmd();
- virtual ~StrictCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- protected:
- int sendGenericOkFail(SocketClient *cli, int cond);
- static int parsePenalty(const char* arg);
- };
-
- class NetworkCommand : public NetdCommand {
- public:
- NetworkCommand();
- virtual ~NetworkCommand() {}
- int runCommand(SocketClient* client, int argc, char** argv);
- private:
- int syntaxError(SocketClient* cli, const char* message);
- int operationError(SocketClient* cli, const char* message, int ret);
- int success(SocketClient* cli);
- };
-};
-
-} // namespace net
-} // namespace android
-
-#endif
diff --git a/server/CommandListener.cpp b/server/NdcDispatcher.cpp
similarity index 80%
rename from server/CommandListener.cpp
rename to server/NdcDispatcher.cpp
index dbda674..51cc384 100644
--- a/server/CommandListener.cpp
+++ b/server/NdcDispatcher.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,43 +14,38 @@
* limitations under the License.
*/
-// #define LOG_NDEBUG 0
+#include "NdcDispatcher.h"
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <errno.h>
-#include <string.h>
#include <linux/if.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
-#define __STDC_FORMAT_MACROS 1
-#include <inttypes.h>
+#include <cinttypes>
+#include <string>
+#include <vector>
-#define LOG_TAG "CommandListener"
-
+#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <log/log.h>
-#include <netd_resolv/params.h>
+#include <android/multinetwork.h>
#include <netdutils/ResponseCode.h>
#include <netdutils/Status.h>
#include <netdutils/StatusOr.h>
#include <netutils/ifc.h>
-#include <sysutils/SocketClient.h>
-#include "CommandListener.h"
-#include "Controllers.h"
#include "NetdConstants.h"
-
+#include "NetworkController.h"
+#include "Permission.h"
#include "UidRanges.h"
#include "netid_client.h"
-#include <string>
-#include <vector>
-
using android::base::Join;
using android::base::StringPrintf;
using android::binder::Status;
@@ -120,15 +115,18 @@
} // namespace
-sp<INetd> CommandListener::mNetd;
+sp<INetd> NdcDispatcher::mNetd;
+sp<IDnsResolver> NdcDispatcher::mDnsResolver;
-CommandListener::CommandListener() : FrameworkListener(SOCKET_NAME, true) {
+NdcDispatcher::NdcDispatcher() {
sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("netd"));
- if (binder != nullptr) {
- CommandListener::mNetd = interface_cast<INetd>(binder);
+ sp<IBinder> binderNetd = sm->getService(String16("netd"));
+ sp<IBinder> binderDnsResolver = sm->getService(String16("dnsresolver"));
+ if ((binderNetd != nullptr) && (binderDnsResolver != nullptr)) {
+ NdcDispatcher::mNetd = interface_cast<INetd>(binderNetd);
+ NdcDispatcher::mDnsResolver = interface_cast<IDnsResolver>(binderDnsResolver);
} else {
- ALOGE("Unable to get INetd service");
+ LOG(LOGLEVEL) << "Unable to get binder service";
exit(1);
}
registerCmd(new InterfaceCmd());
@@ -143,12 +141,30 @@
registerCmd(new StrictCmd());
}
-CommandListener::InterfaceCmd::InterfaceCmd() :
- NetdCommand("interface") {
+void NdcDispatcher::registerCmd(NdcNetdCommand* cmd) {
+ mCommands.push_back(cmd);
}
-int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
+int NdcDispatcher::dispatchCommand(int argc, char** argv) {
+ if (argc >= CMD_ARGS_MAX) {
+ mNdc.sendMsg(500, "Command too long", false);
+ }
+
+ for (const auto* c : mCommands) {
+ if (c->getCommand() == argv[0]) {
+ if (c->runCommand(&mNdc, argc, argv)) {
+ mNdc.sendMsg(500, "Handler error", true);
+ }
+ return 0;
+ }
+ }
+ mNdc.sendMsg(500, "Command not recognized", false);
+ return 0;
+}
+
+NdcDispatcher::InterfaceCmd::InterfaceCmd() : NdcNetdCommand("interface") {}
+
+int NdcDispatcher::InterfaceCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
@@ -203,7 +219,7 @@
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
}
- ALOGD("Setting iface cfg");
+ LOG(LOGLEVEL) << "Setting iface cfg";
struct in_addr addr;
int index = 5;
@@ -232,26 +248,27 @@
/* Process flags */
for (int i = index; i < argc; i++) {
- char *flag = argv[i];
+ char* flag = argv[i];
if (!strcmp(flag, "up")) {
- ALOGD("Trying to bring up %s", argv[2]);
+ LOG(LOGLEVEL) << "Trying to bring up " << argv[2];
interfaceCfg.flags.push_back(toStdString(INetd::IF_STATE_UP()));
Status status = mNetd->interfaceSetCfg(interfaceCfg);
if (!status.isOk()) {
- ALOGE("Error upping interface");
+ LOG(LOGLEVEL) << "Error upping interface";
errno = status.serviceSpecificErrorCode();
cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
ifc_close();
return 0;
}
} else if (!strcmp(flag, "down")) {
- ALOGD("Trying to bring down %s", argv[2]);
+ LOG(LOGLEVEL) << "Trying to bring down " << argv[2];
interfaceCfg.flags.push_back(toStdString(INetd::IF_STATE_DOWN()));
Status status = mNetd->interfaceSetCfg(interfaceCfg);
if (!status.isOk()) {
- ALOGE("Error downing interface");
+ LOG(LOGLEVEL) << "Error downing interface";
errno = status.serviceSpecificErrorCode();
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface",
+ true);
return 0;
}
} else if (!strcmp(flag, "broadcast")) {
@@ -274,7 +291,7 @@
return 0;
} else if (!strcmp(argv[1], "clearaddrs")) {
// arglist: iface
- ALOGD("Clearing all IP addresses on %s", argv[2]);
+ LOG(LOGLEVEL) << "Clearing all IP addresses on " << argv[2];
mNetd->interfaceClearAddrs(std::string(argv[2]));
@@ -283,8 +300,8 @@
} else if (!strcmp(argv[1], "ipv6privacyextensions")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
- false);
+ "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
+ false);
return 0;
}
int enable = !strncmp(argv[3], "enable", 7);
@@ -293,15 +310,14 @@
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
} else {
errno = status.serviceSpecificErrorCode();
- cli->sendMsg(ResponseCode::OperationFailed,
- "Failed to set ipv6 privacy extensions", true);
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to set ipv6 privacy extensions",
+ true);
}
return 0;
} else if (!strcmp(argv[1], "ipv6")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface ipv6 <interface> <enable|disable>",
- false);
+ "Usage: interface ipv6 <interface> <enable|disable>", false);
return 0;
}
@@ -311,14 +327,13 @@
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
} else {
errno = status.serviceSpecificErrorCode();
- cli->sendMsg(ResponseCode::OperationFailed,
- "Failed to change IPv6 state", true);
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to change IPv6 state", true);
}
return 0;
} else if (!strcmp(argv[1], "setmtu")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: interface setmtu <interface> <val>", false);
+ "Usage: interface setmtu <interface> <val>", false);
return 0;
}
@@ -329,8 +344,7 @@
cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
} else {
errno = status.serviceSpecificErrorCode();
- cli->sendMsg(ResponseCode::OperationFailed,
- "Failed to set MTU", true);
+ cli->sendMsg(ResponseCode::OperationFailed, "Failed to set MTU", true);
}
return 0;
} else {
@@ -341,11 +355,9 @@
return 0;
}
-CommandListener::IpFwdCmd::IpFwdCmd() :
- NetdCommand("ipfwd") {
-}
+NdcDispatcher::IpFwdCmd::IpFwdCmd() : NdcNetdCommand("ipfwd") {}
-int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
+int NdcDispatcher::IpFwdCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
bool matched = false;
Status status;
@@ -397,12 +409,9 @@
return 0;
}
-CommandListener::TetherCmd::TetherCmd() :
- NetdCommand("tether") {
-}
+NdcDispatcher::TetherCmd::TetherCmd() : NdcNetdCommand("tether") {}
-int CommandListener::TetherCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
+int NdcDispatcher::TetherCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
Status status;
if (argc < 2) {
@@ -426,18 +435,6 @@
for (const auto& ifname : ifList) {
cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
}
- } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
- // It is not supported in binder currently since NMS doesn't need DnsNetId.
- // TODO: Fix it after migrate to ndc.
- char netIdStr[UINT32_STRLEN];
- snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
- cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
-
- std::vector<std::string> dnsList;
- mNetd->tetherDnsList(&dnsList);
- for (const auto& fwdr : dnsList) {
- cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
- }
}
} else if (!strcmp(argv[1], "start")) {
if (argc % 2 == 1) {
@@ -506,12 +503,9 @@
return 0;
}
-CommandListener::NatCmd::NatCmd() :
- NetdCommand("nat") {
-}
+NdcDispatcher::NatCmd::NatCmd() : NdcNetdCommand("nat") {}
-int CommandListener::NatCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
+int NdcDispatcher::NatCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
Status status;
if (argc < 5) {
@@ -541,18 +535,17 @@
return 0;
}
-CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
- NetdCommand("bandwidth") {
-}
+NdcDispatcher::BandwidthControlCmd::BandwidthControlCmd() : NdcNetdCommand("bandwidth") {}
-void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
- char *msg;
+void NdcDispatcher::BandwidthControlCmd::sendGenericSyntaxError(NdcClient* cli,
+ const char* usageMsg) const {
+ char* msg;
asprintf(&msg, "Usage: bandwidth %s", usageMsg);
cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
free(msg);
}
-void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
+void NdcDispatcher::BandwidthControlCmd::sendGenericOkFail(NdcClient* cli, int cond) const {
if (!cond) {
cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
} else {
@@ -560,17 +553,18 @@
}
}
-void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
+void NdcDispatcher::BandwidthControlCmd::sendGenericOpFailed(NdcClient* cli,
+ const char* errMsg) const {
cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
}
-int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
+int NdcDispatcher::BandwidthControlCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
if (argc < 2) {
sendGenericSyntaxError(cli, "<cmds> <args...>");
return 0;
}
- ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
+ LOG(LOGLEVEL) << StringPrintf("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]).c_str();
if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
if (argc != 3) {
@@ -580,7 +574,6 @@
int rc = !mNetd->bandwidthRemoveInterfaceQuota(argv[2]).isOk();
sendGenericOkFail(cli, rc);
return 0;
-
}
if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
if (argc != 4) {
@@ -592,7 +585,6 @@
int rc = !mNetd->bandwidthSetInterfaceQuota(argv[2], bytes).isOk();
sendGenericOkFail(cli, rc);
return 0;
-
}
if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
if (argc < 3) {
@@ -675,7 +667,6 @@
int rc = !mNetd->bandwidthSetInterfaceAlert(argv[2], bytes).isOk();
sendGenericOkFail(cli, rc);
return 0;
-
}
if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
if (argc != 3) {
@@ -685,25 +676,23 @@
int rc = !mNetd->bandwidthRemoveInterfaceAlert(argv[2]).isOk();
sendGenericOkFail(cli, rc);
return 0;
-
}
cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
return 0;
}
-CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
- NetdCommand("idletimer") {
-}
+NdcDispatcher::IdletimerControlCmd::IdletimerControlCmd() : NdcNetdCommand("idletimer") {}
-int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
- // TODO(ashish): Change the error statements
+int NdcDispatcher::IdletimerControlCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
+ // TODO(ashish): Change the error statements
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
return 0;
}
- ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
+ LOG(LOGLEVEL)
+ << StringPrintf("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]).c_str();
if (!strcmp(argv[1], "add")) {
if (argc != 5) {
@@ -717,7 +706,7 @@
if (!status.isOk()) {
cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
} else {
- cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
+ cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
}
return 0;
}
@@ -732,7 +721,7 @@
if (!status.isOk()) {
cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
} else {
- cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
+ cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
}
return 0;
}
@@ -741,11 +730,9 @@
return 0;
}
-CommandListener::FirewallCmd::FirewallCmd() :
- NetdCommand("firewall") {
-}
+NdcDispatcher::FirewallCmd::FirewallCmd() : NdcNetdCommand("firewall") {}
-int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
+int NdcDispatcher::FirewallCmd::sendGenericOkFail(NdcClient* cli, int cond) const {
if (!cond) {
cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
} else {
@@ -754,29 +741,29 @@
return 0;
}
-int CommandListener::FirewallCmd::parseRule(const char* arg) {
+int NdcDispatcher::FirewallCmd::parseRule(const char* arg) {
if (!strcmp(arg, "allow")) {
return INetd::FIREWALL_RULE_ALLOW;
} else if (!strcmp(arg, "deny")) {
return INetd::FIREWALL_RULE_DENY;
} else {
- ALOGE("failed to parse uid rule (%s)", arg);
+ LOG(LOGLEVEL) << "failed to parse uid rule " << arg;
return INetd::FIREWALL_RULE_ALLOW;
}
}
-int CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
+int NdcDispatcher::FirewallCmd::parseFirewallType(const char* arg) {
if (!strcmp(arg, "whitelist")) {
return INetd::FIREWALL_WHITELIST;
} else if (!strcmp(arg, "blacklist")) {
return INetd::FIREWALL_BLACKLIST;
} else {
- ALOGE("failed to parse firewall type (%s)", arg);
+ LOG(LOGLEVEL) << "failed to parse firewall type " << arg;
return INetd::FIREWALL_BLACKLIST;
}
}
-int CommandListener::FirewallCmd::parseChildChain(const char* arg) {
+int NdcDispatcher::FirewallCmd::parseChildChain(const char* arg) {
if (!strcmp(arg, "dozable")) {
return INetd::FIREWALL_CHAIN_DOZABLE;
} else if (!strcmp(arg, "standby")) {
@@ -786,13 +773,12 @@
} else if (!strcmp(arg, "none")) {
return INetd::FIREWALL_CHAIN_NONE;
} else {
- ALOGE("failed to parse child firewall chain (%s)", arg);
+ LOG(LOGLEVEL) << "failed to parse child firewall chain " << arg;
return -1;
}
}
-int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
- char **argv) {
+int NdcDispatcher::FirewallCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
return 0;
@@ -801,7 +787,7 @@
if (!strcmp(argv[1], "enable")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: firewall enable <whitelist|blacklist>", false);
+ "Usage: firewall enable <whitelist|blacklist>", false);
return 0;
}
int res = !mNetd->firewallSetFirewallType(parseFirewallType(argv[2])).isOk();
@@ -829,8 +815,7 @@
int childChain = parseChildChain(argv[2]);
if (childChain == -1) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Invalid chain name. Valid names are: <dozable|standby|none>",
- false);
+ "Invalid chain name. Valid names are: <dozable|standby|none>", false);
return 0;
}
uid_t uid = 0;
@@ -842,8 +827,7 @@
if (!strcmp(argv[1], "enable_chain")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: firewall enable_chain <dozable|standby>",
- false);
+ "Usage: firewall enable_chain <dozable|standby>", false);
return 0;
}
int res = !mNetd->firewallEnableChildChain(parseChildChain(argv[2]), true).isOk();
@@ -853,8 +837,7 @@
if (!strcmp(argv[1], "disable_chain")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: firewall disable_chain <dozable|standby>",
- false);
+ "Usage: firewall disable_chain <dozable|standby>", false);
return 0;
}
int res = !mNetd->firewallEnableChildChain(parseChildChain(argv[2]), false).isOk();
@@ -865,10 +848,9 @@
return 0;
}
-CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
-}
+NdcDispatcher::ClatdCmd::ClatdCmd() : NdcNetdCommand("clatd") {}
-int CommandListener::ClatdCmd::runCommand(SocketClient* cli, int argc, char** argv) {
+int NdcDispatcher::ClatdCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
int rc = 0;
if (argc < 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
@@ -900,11 +882,9 @@
return 0;
}
-CommandListener::StrictCmd::StrictCmd() :
- NetdCommand("strict") {
-}
+NdcDispatcher::StrictCmd::StrictCmd() : NdcNetdCommand("strict") {}
-int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
+int NdcDispatcher::StrictCmd::sendGenericOkFail(NdcClient* cli, int cond) const {
if (!cond) {
cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
} else {
@@ -913,7 +893,7 @@
return 0;
}
-int CommandListener::StrictCmd::parsePenalty(const char* arg) {
+int NdcDispatcher::StrictCmd::parsePenalty(const char* arg) {
if (!strcmp(arg, "reject")) {
return INetd::PENALTY_POLICY_REJECT;
} else if (!strcmp(arg, "log")) {
@@ -925,8 +905,7 @@
}
}
-int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
- char **argv) {
+int NdcDispatcher::StrictCmd::runCommand(NdcClient* cli, int argc, char** argv) const {
if (argc < 2) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
return 0;
@@ -935,8 +914,7 @@
if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
- "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
- false);
+ "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>", false);
return 0;
}
@@ -962,29 +940,28 @@
return 0;
}
-CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
-}
+NdcDispatcher::NetworkCommand::NetworkCommand() : NdcNetdCommand("network") {}
-int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
- client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
+int NdcDispatcher::NetworkCommand::syntaxError(NdcClient* cli, const char* message) const {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, message, false);
return 0;
}
-int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
- int ret) {
+int NdcDispatcher::NetworkCommand::operationError(NdcClient* cli, const char* message,
+ int ret) const {
errno = ret;
- client->sendMsg(ResponseCode::OperationFailed, message, true);
+ cli->sendMsg(ResponseCode::OperationFailed, message, true);
return 0;
}
-int CommandListener::NetworkCommand::success(SocketClient* client) {
- client->sendMsg(ResponseCode::CommandOkay, "success", false);
+int NdcDispatcher::NetworkCommand::success(NdcClient* cli) const {
+ cli->sendMsg(ResponseCode::CommandOkay, "success", false);
return 0;
}
-int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
+int NdcDispatcher::NetworkCommand::runCommand(NdcClient* cli, int argc, char** argv) const {
if (argc < 2) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
// 0 1 2 3 4 5 6 7 8
@@ -994,7 +971,7 @@
// nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
if (!strcmp(argv[1], "route")) {
if (argc < 6 || argc > 9) {
- return syntaxError(client, "Incorrect number of arguments");
+ return syntaxError(cli, "Incorrect number of arguments");
}
int nextArg = 2;
@@ -1003,19 +980,19 @@
if (!strcmp(argv[nextArg], "legacy")) {
++nextArg;
legacy = true;
- PARSE_UINT_RETURN_IF_FAIL(client, argv[nextArg++], uid, "Unknown argument", false);
+ PARSE_UINT_RETURN_IF_FAIL(cli, argv[nextArg++], uid, "Unknown argument", false);
}
bool add = false;
if (!strcmp(argv[nextArg], "add")) {
add = true;
} else if (strcmp(argv[nextArg], "remove")) {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
++nextArg;
if (argc < nextArg + 3 || argc > nextArg + 4) {
- return syntaxError(client, "Incorrect number of arguments");
+ return syntaxError(cli, "Incorrect number of arguments");
}
unsigned netId = stringToNetId(argv[nextArg++]);
@@ -1035,11 +1012,11 @@
}
if (!status.isOk()) {
- return operationError(client, add ? "addRoute() failed" : "removeRoute() failed",
+ return operationError(cli, add ? "addRoute() failed" : "removeRoute() failed",
status.serviceSpecificErrorCode());
}
- return success(client);
+ return success(cli);
}
// 0 1 2 3 4
@@ -1047,23 +1024,23 @@
// network interface remove <netId> <interface>
if (!strcmp(argv[1], "interface")) {
if (argc != 5) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
unsigned netId = stringToNetId(argv[3]);
if (!strcmp(argv[2], "add")) {
if (Status status = mNetd->networkAddInterface(netId, argv[4]); !status.isOk()) {
- return operationError(client, "addInterfaceToNetwork() failed",
+ return operationError(cli, "addInterfaceToNetwork() failed",
status.serviceSpecificErrorCode());
}
} else if (!strcmp(argv[2], "remove")) {
if (Status status = mNetd->networkRemoveInterface(netId, argv[4]); !status.isOk()) {
- return operationError(client, "removeInterfaceFromNetwork() failed",
+ return operationError(cli, "removeInterfaceFromNetwork() failed",
status.serviceSpecificErrorCode());
}
} else {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
- return success(client);
+ return success(cli);
}
// 0 1 2 3
@@ -1073,47 +1050,47 @@
// network create <netId> vpn <secure>
if (!strcmp(argv[1], "create")) {
if (argc < 3) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
unsigned netId = stringToNetId(argv[2]);
if (argc == 6 && !strcmp(argv[3], "vpn")) {
bool secure = strtol(argv[4], nullptr, 2);
if (Status status = mNetd->networkCreateVpn(netId, secure); !status.isOk()) {
- return operationError(client, "createVirtualNetwork() failed",
+ return operationError(cli, "createVirtualNetwork() failed",
status.serviceSpecificErrorCode());
}
} else if (argc > 4) {
- return syntaxError(client, "Unknown trailing argument(s)");
+ return syntaxError(cli, "Unknown trailing argument(s)");
} else {
int permission = INetd::PERMISSION_NONE;
if (argc == 4) {
permission = stringToINetdPermission(argv[3]);
if (permission == INetd::PERMISSION_NONE) {
- return syntaxError(client, "Unknown permission");
+ return syntaxError(cli, "Unknown permission");
}
}
if (Status status = mNetd->networkCreatePhysical(netId, permission); !status.isOk()) {
- return operationError(client, "createPhysicalNetwork() failed",
+ return operationError(cli, "createPhysicalNetwork() failed",
status.serviceSpecificErrorCode());
}
}
- return success(client);
+ return success(cli);
}
// 0 1 2
// network destroy <netId>
if (!strcmp(argv[1], "destroy")) {
if (argc != 3) {
- return syntaxError(client, "Incorrect number of arguments");
+ return syntaxError(cli, "Incorrect number of arguments");
}
unsigned netId = stringToNetId(argv[2]);
// Both of these functions manage their own locking internally.
if (Status status = mNetd->networkDestroy(netId); !status.isOk()) {
- return operationError(client, "destroyNetwork() failed",
+ return operationError(cli, "destroyNetwork() failed",
status.serviceSpecificErrorCode());
}
- // TODO: add clearing DNS back after NDC migrating to binder ver.
- return success(client);
+ mDnsResolver->clearResolverConfiguration(netId);
+ return success(cli);
}
// 0 1 2 3
@@ -1121,22 +1098,22 @@
// network default clear
if (!strcmp(argv[1], "default")) {
if (argc < 3) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
unsigned netId = NETID_UNSET;
if (!strcmp(argv[2], "set")) {
if (argc < 4) {
- return syntaxError(client, "Missing netId");
+ return syntaxError(cli, "Missing netId");
}
netId = stringToNetId(argv[3]);
} else if (strcmp(argv[2], "clear")) {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
if (Status status = mNetd->networkSetDefault(netId); status.isOk()) {
- return operationError(client, "setDefaultNetwork() failed",
+ return operationError(cli, "setDefaultNetwork() failed",
status.serviceSpecificErrorCode());
}
- return success(client);
+ return success(cli);
}
// 0 1 2 3 4 5
@@ -1146,27 +1123,27 @@
// network permission network clear <netId> ...
if (!strcmp(argv[1], "permission")) {
if (argc < 5) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
int nextArg = 4;
int permission = INetd::PERMISSION_NONE;
if (!strcmp(argv[3], "set")) {
permission = stringToINetdPermission(argv[4]);
if (permission == INetd::PERMISSION_NONE) {
- return syntaxError(client, "Unknown permission");
+ return syntaxError(cli, "Unknown permission");
}
nextArg = 5;
} else if (strcmp(argv[3], "clear")) {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
if (nextArg == argc) {
- return syntaxError(client, "Missing id");
+ return syntaxError(cli, "Missing id");
}
bool userPermissions = !strcmp(argv[2], "user");
bool networkPermissions = !strcmp(argv[2], "network");
if (!userPermissions && !networkPermissions) {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
std::vector<int32_t> ids;
@@ -1175,7 +1152,7 @@
char* endPtr;
unsigned id = strtoul(argv[nextArg], &endPtr, 0);
if (!*argv[nextArg] || *endPtr) {
- return syntaxError(client, "Invalid id");
+ return syntaxError(cli, "Invalid id");
}
ids.push_back(id);
} else {
@@ -1190,12 +1167,12 @@
for (auto netId : ids) {
Status status = mNetd->networkSetPermissionForNetwork(netId, permission);
if (!status.isOk())
- return operationError(client, "setPermissionForNetworks() failed",
+ return operationError(cli, "setPermissionForNetworks() failed",
status.serviceSpecificErrorCode());
}
}
- return success(client);
+ return success(cli);
}
// 0 1 2 3 4
@@ -1203,29 +1180,29 @@
// network users remove <netId> [<uid>[-<uid>]] ...
if (!strcmp(argv[1], "users")) {
if (argc < 4) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
unsigned netId = stringToNetId(argv[3]);
UidRanges uidRanges;
if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
- return syntaxError(client, "Invalid UIDs");
+ return syntaxError(cli, "Invalid UIDs");
}
if (!strcmp(argv[2], "add")) {
if (Status status = mNetd->networkAddUidRanges(netId, uidRanges.getRanges());
!status.isOk()) {
- return operationError(client, "addUsersToNetwork() failed",
+ return operationError(cli, "addUsersToNetwork() failed",
status.serviceSpecificErrorCode());
}
} else if (!strcmp(argv[2], "remove")) {
if (Status status = mNetd->networkRemoveUidRanges(netId, uidRanges.getRanges());
!status.isOk()) {
- return operationError(client, "removeUsersFromNetwork() failed",
+ return operationError(cli, "removeUsersFromNetwork() failed",
status.serviceSpecificErrorCode());
}
} else {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
- return success(client);
+ return success(cli);
}
// 0 1 2 3
@@ -1233,12 +1210,12 @@
// network protect deny <uid> ...
if (!strcmp(argv[1], "protect")) {
if (argc < 4) {
- return syntaxError(client, "Missing argument");
+ return syntaxError(cli, "Missing argument");
}
std::vector<uid_t> uids;
for (int i = 3; i < argc; ++i) {
uid_t uid = 0;
- PARSE_UINT_RETURN_IF_FAIL(client, argv[i], uid, "Unknown argument", false);
+ PARSE_UINT_RETURN_IF_FAIL(cli, argv[i], uid, "Unknown argument", false);
uids.push_back(uid);
}
if (!strcmp(argv[2], "allow")) {
@@ -1250,12 +1227,12 @@
mNetd->networkSetProtectDeny(uid);
}
} else {
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
- return success(client);
+ return success(cli);
}
- return syntaxError(client, "Unknown argument");
+ return syntaxError(cli, "Unknown argument");
}
} // namespace net
diff --git a/server/NdcDispatcher.h b/server/NdcDispatcher.h
new file mode 100644
index 0000000..5732e22
--- /dev/null
+++ b/server/NdcDispatcher.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NDC_DISPATCHER_H__
+#define _NDC_DISPATCHER_H__
+
+#include <string>
+
+#include <android-base/logging.h>
+#include <android/net/IDnsResolver.h>
+#include <android/net/INetd.h>
+#include "binder/IServiceManager.h"
+
+#include "NetdConstants.h"
+
+namespace android {
+namespace net {
+
+class NdcClient {
+ public:
+ NdcClient() = default;
+ ~NdcClient() = default;
+
+ int sendMsg(int code, const char* msg, bool addErrno) {
+ if (addErrno) {
+ printf("%d 0 %s (%s)\n", code, msg, strerror(errno));
+ } else {
+ printf("%d 0 %s\n", code, msg);
+ }
+ return 0;
+ }
+};
+
+class NdcNetdCommand {
+ public:
+ NdcNetdCommand(std::string cmd) : mCommand(std::move(cmd)) {}
+ virtual ~NdcNetdCommand() {}
+
+ virtual int runCommand(NdcClient* c, int argc, char** argv) const = 0;
+
+ const std::string& getCommand() const { return mCommand; }
+
+ private:
+ std::string mCommand;
+};
+
+class NdcDispatcher {
+ public:
+ // Matches the restrictions previously imposed by CommandListener.cpp.
+ static const int CMD_ARGS_MAX = 26;
+ // Default log level is set to minimum one.
+ static const android::base::LogSeverity LOGLEVEL = android::base::VERBOSE;
+
+ NdcDispatcher();
+ ~NdcDispatcher() = default;
+
+ static sp<INetd> mNetd;
+ static sp<IDnsResolver> mDnsResolver;
+ NdcClient mNdc;
+
+ int dispatchCommand(int argc, char** argv);
+ void registerCmd(NdcNetdCommand* cmd);
+
+ private:
+ std::vector<NdcNetdCommand*> mCommands;
+
+ class InterfaceCmd : public NdcNetdCommand {
+ public:
+ InterfaceCmd();
+ virtual ~InterfaceCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class IpFwdCmd : public NdcNetdCommand {
+ public:
+ IpFwdCmd();
+ virtual ~IpFwdCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class TetherCmd : public NdcNetdCommand {
+ public:
+ TetherCmd();
+ virtual ~TetherCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class NatCmd : public NdcNetdCommand {
+ public:
+ NatCmd();
+ virtual ~NatCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class BandwidthControlCmd : public NdcNetdCommand {
+ public:
+ BandwidthControlCmd();
+ virtual ~BandwidthControlCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+
+ protected:
+ void sendGenericOkFail(NdcClient* cli, int cond) const;
+ void sendGenericOpFailed(NdcClient* cli, const char* errMsg) const;
+ void sendGenericSyntaxError(NdcClient* cli, const char* usageMsg) const;
+ };
+
+ class IdletimerControlCmd : public NdcNetdCommand {
+ public:
+ IdletimerControlCmd();
+ virtual ~IdletimerControlCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class FirewallCmd : public NdcNetdCommand {
+ public:
+ FirewallCmd();
+ virtual ~FirewallCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+
+ protected:
+ int sendGenericOkFail(NdcClient* cli, int cond) const;
+ static int parseRule(const char* arg);
+ static int parseFirewallType(const char* arg);
+ static int parseChildChain(const char* arg);
+ };
+
+ class ClatdCmd : public NdcNetdCommand {
+ public:
+ ClatdCmd();
+ virtual ~ClatdCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+ };
+
+ class StrictCmd : public NdcNetdCommand {
+ public:
+ StrictCmd();
+ virtual ~StrictCmd() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+
+ protected:
+ int sendGenericOkFail(NdcClient* cli, int cond) const;
+ static int parsePenalty(const char* arg);
+ };
+
+ class NetworkCommand : public NdcNetdCommand {
+ public:
+ NetworkCommand();
+ virtual ~NetworkCommand() {}
+ int runCommand(NdcClient* cli, int argc, char** argv) const;
+
+ private:
+ int syntaxError(NdcClient* cli, const char* message) const;
+ int operationError(NdcClient* cli, const char* message, int ret) const;
+ int success(NdcClient* cli) const;
+ };
+};
+
+} // namespace net
+} // namespace android
+
+#endif
diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp
index 9fc2c66..f7cb8dd 100644
--- a/server/NetworkController.cpp
+++ b/server/NetworkController.cpp
@@ -23,16 +23,15 @@
// acquiring the lock. Private functions in this file should call xxxLocked() methods and access
// internal state directly.
-#include "NetworkController.h"
-
#define LOG_TAG "Netd"
-#include "log/log.h"
+
+#include "NetworkController.h"
#include <android-base/strings.h>
#include <cutils/misc.h> // FIRST_APPLICATION_UID
#include <netd_resolv/resolv.h>
#include <netd_resolv/resolv_stub.h>
-#include "android/net/INetd.h"
+#include "log/log.h"
#include "Controllers.h"
#include "DummyNetwork.h"
@@ -59,12 +58,6 @@
} // namespace
-const unsigned NetworkController::MIN_OEM_ID = 1;
-const unsigned NetworkController::MAX_OEM_ID = 50;
-const unsigned NetworkController::DUMMY_NET_ID = 51;
-// NetIds 52..98 are reserved for future use.
-const unsigned NetworkController::LOCAL_NET_ID = INetd::LOCAL_NET_ID;
-
// All calls to methods here are made while holding a write lock on mRWLock.
// They are mostly not called directly from this class, but from methods in PhysicalNetwork.cpp.
// However, we're the only user of that class, so all calls to those methods come from here and are
diff --git a/server/NetworkController.h b/server/NetworkController.h
index d765ae7..0522b6d 100644
--- a/server/NetworkController.h
+++ b/server/NetworkController.h
@@ -17,12 +17,13 @@
#ifndef NETD_SERVER_NETWORK_CONTROLLER_H
#define NETD_SERVER_NETWORK_CONTROLLER_H
-
#include <android-base/thread_annotations.h>
#include <android/multinetwork.h>
+
#include "NetdConstants.h"
#include "Permission.h"
+#include "android/net/INetd.h"
#include "netdutils/DumpWriter.h"
#include <sys/types.h>
@@ -83,10 +84,11 @@
*/
class NetworkController {
public:
- static const unsigned MIN_OEM_ID;
- static const unsigned MAX_OEM_ID;
- static const unsigned LOCAL_NET_ID;
- static const unsigned DUMMY_NET_ID;
+ // NetIds 52..98 are reserved for future use.
+ static const unsigned MIN_OEM_ID = 1;
+ static const unsigned MAX_OEM_ID = 50;
+ static const unsigned LOCAL_NET_ID = INetd::LOCAL_NET_ID;
+ static const unsigned DUMMY_NET_ID = 51;
NetworkController();
diff --git a/server/main.cpp b/server/main.cpp
index 45b968d..b783ce5 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -37,7 +37,6 @@
#include <binder/IServiceManager.h>
#include <netdutils/Stopwatch.h>
-#include "CommandListener.h"
#include "Controllers.h"
#include "FwmarkServer.h"
#include "MDnsSdListener.h"
@@ -54,7 +53,6 @@
using android::IPCThreadState;
using android::status_t;
using android::String16;
-using android::net::CommandListener;
using android::net::FwmarkServer;
using android::net::gCtls;
using android::net::gLog;
@@ -105,10 +103,8 @@
// Before we do anything that could fork, mark CLOEXEC the UNIX sockets that we get from init.
// FrameworkListener does this on initialization as well, but we only initialize these
// components after having initialized other subsystems that can fork.
- for (const auto& sock : { CommandListener::SOCKET_NAME,
- DNSPROXYLISTENER_SOCKET_NAME,
- FwmarkServer::SOCKET_NAME,
- MDnsSdListener::SOCKET_NAME }) {
+ for (const auto& sock :
+ {DNSPROXYLISTENER_SOCKET_NAME, FwmarkServer::SOCKET_NAME, MDnsSdListener::SOCKET_NAME}) {
setCloseOnExec(sock);
}
@@ -130,20 +126,6 @@
gCtls = new android::net::Controllers();
gCtls->init();
- // NetdNativeService must start before CommandListener.
- // TODO: put NetdNativeService starting back after subsystems started
- // after migrating CommandListener to NDC, aosp/929861.
- Stopwatch subTime;
- status_t ret;
- if ((ret = NetdNativeService::start()) != android::OK) {
- ALOGE("Unable to start NetdNativeService: %d", ret);
- exit(1);
- }
- gLog.info("Registering NetdNativeService: %.1fms", subTime.getTimeAndReset());
-
- CommandListener cl;
- nm->setBroadcaster((SocketListener *) &cl);
-
if (nm->start()) {
ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
@@ -187,15 +169,13 @@
exit(1);
}
- /*
- * Now that we're up, we can respond to commands. Starting the listener also tells
- * NetworkManagementService that we are up and that our binder interface is ready.
- */
- if (cl.startListener()) {
- ALOGE("Unable to start CommandListener (%s)", strerror(errno));
+ Stopwatch subTime;
+ status_t ret;
+ if ((ret = NetdNativeService::start()) != android::OK) {
+ ALOGE("Unable to start NetdNativeService: %d", ret);
exit(1);
}
- gLog.info("Starting CommandListener: %.1fms", subTime.getTimeAndReset());
+ gLog.info("Registering NetdNativeService: %.1fms", subTime.getTimeAndReset());
android::net::process::ScopedPidFile pidFile(PID_FILE_PATH);
diff --git a/server/ndc.cpp b/server/ndc.cpp
index ec59637..dbf6458 100644
--- a/server/ndc.cpp
+++ b/server/ndc.cpp
@@ -16,165 +16,23 @@
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/poll.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/un.h>
+#include "NdcDispatcher.h"
-#include <cutils/sockets.h>
-#include <private/android_filesystem_config.h>
+namespace {
-static void usage(char *progname);
-static int do_monitor(int sock, int stop_after_cmd);
-static int do_cmd(int sock, int argc, char **argv);
-
-int main(int argc, char **argv) {
- int sock;
- int cmdOffset = 0;
-
- if (argc < 2)
- usage(argv[0]);
-
- // try interpreting the first arg as the socket name - if it fails go back to netd
-
- if ((sock = socket_local_client(argv[1],
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM)) < 0) {
- if ((sock = socket_local_client("netd",
- ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM)) < 0) {
- fprintf(stderr, "Error connecting (%s)\n", strerror(errno));
- exit(4);
- }
- } else {
- if (argc < 3) usage(argv[0]);
- printf("Using alt socket %s\n", argv[1]);
- cmdOffset = 1;
- }
-
- if (!strcmp(argv[1+cmdOffset], "monitor"))
- exit(do_monitor(sock, 0));
- exit(do_cmd(sock, argc-cmdOffset, &(argv[cmdOffset])));
-}
-
-static int do_cmd(int sock, int argc, char **argv) {
- 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 == nullptr) {
- int res = errno;
- perror("strdup failed");
- return res;
- }
-
- for (i = 1; i < argc; i++) {
- if (strchr(argv[i], '"')) {
- perror("argument with embedded quotes not allowed");
- free(final_cmd);
- return 1;
- }
- bool needs_quoting = strchr(argv[i], ' ');
- const char *format = needs_quoting ? "%s\"%s\"%s" : "%s%s%s";
- char *tmp_final_cmd;
-
- if (asprintf(&tmp_final_cmd, format, final_cmd, argv[i],
- (i == (argc - 1)) ? "" : " ") < 0) {
- int res = errno;
- perror("failed asprintf");
- free(final_cmd);
- return res;
- }
- free(final_cmd);
- final_cmd = tmp_final_cmd;
- }
-
- if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {
- int res = errno;
- perror("write");
- free(final_cmd);
- return res;
- }
- free(final_cmd);
-
- return do_monitor(sock, 1);
-}
-
-static int do_monitor(int sock, int stop_after_cmd) {
- char *buffer = (char *)malloc(4096);
-
- if (!stop_after_cmd)
- printf("[Connected to Netd]\n");
-
- while(1) {
- int rc = 0;
- struct pollfd fds = { .fd = sock, .events = POLLIN };
- const int timeout_msecs = 10 * 1000;
- rc = TEMP_FAILURE_RETRY(poll(&fds, 1, timeout_msecs));
- if (rc < 0) {
- int res = errno;
- fprintf(stderr, "Error in poll(): %s\n", strerror(res));
- free(buffer);
- return res;
- }
- if (rc == 0) {
- continue;
- }
- if (!(fds.revents & (POLLIN | POLLERR))) {
- continue;
- }
-
- 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
- fprintf(stderr, "Error reading data (%s)\n", strerror(res));
- free(buffer);
- if (rc == 0)
- return ECONNRESET;
- return res;
- }
-
- int offset = 0;
- int i = 0;
-
- for (i = 0; i < rc; i++) {
- if (buffer[i] == '\0') {
- char tmp[4];
- strncpy(tmp, buffer + offset, 3);
- tmp[3] = '\0';
- long code = strtol(tmp, nullptr, 10);
-
- printf("%s\n", buffer + offset);
- if (stop_after_cmd) {
- if (code >= 200 && code < 600)
- return 0;
- }
- offset = i + 1;
- }
- }
- }
- free(buffer);
- return 0;
-}
-
-static void usage(char *progname) {
- fprintf(stderr, "Usage: %s [<sockname>] ([monitor] | ([<cmd_seq_num>] <cmd> [arg ...]))\n", progname);
+void usage(char* progname) {
+ fprintf(stderr, "Usage: %s (<cmd> [arg ...])\n", progname);
exit(1);
}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ if (argc < 2) {
+ usage(argv[0]);
+ }
+
+ android::net::NdcDispatcher nd;
+ exit(nd.dispatchCommand(argc - 1, argv + 1));
+}