• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2008 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  // #define LOG_NDEBUG 0
18  
19  #include <stdlib.h>
20  #include <sys/socket.h>
21  #include <sys/types.h>
22  #include <netinet/in.h>
23  #include <arpa/inet.h>
24  #include <dirent.h>
25  #include <errno.h>
26  #include <string.h>
27  #include <fcntl.h>
28  #include <linux/if.h>
29  
30  #define LOG_TAG "CommandListener"
31  
32  #include <cutils/log.h>
33  #include <netutils/ifc.h>
34  #include <sysutils/SocketClient.h>
35  
36  #include "CommandListener.h"
37  #include "ResponseCode.h"
38  #include "ThrottleController.h"
39  #include "BandwidthController.h"
40  #include "IdletimerController.h"
41  #include "SecondaryTableController.h"
42  #include "oem_iptables_hook.h"
43  #include "NetdConstants.h"
44  #include "FirewallController.h"
45  
46  TetherController *CommandListener::sTetherCtrl = NULL;
47  NatController *CommandListener::sNatCtrl = NULL;
48  PppController *CommandListener::sPppCtrl = NULL;
49  SoftapController *CommandListener::sSoftapCtrl = NULL;
50  BandwidthController * CommandListener::sBandwidthCtrl = NULL;
51  IdletimerController * CommandListener::sIdletimerCtrl = NULL;
52  InterfaceController *CommandListener::sInterfaceCtrl = NULL;
53  ResolverController *CommandListener::sResolverCtrl = NULL;
54  SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
55  FirewallController *CommandListener::sFirewallCtrl = NULL;
56  
57  /**
58   * List of module chains to be created, along with explicit ordering. ORDERING
59   * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
60   */
61  static const char* FILTER_INPUT[] = {
62          // Bandwidth should always be early in input chain, to make sure we
63          // correctly count incoming traffic against data plan.
64          BandwidthController::LOCAL_INPUT,
65          FirewallController::LOCAL_INPUT,
66          NULL,
67  };
68  
69  static const char* FILTER_FORWARD[] = {
70          OEM_IPTABLES_FILTER_FORWARD,
71          FirewallController::LOCAL_FORWARD,
72          BandwidthController::LOCAL_FORWARD,
73          NatController::LOCAL_FORWARD,
74          NULL,
75  };
76  
77  static const char* FILTER_OUTPUT[] = {
78          OEM_IPTABLES_FILTER_OUTPUT,
79          FirewallController::LOCAL_OUTPUT,
80          BandwidthController::LOCAL_OUTPUT,
81          NULL,
82  };
83  
84  static const char* RAW_PREROUTING[] = {
85          BandwidthController::LOCAL_RAW_PREROUTING,
86          IdletimerController::LOCAL_RAW_PREROUTING,
87          NULL,
88  };
89  
90  static const char* MANGLE_POSTROUTING[] = {
91          BandwidthController::LOCAL_MANGLE_POSTROUTING,
92          IdletimerController::LOCAL_MANGLE_POSTROUTING,
93          NULL,
94  };
95  
96  static const char* NAT_PREROUTING[] = {
97          OEM_IPTABLES_NAT_PREROUTING,
98          NULL,
99  };
100  
101  static const char* NAT_POSTROUTING[] = {
102          NatController::LOCAL_NAT_POSTROUTING,
103          NULL,
104  };
105  
createChildChains(IptablesTarget target,const char * table,const char * parentChain,const char ** childChains)106  static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
107          const char** childChains) {
108      const char** childChain = childChains;
109      do {
110          // Order is important:
111          // -D to delete any pre-existing jump rule (removes references
112          //    that would prevent -X from working)
113          // -F to flush any existing chain
114          // -X to delete any existing chain
115          // -N to create the chain
116          // -A to append the chain to parent
117  
118          execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
119          execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
120          execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
121          execIptables(target, "-t", table, "-N", *childChain, NULL);
122          execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
123      } while (*(++childChain) != NULL);
124  }
125  
CommandListener()126  CommandListener::CommandListener() :
127                   FrameworkListener("netd", true) {
128      registerCmd(new InterfaceCmd());
129      registerCmd(new IpFwdCmd());
130      registerCmd(new TetherCmd());
131      registerCmd(new NatCmd());
132      registerCmd(new ListTtysCmd());
133      registerCmd(new PppdCmd());
134      registerCmd(new SoftapCmd());
135      registerCmd(new BandwidthControlCmd());
136      registerCmd(new IdletimerControlCmd());
137      registerCmd(new ResolverCmd());
138      registerCmd(new FirewallCmd());
139  
140      if (!sSecondaryTableCtrl)
141          sSecondaryTableCtrl = new SecondaryTableController();
142      if (!sTetherCtrl)
143          sTetherCtrl = new TetherController();
144      if (!sNatCtrl)
145          sNatCtrl = new NatController(sSecondaryTableCtrl);
146      if (!sPppCtrl)
147          sPppCtrl = new PppController();
148      if (!sSoftapCtrl)
149          sSoftapCtrl = new SoftapController();
150      if (!sBandwidthCtrl)
151          sBandwidthCtrl = new BandwidthController();
152      if (!sIdletimerCtrl)
153          sIdletimerCtrl = new IdletimerController();
154      if (!sResolverCtrl)
155          sResolverCtrl = new ResolverController();
156      if (!sFirewallCtrl)
157          sFirewallCtrl = new FirewallController();
158      if (!sInterfaceCtrl)
159          sInterfaceCtrl = new InterfaceController();
160  
161      /*
162       * This is the only time we touch top-level chains in iptables; controllers
163       * should only mutate rules inside of their children chains, as created by
164       * the constants above.
165       *
166       * Modules should never ACCEPT packets (except in well-justified cases);
167       * they should instead defer to any remaining modules using RETURN, or
168       * otherwise DROP/REJECT.
169       */
170  
171      // Create chains for children modules
172      createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
173      createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
174      createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
175      createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
176      createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
177      createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
178      createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
179  
180      // Let each module setup their child chains
181      setupOemIptablesHook();
182  
183      /* When enabled, DROPs all packets except those matching rules. */
184      sFirewallCtrl->setupIptablesHooks();
185  
186      /* Does DROPs in FORWARD by default */
187      sNatCtrl->setupIptablesHooks();
188      /*
189       * Does REJECT in INPUT, OUTPUT. Does counting also.
190       * No DROP/REJECT allowed later in netfilter-flow hook order.
191       */
192      sBandwidthCtrl->setupIptablesHooks();
193      /*
194       * Counts in nat: PREROUTING, POSTROUTING.
195       * No DROP/REJECT allowed later in netfilter-flow hook order.
196       */
197      sIdletimerCtrl->setupIptablesHooks();
198  
199      sBandwidthCtrl->enableBandwidthControl(false);
200  }
201  
InterfaceCmd()202  CommandListener::InterfaceCmd::InterfaceCmd() :
203                   NetdCommand("interface") {
204  }
205  
writeFile(const char * path,const char * value,int size)206  int CommandListener::writeFile(const char *path, const char *value, int size) {
207      int fd = open(path, O_WRONLY);
208      if (fd < 0) {
209          ALOGE("Failed to open %s: %s", path, strerror(errno));
210          return -1;
211      }
212  
213      if (write(fd, value, size) != size) {
214          ALOGE("Failed to write %s: %s", path, strerror(errno));
215          close(fd);
216          return -1;
217      }
218      close(fd);
219      return 0;
220  }
221  
runCommand(SocketClient * cli,int argc,char ** argv)222  int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
223                                                        int argc, char **argv) {
224      if (argc < 2) {
225          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
226          return 0;
227      }
228  
229      if (!strcmp(argv[1], "list")) {
230          DIR *d;
231          struct dirent *de;
232  
233          if (!(d = opendir("/sys/class/net"))) {
234              cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
235              return 0;
236          }
237  
238          while((de = readdir(d))) {
239              if (de->d_name[0] == '.')
240                  continue;
241              cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
242          }
243          closedir(d);
244          cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
245          return 0;
246      } else if (!strcmp(argv[1], "readrxcounter")) {
247          if (argc != 3) {
248              cli->sendMsg(ResponseCode::CommandSyntaxError,
249                      "Usage: interface readrxcounter <interface>", false);
250              return 0;
251          }
252          unsigned long rx = 0, tx = 0;
253          if (readInterfaceCounters(argv[2], &rx, &tx)) {
254              cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
255              return 0;
256          }
257  
258          char *msg;
259          asprintf(&msg, "%lu", rx);
260          cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
261          free(msg);
262  
263          return 0;
264      } else if (!strcmp(argv[1], "readtxcounter")) {
265          if (argc != 3) {
266              cli->sendMsg(ResponseCode::CommandSyntaxError,
267                      "Usage: interface readtxcounter <interface>", false);
268              return 0;
269          }
270          unsigned long rx = 0, tx = 0;
271          if (readInterfaceCounters(argv[2], &rx, &tx)) {
272              cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
273              return 0;
274          }
275  
276          char *msg = NULL;
277          asprintf(&msg, "%lu", tx);
278          cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
279          free(msg);
280          return 0;
281      } else if (!strcmp(argv[1], "getthrottle")) {
282          if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
283              cli->sendMsg(ResponseCode::CommandSyntaxError,
284                      "Usage: interface getthrottle <interface> <rx|tx>", false);
285              return 0;
286          }
287          int val = 0;
288          int rc = 0;
289          int voldRc = ResponseCode::InterfaceRxThrottleResult;
290  
291          if (!strcmp(argv[3], "rx")) {
292              rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
293          } else {
294              rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
295              voldRc = ResponseCode::InterfaceTxThrottleResult;
296          }
297          if (rc) {
298              cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
299          } else {
300              char *msg = NULL;
301              asprintf(&msg, "%u", val);
302              cli->sendMsg(voldRc, msg, false);
303              free(msg);
304              return 0;
305          }
306          return 0;
307      } else if (!strcmp(argv[1], "setthrottle")) {
308          if (argc != 5) {
309              cli->sendMsg(ResponseCode::CommandSyntaxError,
310                      "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
311              return 0;
312          }
313          if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
314              cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
315          } else {
316              cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
317          }
318          return 0;
319      } else if (!strcmp(argv[1], "driver")) {
320          int rc;
321          char *rbuf;
322  
323          if (argc < 4) {
324              cli->sendMsg(ResponseCode::CommandSyntaxError,
325                      "Usage: interface driver <interface> <cmd> <args>", false);
326              return 0;
327          }
328          rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf);
329          if (rc) {
330              cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true);
331          } else {
332              cli->sendMsg(ResponseCode::CommandOkay, rbuf, false);
333          }
334          return 0;
335      } else {
336          /*
337           * These commands take a minimum of 3 arguments
338           */
339          if (argc < 3) {
340              cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
341              return 0;
342          }
343  
344          //     0       1       2        3          4           5     6      7
345          // interface route add/remove iface default/secondary dest prefix gateway
346          if (!strcmp(argv[1], "route")) {
347              int prefix_length = 0;
348              if (argc < 8) {
349                  cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
350                  return 0;
351              }
352              if (sscanf(argv[6], "%d", &prefix_length) != 1) {
353                  cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
354                  return 0;
355              }
356              if (!strcmp(argv[2], "add")) {
357                  if (!strcmp(argv[4], "default")) {
358                      if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
359                          cli->sendMsg(ResponseCode::OperationFailed,
360                                  "Failed to add route to default table", true);
361                      } else {
362                          cli->sendMsg(ResponseCode::CommandOkay,
363                                  "Route added to default table", false);
364                      }
365                  } else if (!strcmp(argv[4], "secondary")) {
366                      return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
367                              prefix_length, argv[7]);
368                  } else {
369                      cli->sendMsg(ResponseCode::CommandParameterError,
370                              "Invalid route type, expecting 'default' or 'secondary'", false);
371                      return 0;
372                  }
373              } else if (!strcmp(argv[2], "remove")) {
374                  if (!strcmp(argv[4], "default")) {
375                      if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
376                          cli->sendMsg(ResponseCode::OperationFailed,
377                                  "Failed to remove route from default table", true);
378                      } else {
379                          cli->sendMsg(ResponseCode::CommandOkay,
380                                  "Route removed from default table", false);
381                      }
382                  } else if (!strcmp(argv[4], "secondary")) {
383                      return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
384                              prefix_length, argv[7]);
385                  } else {
386                      cli->sendMsg(ResponseCode::CommandParameterError,
387                              "Invalid route type, expecting 'default' or 'secondary'", false);
388                      return 0;
389                  }
390              } else {
391                  cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
392              }
393              return 0;
394          }
395  
396          if (!strcmp(argv[1], "getcfg")) {
397              struct in_addr addr;
398              int prefixLength;
399              unsigned char hwaddr[6];
400              unsigned flags = 0;
401  
402              ifc_init();
403              memset(hwaddr, 0, sizeof(hwaddr));
404  
405              if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
406                  cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
407                  ifc_close();
408                  return 0;
409              }
410  
411              if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
412                  ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
413              }
414  
415              char *addr_s = strdup(inet_ntoa(addr));
416              const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
417  
418              updown =  (flags & IFF_UP)           ? "up" : "down";
419              brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
420              loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
421              ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
422              running = (flags & IFF_RUNNING)      ? " running" : "";
423              multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
424  
425              char *flag_s;
426  
427              asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
428  
429              char *msg = NULL;
430              asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
431                       hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
432                       addr_s, prefixLength, flag_s);
433  
434              cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
435  
436              free(addr_s);
437              free(flag_s);
438              free(msg);
439  
440              ifc_close();
441              return 0;
442          } else if (!strcmp(argv[1], "setcfg")) {
443              // arglist: iface [addr prefixLength] flags
444              if (argc < 4) {
445                  cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
446                  return 0;
447              }
448              ALOGD("Setting iface cfg");
449  
450              struct in_addr addr;
451              unsigned flags = 0;
452              int index = 5;
453  
454              ifc_init();
455  
456              if (!inet_aton(argv[3], &addr)) {
457                  // Handle flags only case
458                  index = 3;
459              } else {
460                  if (ifc_set_addr(argv[2], addr.s_addr)) {
461                      cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
462                      ifc_close();
463                      return 0;
464                  }
465  
466                  // Set prefix length on a non zero address
467                  if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
468                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
469                     ifc_close();
470                     return 0;
471                 }
472              }
473  
474              /* Process flags */
475              for (int i = index; i < argc; i++) {
476                  char *flag = argv[i];
477                  if (!strcmp(flag, "up")) {
478                      ALOGD("Trying to bring up %s", argv[2]);
479                      if (ifc_up(argv[2])) {
480                          ALOGE("Error upping interface");
481                          cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
482                          ifc_close();
483                          return 0;
484                      }
485                  } else if (!strcmp(flag, "down")) {
486                      ALOGD("Trying to bring down %s", argv[2]);
487                      if (ifc_down(argv[2])) {
488                          ALOGE("Error downing interface");
489                          cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
490                          ifc_close();
491                          return 0;
492                      }
493                  } else if (!strcmp(flag, "broadcast")) {
494                      // currently ignored
495                  } else if (!strcmp(flag, "multicast")) {
496                      // currently ignored
497                  } else if (!strcmp(flag, "running")) {
498                      // currently ignored
499                  } else if (!strcmp(flag, "loopback")) {
500                      // currently ignored
501                  } else if (!strcmp(flag, "point-to-point")) {
502                      // currently ignored
503                  } else {
504                      cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
505                      ifc_close();
506                      return 0;
507                  }
508              }
509  
510              cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
511              ifc_close();
512              return 0;
513          } else if (!strcmp(argv[1], "clearaddrs")) {
514              // arglist: iface
515              ALOGD("Clearing all IP addresses on %s", argv[2]);
516  
517              ifc_clear_addresses(argv[2]);
518  
519              cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
520              return 0;
521          } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
522              if (argc != 4) {
523                  cli->sendMsg(ResponseCode::CommandSyntaxError,
524                          "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
525                          false);
526                  return 0;
527              }
528  
529              char *tmp;
530              asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]);
531  
532              if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) {
533                  free(tmp);
534                  cli->sendMsg(ResponseCode::OperationFailed,
535                          "Failed to set ipv6 privacy extensions", true);
536                  return 0;
537              }
538  
539              free(tmp);
540              cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
541              return 0;
542          } else if (!strcmp(argv[1], "ipv6")) {
543              if (argc != 4) {
544                  cli->sendMsg(ResponseCode::CommandSyntaxError,
545                          "Usage: interface ipv6 <interface> <enable|disable>",
546                          false);
547                  return 0;
548              }
549  
550              char *tmp;
551              asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]);
552  
553              if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) {
554                  free(tmp);
555                  cli->sendMsg(ResponseCode::OperationFailed,
556                          "Failed to change IPv6 state", true);
557                  return 0;
558              }
559  
560              free(tmp);
561              cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
562              return 0;
563          } else {
564              cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
565              return 0;
566          }
567      }
568      return 0;
569  }
570  
571  
ListTtysCmd()572  CommandListener::ListTtysCmd::ListTtysCmd() :
573                   NetdCommand("list_ttys") {
574  }
575  
runCommand(SocketClient * cli,int argc,char ** argv)576  int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
577                                               int argc, char **argv) {
578      TtyCollection *tlist = sPppCtrl->getTtyList();
579      TtyCollection::iterator it;
580  
581      for (it = tlist->begin(); it != tlist->end(); ++it) {
582          cli->sendMsg(ResponseCode::TtyListResult, *it, false);
583      }
584  
585      cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
586      return 0;
587  }
588  
IpFwdCmd()589  CommandListener::IpFwdCmd::IpFwdCmd() :
590                   NetdCommand("ipfwd") {
591  }
592  
runCommand(SocketClient * cli,int argc,char ** argv)593  int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
594                                                        int argc, char **argv) {
595      int rc = 0;
596  
597      if (argc < 2) {
598          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
599          return 0;
600      }
601  
602      if (!strcmp(argv[1], "status")) {
603          char *tmp = NULL;
604  
605          asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
606          cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
607          free(tmp);
608          return 0;
609      } else if (!strcmp(argv[1], "enable")) {
610          rc = sTetherCtrl->setIpFwdEnabled(true);
611      } else if (!strcmp(argv[1], "disable")) {
612          rc = sTetherCtrl->setIpFwdEnabled(false);
613      } else {
614          cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
615          return 0;
616      }
617  
618      if (!rc) {
619          cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
620      } else {
621          cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
622      }
623  
624      return 0;
625  }
626  
TetherCmd()627  CommandListener::TetherCmd::TetherCmd() :
628                   NetdCommand("tether") {
629  }
630  
runCommand(SocketClient * cli,int argc,char ** argv)631  int CommandListener::TetherCmd::runCommand(SocketClient *cli,
632                                                        int argc, char **argv) {
633      int rc = 0;
634  
635      if (argc < 2) {
636          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
637          return 0;
638      }
639  
640      if (!strcmp(argv[1], "stop")) {
641          rc = sTetherCtrl->stopTethering();
642      } else if(!strcmp(argv[1], "start-reverse")) {
643          ALOGD("CommandListener::TetherCmd::run, call startReverseTethering, iface:%s", argv[2]);
644          sTetherCtrl->startReverseTethering(argv[2]);
645      } else if (!strcmp(argv[1], "stop-reverse")) {
646          ALOGD("CommandListener::TetherCmd::run, call stopReverseTethering");
647          rc = sTetherCtrl->stopReverseTethering();
648      } else if (!strcmp(argv[1], "status")) {
649          char *tmp = NULL;
650  
651          asprintf(&tmp, "Tethering services %s",
652                   (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
653          cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
654          free(tmp);
655          return 0;
656      } else {
657          /*
658           * These commands take a minimum of 4 arguments
659           */
660          if (argc < 4) {
661              cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
662              return 0;
663          }
664  
665          if (!strcmp(argv[1], "start")) {
666              if (argc % 2 == 1) {
667                  cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
668                  return 0;
669              }
670  
671              int num_addrs = argc - 2;
672              int arg_index = 2;
673              int array_index = 0;
674              in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
675              while (array_index < num_addrs) {
676                  if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
677                      cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
678                      free(addrs);
679                      return 0;
680                  }
681              }
682              rc = sTetherCtrl->startTethering(num_addrs, addrs);
683              free(addrs);
684          } else if (!strcmp(argv[1], "interface")) {
685              if (!strcmp(argv[2], "add")) {
686                  rc = sTetherCtrl->tetherInterface(argv[3]);
687              } else if (!strcmp(argv[2], "remove")) {
688                  rc = sTetherCtrl->untetherInterface(argv[3]);
689              } else if (!strcmp(argv[2], "list")) {
690                  InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
691                  InterfaceCollection::iterator it;
692  
693                  for (it = ilist->begin(); it != ilist->end(); ++it) {
694                      cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
695                  }
696              } else {
697                  cli->sendMsg(ResponseCode::CommandParameterError,
698                               "Unknown tether interface operation", false);
699                  return 0;
700              }
701          } else if (!strcmp(argv[1], "dns")) {
702              if (!strcmp(argv[2], "set")) {
703                  rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
704              } else if (!strcmp(argv[2], "list")) {
705                  NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
706                  NetAddressCollection::iterator it;
707  
708                  for (it = dlist->begin(); it != dlist->end(); ++it) {
709                      cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
710                  }
711              } else {
712                  cli->sendMsg(ResponseCode::CommandParameterError,
713                               "Unknown tether interface operation", false);
714                  return 0;
715              }
716          } else {
717              cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
718              return 0;
719          }
720      }
721  
722      if (!rc) {
723          cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
724      } else {
725          cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
726      }
727  
728      return 0;
729  }
730  
NatCmd()731  CommandListener::NatCmd::NatCmd() :
732                   NetdCommand("nat") {
733  }
734  
runCommand(SocketClient * cli,int argc,char ** argv)735  int CommandListener::NatCmd::runCommand(SocketClient *cli,
736                                                        int argc, char **argv) {
737      int rc = 0;
738  
739      if (argc < 5) {
740          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
741          return 0;
742      }
743  
744      if (!strcmp(argv[1], "enable")) {
745          rc = sNatCtrl->enableNat(argc, argv);
746          if(!rc) {
747              /* Ignore ifaces for now. */
748              rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
749          }
750      } else if (!strcmp(argv[1], "disable")) {
751          /* Ignore ifaces for now. */
752          rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
753          rc |= sNatCtrl->disableNat(argc, argv);
754      } else {
755          cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
756          return 0;
757      }
758  
759      if (!rc) {
760          cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
761      } else {
762          cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
763      }
764  
765      return 0;
766  }
767  
PppdCmd()768  CommandListener::PppdCmd::PppdCmd() :
769                   NetdCommand("pppd") {
770  }
771  
runCommand(SocketClient * cli,int argc,char ** argv)772  int CommandListener::PppdCmd::runCommand(SocketClient *cli,
773                                                        int argc, char **argv) {
774      int rc = 0;
775  
776      if (argc < 3) {
777          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
778          return 0;
779      }
780  
781      if (!strcmp(argv[1], "attach")) {
782          struct in_addr l, r, dns1, dns2;
783  
784          memset(&dns1, sizeof(struct in_addr), 0);
785          memset(&dns2, sizeof(struct in_addr), 0);
786  
787          if (!inet_aton(argv[3], &l)) {
788              cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
789              return 0;
790          }
791          if (!inet_aton(argv[4], &r)) {
792              cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
793              return 0;
794          }
795          if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
796              cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
797              return 0;
798          }
799          if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
800              cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
801              return 0;
802          }
803          rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
804      } else if (!strcmp(argv[1], "detach")) {
805          rc = sPppCtrl->detachPppd(argv[2]);
806      } else {
807          cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
808          return 0;
809      }
810  
811      if (!rc) {
812          cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
813      } else {
814          cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
815      }
816  
817      return 0;
818  }
819  
SoftapCmd()820  CommandListener::SoftapCmd::SoftapCmd() :
821                   NetdCommand("softap") {
822  }
823  
runCommand(SocketClient * cli,int argc,char ** argv)824  int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
825                                          int argc, char **argv) {
826      int rc = 0, flag = 0;
827      char *retbuf = NULL;
828  
829      if (argc < 2) {
830          cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
831          return 0;
832      }
833  
834      if (!strcmp(argv[1], "startap")) {
835          rc = sSoftapCtrl->startSoftap();
836      } else if (!strcmp(argv[1], "stopap")) {
837          rc = sSoftapCtrl->stopSoftap();
838      } else if (!strcmp(argv[1], "fwreload")) {
839          rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
840      } else if (!strcmp(argv[1], "clients")) {
841          rc = sSoftapCtrl->clientsSoftap(&retbuf);
842          if (!rc) {
843              cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
844              free(retbuf);
845              return 0;
846          }
847      } else if (!strcmp(argv[1], "status")) {
848          asprintf(&retbuf, "Softap service %s",
849                   (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
850          cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
851          free(retbuf);
852          return 0;
853      } else if (!strcmp(argv[1], "set")) {
854          rc = sSoftapCtrl->setSoftap(argc, argv);
855      } else {
856          cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
857          return 0;
858      }
859  
860      if (!rc) {
861          cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
862      } else {
863          cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
864      }
865  
866      return 0;
867  }
868  
ResolverCmd()869  CommandListener::ResolverCmd::ResolverCmd() :
870          NetdCommand("resolver") {
871  }
872  
runCommand(SocketClient * cli,int argc,char ** argv)873  int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
874      int rc = 0;
875      struct in_addr addr;
876  
877      if (argc < 2) {
878          cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
879          return 0;
880      }
881  
882      if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
883          if (argc == 3) {
884              rc = sResolverCtrl->setDefaultInterface(argv[2]);
885          } else {
886              cli->sendMsg(ResponseCode::CommandSyntaxError,
887                      "Wrong number of arguments to resolver setdefaultif", false);
888              return 0;
889          }
890      } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
891          if (argc >= 4) {
892              rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
893          } else {
894              cli->sendMsg(ResponseCode::CommandSyntaxError,
895                      "Wrong number of arguments to resolver setifdns", false);
896              return 0;
897          }
898  
899          // set the address of the interface to which the name servers
900          // are bound. Required in order to bind to right interface when
901          // doing the dns query.
902          if (!rc) {
903              ifc_init();
904              ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
905  
906              rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
907          }
908      } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
909          if (argc == 2) {
910              rc = sResolverCtrl->flushDefaultDnsCache();
911          } else {
912              cli->sendMsg(ResponseCode::CommandSyntaxError,
913                      "Wrong number of arguments to resolver flushdefaultif", false);
914              return 0;
915          }
916      } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
917          if (argc == 3) {
918              rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
919          } else {
920              cli->sendMsg(ResponseCode::CommandSyntaxError,
921                      "Wrong number of arguments to resolver setdefaultif", false);
922              return 0;
923          }
924      } else {
925          cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
926          return 0;
927      }
928  
929      if (!rc) {
930          cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
931      } else {
932          cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
933      }
934  
935      return 0;
936  }
937  
readInterfaceCounters(const char * iface,unsigned long * rx,unsigned long * tx)938  int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
939      FILE *fp = fopen("/proc/net/dev", "r");
940      if (!fp) {
941          ALOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
942          return -1;
943      }
944  
945      char buffer[512];
946  
947      fgets(buffer, sizeof(buffer), fp); // Header 1
948      fgets(buffer, sizeof(buffer), fp); // Header 2
949      while(fgets(buffer, sizeof(buffer), fp)) {
950          buffer[strlen(buffer)-1] = '\0';
951  
952          char name[31];
953          unsigned long d;
954          sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
955                  name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
956          char *rxString = strchr(name, ':');
957          *rxString = '\0';
958          rxString++;
959          // when the rx count gets too big it changes from "name: 999" to "name:1000"
960          // and the sscanf munge the two together.  Detect that and fix
961          // note that all the %lu will be off by one and the real tx value will be in d
962          if (*rxString != '\0') {
963              *tx = d;
964              sscanf(rxString, "%20lu", rx);
965          }
966          if (strcmp(name, iface)) {
967              continue;
968          }
969          fclose(fp);
970          return 0;
971      }
972  
973      fclose(fp);
974      *rx = 0;
975      *tx = 0;
976      return 0;
977  }
978  
BandwidthControlCmd()979  CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
980      NetdCommand("bandwidth") {
981  }
982  
sendGenericSyntaxError(SocketClient * cli,const char * usageMsg)983  void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
984      char *msg;
985      asprintf(&msg, "Usage: bandwidth %s", usageMsg);
986      cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
987      free(msg);
988  }
989  
sendGenericOkFail(SocketClient * cli,int cond)990  void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
991      if (!cond) {
992          cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
993      } else {
994          cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
995      }
996  }
997  
sendGenericOpFailed(SocketClient * cli,const char * errMsg)998  void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
999      cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
1000  }
1001  
runCommand(SocketClient * cli,int argc,char ** argv)1002  int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1003      if (argc < 2) {
1004          sendGenericSyntaxError(cli, "<cmds> <args...>");
1005          return 0;
1006      }
1007  
1008      ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1009  
1010      if (!strcmp(argv[1], "enable")) {
1011          int rc = sBandwidthCtrl->enableBandwidthControl(true);
1012          sendGenericOkFail(cli, rc);
1013          return 0;
1014  
1015      }
1016      if (!strcmp(argv[1], "disable")) {
1017          int rc = sBandwidthCtrl->disableBandwidthControl();
1018          sendGenericOkFail(cli, rc);
1019          return 0;
1020  
1021      }
1022      if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
1023          if (argc != 3) {
1024              sendGenericSyntaxError(cli, "removequota <interface>");
1025              return 0;
1026          }
1027          int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
1028          sendGenericOkFail(cli, rc);
1029          return 0;
1030  
1031      }
1032      if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
1033          int64_t bytes;
1034          if (argc != 2) {
1035              sendGenericSyntaxError(cli, "getquota");
1036              return 0;
1037          }
1038          int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
1039          if (rc) {
1040              sendGenericOpFailed(cli, "Failed to get quota");
1041              return 0;
1042          }
1043  
1044          char *msg;
1045          asprintf(&msg, "%lld", bytes);
1046          cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
1047          free(msg);
1048          return 0;
1049  
1050      }
1051      if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
1052          int64_t bytes;
1053          if (argc != 3) {
1054              sendGenericSyntaxError(cli, "getiquota <iface>");
1055              return 0;
1056          }
1057  
1058          int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
1059          if (rc) {
1060              sendGenericOpFailed(cli, "Failed to get quota");
1061              return 0;
1062          }
1063          char *msg;
1064          asprintf(&msg, "%lld", bytes);
1065          cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
1066          free(msg);
1067          return 0;
1068  
1069      }
1070      if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
1071          if (argc != 4) {
1072              sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
1073              return 0;
1074          }
1075          int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
1076          sendGenericOkFail(cli, rc);
1077          return 0;
1078      }
1079      if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
1080          int rc;
1081          if (argc < 4) {
1082              sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
1083              return 0;
1084          }
1085  
1086          for (int q = 3; argc >= 4; q++, argc--) {
1087              rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
1088              if (rc) {
1089                  char *msg;
1090                  asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
1091                  cli->sendMsg(ResponseCode::OperationFailed,
1092                               msg, false);
1093                  free(msg);
1094                  return 0;
1095              }
1096          }
1097          sendGenericOkFail(cli, rc);
1098          return 0;
1099  
1100      }
1101      if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
1102          int rc;
1103          if (argc < 3) {
1104              sendGenericSyntaxError(cli, "removequotas <interface> ...");
1105              return 0;
1106          }
1107  
1108          for (int q = 2; argc >= 3; q++, argc--) {
1109              rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
1110              if (rc) {
1111                  char *msg;
1112                  asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1113                  cli->sendMsg(ResponseCode::OperationFailed,
1114                               msg, false);
1115                  free(msg);
1116                  return 0;
1117              }
1118          }
1119          sendGenericOkFail(cli, rc);
1120          return 0;
1121  
1122      }
1123      if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1124          if (argc != 3) {
1125              sendGenericSyntaxError(cli, "removeiquota <interface>");
1126              return 0;
1127          }
1128          int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1129          sendGenericOkFail(cli, rc);
1130          return 0;
1131  
1132      }
1133      if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1134          if (argc != 4) {
1135              sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1136              return 0;
1137          }
1138          int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1139          sendGenericOkFail(cli, rc);
1140          return 0;
1141  
1142      }
1143      if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1144          if (argc < 3) {
1145              sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1146              return 0;
1147          }
1148          int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1149          sendGenericOkFail(cli, rc);
1150          return 0;
1151  
1152  
1153      }
1154      if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1155          if (argc < 3) {
1156              sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1157              return 0;
1158          }
1159          int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1160          sendGenericOkFail(cli, rc);
1161          return 0;
1162  
1163      }
1164      if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1165          if (argc != 3) {
1166              sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1167              return 0;
1168          }
1169          int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1170          sendGenericOkFail(cli, rc);
1171          return 0;
1172  
1173      }
1174      if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1175          if (argc != 4) {
1176              sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1177              return 0;
1178          }
1179          /* We ignore the interfaces for now. */
1180          int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1181          sendGenericOkFail(cli, rc);
1182          return 0;
1183  
1184      }
1185      if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1186          if (argc != 2) {
1187              sendGenericSyntaxError(cli, "removeglobalalert");
1188              return 0;
1189          }
1190          int rc = sBandwidthCtrl->removeGlobalAlert();
1191          sendGenericOkFail(cli, rc);
1192          return 0;
1193  
1194      }
1195      if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1196          if (argc != 4) {
1197              sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1198              return 0;
1199          }
1200          /* We ignore the interfaces for now. */
1201          int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1202          sendGenericOkFail(cli, rc);
1203          return 0;
1204  
1205      }
1206      if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1207          if (argc != 3) {
1208              sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1209              return 0;
1210          }
1211          int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1212          sendGenericOkFail(cli, rc);
1213          return 0;
1214  
1215      }
1216      if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1217          if (argc != 2) {
1218              sendGenericSyntaxError(cli, "removesharedalert");
1219              return 0;
1220          }
1221          int rc = sBandwidthCtrl->removeSharedAlert();
1222          sendGenericOkFail(cli, rc);
1223          return 0;
1224  
1225      }
1226      if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1227          if (argc != 4) {
1228              sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1229              return 0;
1230          }
1231          int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1232          sendGenericOkFail(cli, rc);
1233          return 0;
1234  
1235      }
1236      if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1237          if (argc != 3) {
1238              sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1239              return 0;
1240          }
1241          int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1242          sendGenericOkFail(cli, rc);
1243          return 0;
1244  
1245      }
1246      if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1247          BandwidthController::TetherStats tetherStats;
1248          std::string extraProcessingInfo = "";
1249          if (argc != 4) {
1250              sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
1251              return 0;
1252          }
1253  
1254          tetherStats.ifaceIn = argv[2];
1255          tetherStats.ifaceOut = argv[3];
1256          int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo);
1257          if (rc) {
1258                  extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1259                  sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1260              return 0;
1261          }
1262  
1263          char *msg = tetherStats.getStatsLine();
1264          cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
1265          free(msg);
1266          return 0;
1267  
1268      }
1269  
1270      cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1271      return 0;
1272  }
1273  
IdletimerControlCmd()1274  CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1275      NetdCommand("idletimer") {
1276  }
1277  
runCommand(SocketClient * cli,int argc,char ** argv)1278  int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1279    // TODO(ashish): Change the error statements
1280      if (argc < 2) {
1281          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1282          return 0;
1283      }
1284  
1285      ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1286  
1287      if (!strcmp(argv[1], "enable")) {
1288        if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1289          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1290        } else {
1291          cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1292        }
1293        return 0;
1294  
1295      }
1296      if (!strcmp(argv[1], "disable")) {
1297        if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1298          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1299        } else {
1300          cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1301        }
1302        return 0;
1303      }
1304      if (!strcmp(argv[1], "add")) {
1305          if (argc != 5) {
1306              cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1307              return 0;
1308          }
1309          if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1310                                          argv[2], atoi(argv[3]), argv[4])) {
1311            cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1312          } else {
1313            cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1314          }
1315          return 0;
1316      }
1317      if (!strcmp(argv[1], "remove")) {
1318          if (argc != 5) {
1319              cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1320              return 0;
1321          }
1322          // ashish: fixme timeout
1323          if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1324                                          argv[2], atoi(argv[3]), argv[4])) {
1325            cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1326          } else {
1327            cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1328          }
1329          return 0;
1330      }
1331  
1332      cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1333      return 0;
1334  }
1335  
FirewallCmd()1336  CommandListener::FirewallCmd::FirewallCmd() :
1337      NetdCommand("firewall") {
1338  }
1339  
sendGenericOkFail(SocketClient * cli,int cond)1340  int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1341      if (!cond) {
1342          cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1343      } else {
1344          cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1345      }
1346      return 0;
1347  }
1348  
parseRule(const char * arg)1349  FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1350      if (!strcmp(arg, "allow")) {
1351          return ALLOW;
1352      } else {
1353          return DENY;
1354      }
1355  }
1356  
runCommand(SocketClient * cli,int argc,char ** argv)1357  int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1358          char **argv) {
1359      if (argc < 2) {
1360          cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1361          return 0;
1362      }
1363  
1364      if (!strcmp(argv[1], "enable")) {
1365          int res = sFirewallCtrl->enableFirewall();
1366          return sendGenericOkFail(cli, res);
1367      }
1368      if (!strcmp(argv[1], "disable")) {
1369          int res = sFirewallCtrl->disableFirewall();
1370          return sendGenericOkFail(cli, res);
1371      }
1372      if (!strcmp(argv[1], "is_enabled")) {
1373          int res = sFirewallCtrl->isFirewallEnabled();
1374          return sendGenericOkFail(cli, res);
1375      }
1376  
1377      if (!strcmp(argv[1], "set_interface_rule")) {
1378          if (argc != 4) {
1379              cli->sendMsg(ResponseCode::CommandSyntaxError,
1380                           "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1381              return 0;
1382          }
1383  
1384          const char* iface = argv[2];
1385          FirewallRule rule = parseRule(argv[3]);
1386  
1387          int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1388          return sendGenericOkFail(cli, res);
1389      }
1390  
1391      if (!strcmp(argv[1], "set_egress_source_rule")) {
1392          if (argc != 4) {
1393              cli->sendMsg(ResponseCode::CommandSyntaxError,
1394                           "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1395                           false);
1396              return 0;
1397          }
1398  
1399          const char* addr = argv[2];
1400          FirewallRule rule = parseRule(argv[3]);
1401  
1402          int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1403          return sendGenericOkFail(cli, res);
1404      }
1405  
1406      if (!strcmp(argv[1], "set_egress_dest_rule")) {
1407          if (argc != 5) {
1408              cli->sendMsg(ResponseCode::CommandSyntaxError,
1409                           "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1410                           false);
1411              return 0;
1412          }
1413  
1414          const char* addr = argv[2];
1415          int port = atoi(argv[3]);
1416          FirewallRule rule = parseRule(argv[4]);
1417  
1418          int res = 0;
1419          res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1420          res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1421          return sendGenericOkFail(cli, res);
1422      }
1423  
1424      if (!strcmp(argv[1], "set_uid_rule")) {
1425          if (argc != 4) {
1426              cli->sendMsg(ResponseCode::CommandSyntaxError,
1427                           "Usage: firewall set_uid_rule <1000> <allow|deny>",
1428                           false);
1429              return 0;
1430          }
1431  
1432          int uid = atoi(argv[2]);
1433          FirewallRule rule = parseRule(argv[3]);
1434  
1435          int res = sFirewallCtrl->setUidRule(uid, rule);
1436          return sendGenericOkFail(cli, res);
1437      }
1438  
1439      cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1440      return 0;
1441  }
1442