2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 // #define LOG_NDEBUG 0
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
30 #define LOG_TAG "CommandListener"
32 #include <cutils/log.h>
33 #include <netutils/ifc.h>
34 #include <sysutils/SocketClient.h>
36 #include "CommandListener.h"
37 #include "ResponseCode.h"
38 #include "ThrottleController.h"
39 #include "BandwidthController.h"
40 #include "SecondaryTableController.h"
43 TetherController *CommandListener::sTetherCtrl = NULL;
44 NatController *CommandListener::sNatCtrl = NULL;
45 PppController *CommandListener::sPppCtrl = NULL;
46 PanController *CommandListener::sPanCtrl = NULL;
47 SoftapController *CommandListener::sSoftapCtrl = NULL;
48 BandwidthController * CommandListener::sBandwidthCtrl = NULL;
49 ResolverController *CommandListener::sResolverCtrl = NULL;
50 SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
52 CommandListener::CommandListener() :
53 FrameworkListener("netd") {
54 registerCmd(new InterfaceCmd());
55 registerCmd(new IpFwdCmd());
56 registerCmd(new TetherCmd());
57 registerCmd(new NatCmd());
58 registerCmd(new ListTtysCmd());
59 registerCmd(new PppdCmd());
60 registerCmd(new PanCmd());
61 registerCmd(new SoftapCmd());
62 registerCmd(new BandwidthControlCmd());
63 registerCmd(new ResolverCmd());
65 if (!sSecondaryTableCtrl)
66 sSecondaryTableCtrl = new SecondaryTableController();
68 sTetherCtrl = new TetherController();
70 sNatCtrl = new NatController(sSecondaryTableCtrl);
72 sPppCtrl = new PppController();
74 sPanCtrl = new PanController();
76 sSoftapCtrl = new SoftapController();
78 sBandwidthCtrl = new BandwidthController();
80 sResolverCtrl = new ResolverController();
83 CommandListener::InterfaceCmd::InterfaceCmd() :
84 NetdCommand("interface") {
87 int CommandListener::writeFile(const char *path, const char *value, int size) {
88 int fd = open(path, O_WRONLY);
90 LOGE("Failed to open %s: %s", path, strerror(errno));
94 if (write(fd, value, size) != size) {
95 LOGE("Failed to write %s: %s", path, strerror(errno));
103 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
104 int argc, char **argv) {
106 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
110 if (!strcmp(argv[1], "list")) {
114 if (!(d = opendir("/sys/class/net"))) {
115 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
119 while((de = readdir(d))) {
120 if (de->d_name[0] == '.')
122 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
125 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
127 } else if (!strcmp(argv[1], "readrxcounter")) {
129 cli->sendMsg(ResponseCode::CommandSyntaxError,
130 "Usage: interface readrxcounter <interface>", false);
133 unsigned long rx = 0, tx = 0;
134 if (readInterfaceCounters(argv[2], &rx, &tx)) {
135 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
140 asprintf(&msg, "%lu", rx);
141 cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
145 } else if (!strcmp(argv[1], "readtxcounter")) {
147 cli->sendMsg(ResponseCode::CommandSyntaxError,
148 "Usage: interface readtxcounter <interface>", false);
151 unsigned long rx = 0, tx = 0;
152 if (readInterfaceCounters(argv[2], &rx, &tx)) {
153 cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
158 asprintf(&msg, "%lu", tx);
159 cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
162 } else if (!strcmp(argv[1], "getthrottle")) {
163 if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
164 cli->sendMsg(ResponseCode::CommandSyntaxError,
165 "Usage: interface getthrottle <interface> <rx|tx>", false);
170 int voldRc = ResponseCode::InterfaceRxThrottleResult;
172 if (!strcmp(argv[3], "rx")) {
173 rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
175 rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
176 voldRc = ResponseCode::InterfaceTxThrottleResult;
179 cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
182 asprintf(&msg, "%u", val);
183 cli->sendMsg(voldRc, msg, false);
188 } else if (!strcmp(argv[1], "setthrottle")) {
190 cli->sendMsg(ResponseCode::CommandSyntaxError,
191 "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
194 if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
195 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
197 cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
202 * These commands take a minimum of 3 arguments
205 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
210 // interface route add/remove iface default/secondary dest prefix gateway
211 if (!strcmp(argv[1], "route")) {
212 int prefix_length = 0;
214 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
217 if (sscanf(argv[6], "%d", &prefix_length) != 1) {
218 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
221 if (!strcmp(argv[2], "add")) {
222 if (!strcmp(argv[4], "default")) {
223 if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
224 cli->sendMsg(ResponseCode::OperationFailed,
225 "Failed to add route to default table", true);
227 cli->sendMsg(ResponseCode::CommandOkay,
228 "Route added to default table", false);
230 } else if (!strcmp(argv[4], "secondary")) {
231 return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
232 prefix_length, argv[7]);
234 cli->sendMsg(ResponseCode::CommandParameterError,
235 "Invalid route type, expecting 'default' or 'secondary'", false);
238 } else if (!strcmp(argv[2], "remove")) {
239 if (!strcmp(argv[4], "default")) {
240 if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
241 cli->sendMsg(ResponseCode::OperationFailed,
242 "Failed to remove route from default table", true);
244 cli->sendMsg(ResponseCode::CommandOkay,
245 "Route removed from default table", false);
247 } else if (!strcmp(argv[4], "secondary")) {
248 return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
249 prefix_length, argv[7]);
251 cli->sendMsg(ResponseCode::CommandParameterError,
252 "Invalid route type, expecting 'default' or 'secondary'", false);
256 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
261 if (!strcmp(argv[1], "getcfg")) {
264 unsigned char hwaddr[6];
268 memset(hwaddr, 0, sizeof(hwaddr));
270 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
271 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
276 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
277 LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
280 char *addr_s = strdup(inet_ntoa(addr));
281 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
283 updown = (flags & IFF_UP) ? "up" : "down";
284 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : "";
285 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : "";
286 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : "";
287 running = (flags & IFF_RUNNING) ? " running" : "";
288 multi = (flags & IFF_MULTICAST) ? " multicast" : "";
292 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
295 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
296 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
297 addr_s, prefixLength, flag_s);
299 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
307 } else if (!strcmp(argv[1], "setcfg")) {
308 // arglist: iface addr prefixLength flags
310 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
313 LOGD("Setting iface cfg");
318 if (!inet_aton(argv[3], &addr)) {
319 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
324 if (ifc_set_addr(argv[2], addr.s_addr)) {
325 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
330 //Set prefix length on a non zero address
331 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
332 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
338 for (int i = 5; i < argc; i++) {
339 char *flag = argv[i];
340 if (!strcmp(flag, "up")) {
341 LOGD("Trying to bring up %s", argv[2]);
342 if (ifc_up(argv[2])) {
343 LOGE("Error upping interface");
344 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
348 } else if (!strcmp(flag, "down")) {
349 LOGD("Trying to bring down %s", argv[2]);
350 if (ifc_down(argv[2])) {
351 LOGE("Error downing interface");
352 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
356 } else if (!strcmp(flag, "broadcast")) {
358 } else if (!strcmp(flag, "multicast")) {
360 } else if (!strcmp(flag, "running")) {
362 } else if (!strcmp(flag, "loopback")) {
364 } else if (!strcmp(flag, "point-to-point")) {
367 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
373 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
376 } else if (!strcmp(argv[1], "clearaddrs")) {
378 LOGD("Clearing all IP addresses on %s", argv[2]);
380 ifc_clear_addresses(argv[2]);
382 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
384 } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
386 cli->sendMsg(ResponseCode::CommandSyntaxError,
387 "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
393 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]);
395 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) {
397 cli->sendMsg(ResponseCode::OperationFailed,
398 "Failed to set ipv6 privacy extensions", true);
403 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
405 } else if (!strcmp(argv[1], "ipv6")) {
407 cli->sendMsg(ResponseCode::CommandSyntaxError,
408 "Usage: interface ipv6 <interface> <enable|disable>",
414 asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]);
416 if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) {
418 cli->sendMsg(ResponseCode::OperationFailed,
419 "Failed to change IPv6 state", true);
424 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
427 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
435 CommandListener::ListTtysCmd::ListTtysCmd() :
436 NetdCommand("list_ttys") {
439 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
440 int argc, char **argv) {
441 TtyCollection *tlist = sPppCtrl->getTtyList();
442 TtyCollection::iterator it;
444 for (it = tlist->begin(); it != tlist->end(); ++it) {
445 cli->sendMsg(ResponseCode::TtyListResult, *it, false);
448 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
452 CommandListener::IpFwdCmd::IpFwdCmd() :
453 NetdCommand("ipfwd") {
456 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
457 int argc, char **argv) {
461 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
465 if (!strcmp(argv[1], "status")) {
468 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
469 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
472 } else if (!strcmp(argv[1], "enable")) {
473 rc = sTetherCtrl->setIpFwdEnabled(true);
474 } else if (!strcmp(argv[1], "disable")) {
475 rc = sTetherCtrl->setIpFwdEnabled(false);
477 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
482 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
484 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
490 CommandListener::TetherCmd::TetherCmd() :
491 NetdCommand("tether") {
494 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
495 int argc, char **argv) {
499 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
503 if (!strcmp(argv[1], "stop")) {
504 rc = sTetherCtrl->stopTethering();
505 } else if (!strcmp(argv[1], "status")) {
508 asprintf(&tmp, "Tethering services %s",
509 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
510 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
515 * These commands take a minimum of 4 arguments
518 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
522 if (!strcmp(argv[1], "start")) {
524 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
528 int num_addrs = argc - 2;
531 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
532 while (array_index < num_addrs) {
533 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
534 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
539 rc = sTetherCtrl->startTethering(num_addrs, addrs);
541 } else if (!strcmp(argv[1], "interface")) {
542 if (!strcmp(argv[2], "add")) {
543 rc = sTetherCtrl->tetherInterface(argv[3]);
544 } else if (!strcmp(argv[2], "remove")) {
545 rc = sTetherCtrl->untetherInterface(argv[3]);
546 } else if (!strcmp(argv[2], "list")) {
547 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
548 InterfaceCollection::iterator it;
550 for (it = ilist->begin(); it != ilist->end(); ++it) {
551 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
554 cli->sendMsg(ResponseCode::CommandParameterError,
555 "Unknown tether interface operation", false);
558 } else if (!strcmp(argv[1], "dns")) {
559 if (!strcmp(argv[2], "set")) {
560 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
561 } else if (!strcmp(argv[2], "list")) {
562 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
563 NetAddressCollection::iterator it;
565 for (it = dlist->begin(); it != dlist->end(); ++it) {
566 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
569 cli->sendMsg(ResponseCode::CommandParameterError,
570 "Unknown tether interface operation", false);
574 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
580 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
582 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
588 CommandListener::NatCmd::NatCmd() :
592 int CommandListener::NatCmd::runCommand(SocketClient *cli,
593 int argc, char **argv) {
597 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
601 if (!strcmp(argv[1], "enable")) {
602 rc = sNatCtrl->enableNat(argc, argv);
604 /* Ignore ifaces for now. */
605 rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
607 } else if (!strcmp(argv[1], "disable")) {
608 /* Ignore ifaces for now. */
609 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
610 rc |= sNatCtrl->disableNat(argc, argv);
612 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
617 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
619 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
625 CommandListener::PppdCmd::PppdCmd() :
626 NetdCommand("pppd") {
629 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
630 int argc, char **argv) {
634 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
638 if (!strcmp(argv[1], "attach")) {
639 struct in_addr l, r, dns1, dns2;
641 memset(&dns1, sizeof(struct in_addr), 0);
642 memset(&dns2, sizeof(struct in_addr), 0);
644 if (!inet_aton(argv[3], &l)) {
645 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
648 if (!inet_aton(argv[4], &r)) {
649 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
652 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
653 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
656 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
657 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
660 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
661 } else if (!strcmp(argv[1], "detach")) {
662 rc = sPppCtrl->detachPppd(argv[2]);
664 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
669 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
671 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
677 CommandListener::PanCmd::PanCmd() :
681 int CommandListener::PanCmd::runCommand(SocketClient *cli,
682 int argc, char **argv) {
686 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
690 if (!strcmp(argv[1], "start")) {
691 rc = sPanCtrl->startPan();
692 } else if (!strcmp(argv[1], "stop")) {
693 rc = sPanCtrl->stopPan();
694 } else if (!strcmp(argv[1], "status")) {
697 asprintf(&tmp, "Pan services %s",
698 (sPanCtrl->isPanStarted() ? "started" : "stopped"));
699 cli->sendMsg(ResponseCode::PanStatusResult, tmp, false);
703 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false);
708 cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false);
710 cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true);
716 CommandListener::SoftapCmd::SoftapCmd() :
717 NetdCommand("softap") {
720 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
721 int argc, char **argv) {
722 int rc = 0, flag = 0;
726 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
730 if (!strcmp(argv[1], "start")) {
731 rc = sSoftapCtrl->startDriver(argv[2]);
732 } else if (!strcmp(argv[1], "stop")) {
733 rc = sSoftapCtrl->stopDriver(argv[2]);
734 } else if (!strcmp(argv[1], "startap")) {
735 rc = sSoftapCtrl->startSoftap();
736 } else if (!strcmp(argv[1], "stopap")) {
737 rc = sSoftapCtrl->stopSoftap();
738 } else if (!strcmp(argv[1], "fwreload")) {
739 rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
740 } else if (!strcmp(argv[1], "clients")) {
741 rc = sSoftapCtrl->clientsSoftap(&retbuf);
743 cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
747 } else if (!strcmp(argv[1], "status")) {
748 asprintf(&retbuf, "Softap service %s",
749 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
750 cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
753 } else if (!strcmp(argv[1], "set")) {
754 rc = sSoftapCtrl->setSoftap(argc, argv);
756 cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
761 cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
763 cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
769 CommandListener::ResolverCmd::ResolverCmd() :
770 NetdCommand("resolver") {
773 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
778 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
782 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
784 rc = sResolverCtrl->setDefaultInterface(argv[2]);
786 cli->sendMsg(ResponseCode::CommandSyntaxError,
787 "Wrong number of arguments to resolver setdefaultif", false);
790 } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
792 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
794 cli->sendMsg(ResponseCode::CommandSyntaxError,
795 "Wrong number of arguments to resolver setifdns", false);
799 // set the address of the interface to which the name servers
800 // are bound. Required in order to bind to right interface when
801 // doing the dns query.
804 ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
806 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
808 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
810 rc = sResolverCtrl->flushDefaultDnsCache();
812 cli->sendMsg(ResponseCode::CommandSyntaxError,
813 "Wrong number of arguments to resolver flushdefaultif", false);
816 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
818 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
820 cli->sendMsg(ResponseCode::CommandSyntaxError,
821 "Wrong number of arguments to resolver setdefaultif", false);
825 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
830 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
832 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
838 int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
839 FILE *fp = fopen("/proc/net/dev", "r");
841 LOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
847 fgets(buffer, sizeof(buffer), fp); // Header 1
848 fgets(buffer, sizeof(buffer), fp); // Header 2
849 while(fgets(buffer, sizeof(buffer), fp)) {
850 buffer[strlen(buffer)-1] = '\0';
854 sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
855 name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
856 char *rxString = strchr(name, ':');
859 // when the rx count gets too big it changes from "name: 999" to "name:1000"
860 // and the sscanf munge the two together. Detect that and fix
861 // note that all the %lu will be off by one and the real tx value will be in d
862 if (*rxString != '\0') {
864 sscanf(rxString, "%20lu", rx);
866 if (strcmp(name, iface)) {
879 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
880 NetdCommand("bandwidth") {
883 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
885 asprintf(&msg, "Usage: bandwidth %s", usageMsg);
886 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
890 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
892 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
894 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
898 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
899 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
902 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
904 sendGenericSyntaxError(cli, "<cmds> <args...>");
908 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
910 if (!strcmp(argv[1], "enable")) {
911 int rc = sBandwidthCtrl->enableBandwidthControl();
912 sendGenericOkFail(cli, rc);
916 if (!strcmp(argv[1], "disable")) {
917 int rc = sBandwidthCtrl->disableBandwidthControl();
918 sendGenericOkFail(cli, rc);
922 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
924 sendGenericSyntaxError(cli, "removequota <interface>");
927 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
928 sendGenericOkFail(cli, rc);
932 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
935 sendGenericSyntaxError(cli, "getquota");
938 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
940 sendGenericOpFailed(cli, "Failed to get quota");
945 asprintf(&msg, "%lld", bytes);
946 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
951 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
954 sendGenericSyntaxError(cli, "getiquota <iface>");
958 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
960 sendGenericOpFailed(cli, "Failed to get quota");
964 asprintf(&msg, "%lld", bytes);
965 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
970 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
972 sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
975 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
976 sendGenericOkFail(cli, rc);
979 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
982 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
986 for (int q = 3; argc >= 4; q++, argc--) {
987 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
990 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
991 cli->sendMsg(ResponseCode::OperationFailed,
997 sendGenericOkFail(cli, rc);
1001 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
1004 sendGenericSyntaxError(cli, "removequotas <interface> ...");
1008 for (int q = 2; argc >= 3; q++, argc--) {
1009 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
1012 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1013 cli->sendMsg(ResponseCode::OperationFailed,
1019 sendGenericOkFail(cli, rc);
1023 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1025 sendGenericSyntaxError(cli, "removeiquota <interface>");
1028 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1029 sendGenericOkFail(cli, rc);
1033 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1035 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1038 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1039 sendGenericOkFail(cli, rc);
1043 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1045 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1048 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1049 sendGenericOkFail(cli, rc);
1054 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1056 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1059 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1060 sendGenericOkFail(cli, rc);
1064 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1066 sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1069 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1070 sendGenericOkFail(cli, rc);
1074 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1076 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1079 /* We ignore the interfaces for now. */
1080 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1081 sendGenericOkFail(cli, rc);
1085 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1087 sendGenericSyntaxError(cli, "removeglobalalert");
1090 int rc = sBandwidthCtrl->removeGlobalAlert();
1091 sendGenericOkFail(cli, rc);
1095 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1097 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1100 /* We ignore the interfaces for now. */
1101 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1102 sendGenericOkFail(cli, rc);
1106 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1108 sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1111 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1112 sendGenericOkFail(cli, rc);
1116 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1118 sendGenericSyntaxError(cli, "removesharedalert");
1121 int rc = sBandwidthCtrl->removeSharedAlert();
1122 sendGenericOkFail(cli, rc);
1126 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1128 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1131 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1132 sendGenericOkFail(cli, rc);
1136 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1138 sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1141 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1142 sendGenericOkFail(cli, rc);
1146 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1147 BandwidthController::TetherStats tetherStats;
1148 std::string extraProcessingInfo = "";
1150 sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
1154 tetherStats.ifaceIn = argv[2];
1155 tetherStats.ifaceOut = argv[3];
1156 int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo);
1158 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1159 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1163 char *msg = tetherStats.getStatsLine();
1164 cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
1170 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);