• Home
  • History
  • Annotate
  • 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 <linux/if.h>
28 #include <resolv_netid.h>
29 
30 #define __STDC_FORMAT_MACROS 1
31 #include <inttypes.h>
32 
33 #define LOG_TAG "CommandListener"
34 
35 #include <cutils/log.h>
36 #include <netutils/ifc.h>
37 #include <sysutils/SocketClient.h>
38 
39 #include "CommandListener.h"
40 #include "ResponseCode.h"
41 #include "BandwidthController.h"
42 #include "IdletimerController.h"
43 #include "oem_iptables_hook.h"
44 #include "NetdConstants.h"
45 #include "FirewallController.h"
46 #include "RouteController.h"
47 #include "UidRanges.h"
48 
49 #include <string>
50 #include <vector>
51 
52 namespace {
53 
54 const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
55 
stringToPermission(const char * arg)56 Permission stringToPermission(const char* arg) {
57     if (!strcmp(arg, "NETWORK")) {
58         return PERMISSION_NETWORK;
59     }
60     if (!strcmp(arg, "SYSTEM")) {
61         return PERMISSION_SYSTEM;
62     }
63     return PERMISSION_NONE;
64 }
65 
stringToNetId(const char * arg)66 unsigned stringToNetId(const char* arg) {
67     if (!strcmp(arg, "local")) {
68         return NetworkController::LOCAL_NET_ID;
69     }
70     // OEM NetIds are "oem1", "oem2", .., "oem50".
71     if (!strncmp(arg, "oem", 3)) {
72         unsigned n = strtoul(arg + 3, NULL, 0);
73         if (1 <= n && n <= NUM_OEM_IDS) {
74             return NetworkController::MIN_OEM_ID + n;
75         }
76         return NETID_UNSET;
77     }
78     // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
79     return strtoul(arg, NULL, 0);
80 }
81 
82 }  // namespace
83 
84 NetworkController *CommandListener::sNetCtrl = NULL;
85 TetherController *CommandListener::sTetherCtrl = NULL;
86 NatController *CommandListener::sNatCtrl = NULL;
87 PppController *CommandListener::sPppCtrl = NULL;
88 SoftapController *CommandListener::sSoftapCtrl = NULL;
89 BandwidthController * CommandListener::sBandwidthCtrl = NULL;
90 IdletimerController * CommandListener::sIdletimerCtrl = NULL;
91 InterfaceController *CommandListener::sInterfaceCtrl = NULL;
92 ResolverController *CommandListener::sResolverCtrl = NULL;
93 FirewallController *CommandListener::sFirewallCtrl = NULL;
94 ClatdController *CommandListener::sClatdCtrl = NULL;
95 
96 /**
97  * List of module chains to be created, along with explicit ordering. ORDERING
98  * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
99  */
100 static const char* FILTER_INPUT[] = {
101         // Bandwidth should always be early in input chain, to make sure we
102         // correctly count incoming traffic against data plan.
103         BandwidthController::LOCAL_INPUT,
104         FirewallController::LOCAL_INPUT,
105         NULL,
106 };
107 
108 static const char* FILTER_FORWARD[] = {
109         OEM_IPTABLES_FILTER_FORWARD,
110         FirewallController::LOCAL_FORWARD,
111         BandwidthController::LOCAL_FORWARD,
112         NatController::LOCAL_FORWARD,
113         NULL,
114 };
115 
116 static const char* FILTER_OUTPUT[] = {
117         OEM_IPTABLES_FILTER_OUTPUT,
118         FirewallController::LOCAL_OUTPUT,
119         BandwidthController::LOCAL_OUTPUT,
120         NULL,
121 };
122 
123 static const char* RAW_PREROUTING[] = {
124         BandwidthController::LOCAL_RAW_PREROUTING,
125         IdletimerController::LOCAL_RAW_PREROUTING,
126         NULL,
127 };
128 
129 static const char* MANGLE_POSTROUTING[] = {
130         BandwidthController::LOCAL_MANGLE_POSTROUTING,
131         IdletimerController::LOCAL_MANGLE_POSTROUTING,
132         NULL,
133 };
134 
135 static const char* MANGLE_FORWARD[] = {
136         NatController::LOCAL_MANGLE_FORWARD,
137         NULL,
138 };
139 
140 static const char* NAT_PREROUTING[] = {
141         OEM_IPTABLES_NAT_PREROUTING,
142         NULL,
143 };
144 
145 static const char* NAT_POSTROUTING[] = {
146         NatController::LOCAL_NAT_POSTROUTING,
147         NULL,
148 };
149 
createChildChains(IptablesTarget target,const char * table,const char * parentChain,const char ** childChains)150 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
151         const char** childChains) {
152     const char** childChain = childChains;
153     do {
154         // Order is important:
155         // -D to delete any pre-existing jump rule (removes references
156         //    that would prevent -X from working)
157         // -F to flush any existing chain
158         // -X to delete any existing chain
159         // -N to create the chain
160         // -A to append the chain to parent
161 
162         execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
163         execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
164         execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
165         execIptables(target, "-t", table, "-N", *childChain, NULL);
166         execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
167     } while (*(++childChain) != NULL);
168 }
169 
CommandListener()170 CommandListener::CommandListener() :
171                  FrameworkListener("netd", true) {
172     registerCmd(new InterfaceCmd());
173     registerCmd(new IpFwdCmd());
174     registerCmd(new TetherCmd());
175     registerCmd(new NatCmd());
176     registerCmd(new ListTtysCmd());
177     registerCmd(new PppdCmd());
178     registerCmd(new SoftapCmd());
179     registerCmd(new BandwidthControlCmd());
180     registerCmd(new IdletimerControlCmd());
181     registerCmd(new ResolverCmd());
182     registerCmd(new FirewallCmd());
183     registerCmd(new ClatdCmd());
184     registerCmd(new NetworkCommand());
185 
186     if (!sNetCtrl)
187         sNetCtrl = new NetworkController();
188     if (!sTetherCtrl)
189         sTetherCtrl = new TetherController();
190     if (!sNatCtrl)
191         sNatCtrl = new NatController();
192     if (!sPppCtrl)
193         sPppCtrl = new PppController();
194     if (!sSoftapCtrl)
195         sSoftapCtrl = new SoftapController();
196     if (!sBandwidthCtrl)
197         sBandwidthCtrl = new BandwidthController();
198     if (!sIdletimerCtrl)
199         sIdletimerCtrl = new IdletimerController();
200     if (!sResolverCtrl)
201         sResolverCtrl = new ResolverController();
202     if (!sFirewallCtrl)
203         sFirewallCtrl = new FirewallController();
204     if (!sInterfaceCtrl)
205         sInterfaceCtrl = new InterfaceController();
206     if (!sClatdCtrl)
207         sClatdCtrl = new ClatdController(sNetCtrl);
208 
209     /*
210      * This is the only time we touch top-level chains in iptables; controllers
211      * should only mutate rules inside of their children chains, as created by
212      * the constants above.
213      *
214      * Modules should never ACCEPT packets (except in well-justified cases);
215      * they should instead defer to any remaining modules using RETURN, or
216      * otherwise DROP/REJECT.
217      */
218 
219     // Create chains for children modules
220     createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
221     createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
222     createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
223     createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
224     createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
225     createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
226     createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
227     createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
228 
229     // Let each module setup their child chains
230     setupOemIptablesHook();
231 
232     /* When enabled, DROPs all packets except those matching rules. */
233     sFirewallCtrl->setupIptablesHooks();
234 
235     /* Does DROPs in FORWARD by default */
236     sNatCtrl->setupIptablesHooks();
237     /*
238      * Does REJECT in INPUT, OUTPUT. Does counting also.
239      * No DROP/REJECT allowed later in netfilter-flow hook order.
240      */
241     sBandwidthCtrl->setupIptablesHooks();
242     /*
243      * Counts in nat: PREROUTING, POSTROUTING.
244      * No DROP/REJECT allowed later in netfilter-flow hook order.
245      */
246     sIdletimerCtrl->setupIptablesHooks();
247 
248     sBandwidthCtrl->enableBandwidthControl(false);
249 
250     if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
251         ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
252     }
253 }
254 
InterfaceCmd()255 CommandListener::InterfaceCmd::InterfaceCmd() :
256                  NetdCommand("interface") {
257 }
258 
runCommand(SocketClient * cli,int argc,char ** argv)259 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
260                                                       int argc, char **argv) {
261     if (argc < 2) {
262         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
263         return 0;
264     }
265 
266     if (!strcmp(argv[1], "list")) {
267         DIR *d;
268         struct dirent *de;
269 
270         if (!(d = opendir("/sys/class/net"))) {
271             cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
272             return 0;
273         }
274 
275         while((de = readdir(d))) {
276             if (de->d_name[0] == '.')
277                 continue;
278             cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
279         }
280         closedir(d);
281         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
282         return 0;
283     } else {
284         /*
285          * These commands take a minimum of 3 arguments
286          */
287         if (argc < 3) {
288             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
289             return 0;
290         }
291 
292         if (!strcmp(argv[1], "getcfg")) {
293             struct in_addr addr;
294             int prefixLength;
295             unsigned char hwaddr[6];
296             unsigned flags = 0;
297 
298             ifc_init();
299             memset(hwaddr, 0, sizeof(hwaddr));
300 
301             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
302                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
303                 ifc_close();
304                 return 0;
305             }
306 
307             if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
308                 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
309             }
310 
311             char *addr_s = strdup(inet_ntoa(addr));
312             const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
313 
314             updown =  (flags & IFF_UP)           ? "up" : "down";
315             brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
316             loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
317             ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
318             running = (flags & IFF_RUNNING)      ? " running" : "";
319             multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
320 
321             char *flag_s;
322 
323             asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
324 
325             char *msg = NULL;
326             asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
327                      hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
328                      addr_s, prefixLength, flag_s);
329 
330             cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
331 
332             free(addr_s);
333             free(flag_s);
334             free(msg);
335 
336             ifc_close();
337             return 0;
338         } else if (!strcmp(argv[1], "setcfg")) {
339             // arglist: iface [addr prefixLength] flags
340             if (argc < 4) {
341                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
342                 return 0;
343             }
344             ALOGD("Setting iface cfg");
345 
346             struct in_addr addr;
347             int index = 5;
348 
349             ifc_init();
350 
351             if (!inet_aton(argv[3], &addr)) {
352                 // Handle flags only case
353                 index = 3;
354             } else {
355                 if (ifc_set_addr(argv[2], addr.s_addr)) {
356                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
357                     ifc_close();
358                     return 0;
359                 }
360 
361                 // Set prefix length on a non zero address
362                 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
363                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
364                    ifc_close();
365                    return 0;
366                }
367             }
368 
369             /* Process flags */
370             for (int i = index; i < argc; i++) {
371                 char *flag = argv[i];
372                 if (!strcmp(flag, "up")) {
373                     ALOGD("Trying to bring up %s", argv[2]);
374                     if (ifc_up(argv[2])) {
375                         ALOGE("Error upping interface");
376                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
377                         ifc_close();
378                         return 0;
379                     }
380                 } else if (!strcmp(flag, "down")) {
381                     ALOGD("Trying to bring down %s", argv[2]);
382                     if (ifc_down(argv[2])) {
383                         ALOGE("Error downing interface");
384                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
385                         ifc_close();
386                         return 0;
387                     }
388                 } else if (!strcmp(flag, "broadcast")) {
389                     // currently ignored
390                 } else if (!strcmp(flag, "multicast")) {
391                     // currently ignored
392                 } else if (!strcmp(flag, "running")) {
393                     // currently ignored
394                 } else if (!strcmp(flag, "loopback")) {
395                     // currently ignored
396                 } else if (!strcmp(flag, "point-to-point")) {
397                     // currently ignored
398                 } else {
399                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
400                     ifc_close();
401                     return 0;
402                 }
403             }
404 
405             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
406             ifc_close();
407             return 0;
408         } else if (!strcmp(argv[1], "clearaddrs")) {
409             // arglist: iface
410             ALOGD("Clearing all IP addresses on %s", argv[2]);
411 
412             ifc_clear_addresses(argv[2]);
413 
414             cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
415             return 0;
416         } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
417             if (argc != 4) {
418                 cli->sendMsg(ResponseCode::CommandSyntaxError,
419                         "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
420                         false);
421                 return 0;
422             }
423             int enable = !strncmp(argv[3], "enable", 7);
424             if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
425                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
426             } else {
427                 cli->sendMsg(ResponseCode::OperationFailed,
428                         "Failed to set ipv6 privacy extensions", true);
429             }
430             return 0;
431         } else if (!strcmp(argv[1], "ipv6")) {
432             if (argc != 4) {
433                 cli->sendMsg(ResponseCode::CommandSyntaxError,
434                         "Usage: interface ipv6 <interface> <enable|disable>",
435                         false);
436                 return 0;
437             }
438 
439             int enable = !strncmp(argv[3], "enable", 7);
440             if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
441                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
442             } else {
443                 cli->sendMsg(ResponseCode::OperationFailed,
444                         "Failed to change IPv6 state", true);
445             }
446             return 0;
447         } else if (!strcmp(argv[1], "ipv6ndoffload")) {
448             if (argc != 4) {
449                 cli->sendMsg(ResponseCode::CommandSyntaxError,
450                         "Usage: interface ipv6ndoffload <interface> <enable|disable>",
451                         false);
452                 return 0;
453             }
454             int enable = !strncmp(argv[3], "enable", 7);
455             if (sInterfaceCtrl->setIPv6NdOffload(argv[2], enable) == 0) {
456                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
457             } else {
458                 cli->sendMsg(ResponseCode::OperationFailed,
459                         "Failed to change IPv6 ND offload state", true);
460             }
461             return 0;
462         } else if (!strcmp(argv[1], "setmtu")) {
463             if (argc != 4) {
464                 cli->sendMsg(ResponseCode::CommandSyntaxError,
465                         "Usage: interface setmtu <interface> <val>", false);
466                 return 0;
467             }
468             if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
469                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
470             } else {
471                 cli->sendMsg(ResponseCode::OperationFailed,
472                         "Failed to get MTU", true);
473             }
474             return 0;
475         } else {
476             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
477             return 0;
478         }
479     }
480     return 0;
481 }
482 
483 
ListTtysCmd()484 CommandListener::ListTtysCmd::ListTtysCmd() :
485                  NetdCommand("list_ttys") {
486 }
487 
runCommand(SocketClient * cli,int,char **)488 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
489                                              int /* argc */, char ** /* argv */) {
490     TtyCollection *tlist = sPppCtrl->getTtyList();
491     TtyCollection::iterator it;
492 
493     for (it = tlist->begin(); it != tlist->end(); ++it) {
494         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
495     }
496 
497     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
498     return 0;
499 }
500 
IpFwdCmd()501 CommandListener::IpFwdCmd::IpFwdCmd() :
502                  NetdCommand("ipfwd") {
503 }
504 
runCommand(SocketClient * cli,int argc,char ** argv)505 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
506                                                       int argc, char **argv) {
507     int rc = 0;
508 
509     if (argc < 2) {
510         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
511         return 0;
512     }
513 
514     if (!strcmp(argv[1], "status")) {
515         char *tmp = NULL;
516 
517         asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
518         cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
519         free(tmp);
520         return 0;
521     } else if (!strcmp(argv[1], "enable")) {
522         rc = sTetherCtrl->setIpFwdEnabled(true);
523     } else if (!strcmp(argv[1], "disable")) {
524         rc = sTetherCtrl->setIpFwdEnabled(false);
525     } else {
526         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
527         return 0;
528     }
529 
530     if (!rc) {
531         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
532     } else {
533         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
534     }
535 
536     return 0;
537 }
538 
TetherCmd()539 CommandListener::TetherCmd::TetherCmd() :
540                  NetdCommand("tether") {
541 }
542 
runCommand(SocketClient * cli,int argc,char ** argv)543 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
544                                                       int argc, char **argv) {
545     int rc = 0;
546 
547     if (argc < 2) {
548         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
549         return 0;
550     }
551 
552     if (!strcmp(argv[1], "stop")) {
553         rc = sTetherCtrl->stopTethering();
554     } else if (!strcmp(argv[1], "status")) {
555         char *tmp = NULL;
556 
557         asprintf(&tmp, "Tethering services %s",
558                  (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
559         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
560         free(tmp);
561         return 0;
562     } else if (argc == 3) {
563         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
564             InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
565             InterfaceCollection::iterator it;
566             for (it = ilist->begin(); it != ilist->end(); ++it) {
567                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
568             }
569         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
570             char netIdStr[UINT32_STRLEN];
571             snprintf(netIdStr, sizeof(netIdStr), "%u", sTetherCtrl->getDnsNetId());
572             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
573 
574             NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
575             NetAddressCollection::iterator it;
576 
577             for (it = dlist->begin(); it != dlist->end(); ++it) {
578                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
579             }
580         }
581     } else {
582         /*
583          * These commands take a minimum of 4 arguments
584          */
585         if (argc < 4) {
586             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
587             return 0;
588         }
589 
590         if (!strcmp(argv[1], "start")) {
591             if (argc % 2 == 1) {
592                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
593                 return 0;
594             }
595 
596             int num_addrs = argc - 2;
597             int arg_index = 2;
598             int array_index = 0;
599             in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
600             while (array_index < num_addrs) {
601                 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
602                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
603                     free(addrs);
604                     return 0;
605                 }
606             }
607             rc = sTetherCtrl->startTethering(num_addrs, addrs);
608             free(addrs);
609         } else if (!strcmp(argv[1], "interface")) {
610             if (!strcmp(argv[2], "add")) {
611                 rc = sTetherCtrl->tetherInterface(argv[3]);
612             } else if (!strcmp(argv[2], "remove")) {
613                 rc = sTetherCtrl->untetherInterface(argv[3]);
614             /* else if (!strcmp(argv[2], "list")) handled above */
615             } else {
616                 cli->sendMsg(ResponseCode::CommandParameterError,
617                              "Unknown tether interface operation", false);
618                 return 0;
619             }
620         } else if (!strcmp(argv[1], "dns")) {
621             if (!strcmp(argv[2], "set")) {
622                 if (argc < 5) {
623                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
624                     return 0;
625                 }
626                 unsigned netId = stringToNetId(argv[3]);
627                 rc = sTetherCtrl->setDnsForwarders(netId, &argv[4], argc - 4);
628             /* else if (!strcmp(argv[2], "list")) handled above */
629             } else {
630                 cli->sendMsg(ResponseCode::CommandParameterError,
631                              "Unknown tether interface operation", false);
632                 return 0;
633             }
634         } else {
635             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
636             return 0;
637         }
638     }
639 
640     if (!rc) {
641         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
642     } else {
643         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
644     }
645 
646     return 0;
647 }
648 
NatCmd()649 CommandListener::NatCmd::NatCmd() :
650                  NetdCommand("nat") {
651 }
652 
runCommand(SocketClient * cli,int argc,char ** argv)653 int CommandListener::NatCmd::runCommand(SocketClient *cli,
654                                                       int argc, char **argv) {
655     int rc = 0;
656 
657     if (argc < 5) {
658         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
659         return 0;
660     }
661 
662     //  0     1       2        3
663     // nat  enable intiface extiface
664     // nat disable intiface extiface
665     if (!strcmp(argv[1], "enable") && argc >= 4) {
666         rc = sNatCtrl->enableNat(argv[2], argv[3]);
667         if(!rc) {
668             /* Ignore ifaces for now. */
669             rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
670         }
671     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
672         /* Ignore ifaces for now. */
673         rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
674         rc |= sNatCtrl->disableNat(argv[2], argv[3]);
675     } else {
676         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
677         return 0;
678     }
679 
680     if (!rc) {
681         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
682     } else {
683         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
684     }
685 
686     return 0;
687 }
688 
PppdCmd()689 CommandListener::PppdCmd::PppdCmd() :
690                  NetdCommand("pppd") {
691 }
692 
runCommand(SocketClient * cli,int argc,char ** argv)693 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
694                                                       int argc, char **argv) {
695     int rc = 0;
696 
697     if (argc < 3) {
698         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
699         return 0;
700     }
701 
702     if (!strcmp(argv[1], "attach")) {
703         struct in_addr l, r, dns1, dns2;
704 
705         memset(&dns1, 0, sizeof(struct in_addr));
706         memset(&dns2, 0, sizeof(struct in_addr));
707 
708         if (!inet_aton(argv[3], &l)) {
709             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
710             return 0;
711         }
712         if (!inet_aton(argv[4], &r)) {
713             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
714             return 0;
715         }
716         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
717             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
718             return 0;
719         }
720         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
721             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
722             return 0;
723         }
724         rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
725     } else if (!strcmp(argv[1], "detach")) {
726         rc = sPppCtrl->detachPppd(argv[2]);
727     } else {
728         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
729         return 0;
730     }
731 
732     if (!rc) {
733         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
734     } else {
735         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
736     }
737 
738     return 0;
739 }
740 
SoftapCmd()741 CommandListener::SoftapCmd::SoftapCmd() :
742                  NetdCommand("softap") {
743 }
744 
runCommand(SocketClient * cli,int argc,char ** argv)745 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
746                                         int argc, char **argv) {
747     int rc = ResponseCode::SoftapStatusResult;
748     char *retbuf = NULL;
749 
750     if (sSoftapCtrl == NULL) {
751       cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
752       return -1;
753     }
754     if (argc < 2) {
755         cli->sendMsg(ResponseCode::CommandSyntaxError,
756                      "Missing argument in a SoftAP command", false);
757         return 0;
758     }
759 
760     if (!strcmp(argv[1], "startap")) {
761         rc = sSoftapCtrl->startSoftap();
762     } else if (!strcmp(argv[1], "stopap")) {
763         rc = sSoftapCtrl->stopSoftap();
764     } else if (!strcmp(argv[1], "fwreload")) {
765         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
766     } else if (!strcmp(argv[1], "status")) {
767         asprintf(&retbuf, "Softap service %s running",
768                  (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
769         cli->sendMsg(rc, retbuf, false);
770         free(retbuf);
771         return 0;
772     } else if (!strcmp(argv[1], "set")) {
773         rc = sSoftapCtrl->setSoftap(argc, argv);
774     } else {
775         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
776         return 0;
777     }
778 
779     if (rc >= 400 && rc < 600)
780       cli->sendMsg(rc, "SoftAP command has failed", false);
781     else
782       cli->sendMsg(rc, "Ok", false);
783 
784     return 0;
785 }
786 
ResolverCmd()787 CommandListener::ResolverCmd::ResolverCmd() :
788         NetdCommand("resolver") {
789 }
790 
runCommand(SocketClient * cli,int argc,char ** margv)791 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
792     int rc = 0;
793     const char **argv = const_cast<const char **>(margv);
794 
795     if (argc < 2) {
796         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
797         return 0;
798     }
799 
800     if (!strcmp(argv[1], "setnetdns")) {
801         // "resolver setnetdns <netId> <domains> <dns1> <dns2> ..."
802         if (argc >= 5) {
803             rc = sResolverCtrl->setDnsServers(strtoul(argv[2], NULL, 0), argv[3], &argv[4], argc - 4);
804         } else {
805             cli->sendMsg(ResponseCode::CommandSyntaxError,
806                     "Wrong number of arguments to resolver setnetdns", false);
807             return 0;
808         }
809     } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
810         if (argc == 3) {
811             rc = sResolverCtrl->clearDnsServers(strtoul(argv[2], NULL, 0));
812         } else {
813             cli->sendMsg(ResponseCode::CommandSyntaxError,
814                     "Wrong number of arguments to resolver clearnetdns", false);
815             return 0;
816         }
817     } else if (!strcmp(argv[1], "flushnet")) { // "resolver flushnet <netId>"
818         if (argc == 3) {
819             rc = sResolverCtrl->flushDnsCache(strtoul(argv[2], NULL, 0));
820         } else {
821             cli->sendMsg(ResponseCode::CommandSyntaxError,
822                     "Wrong number of arguments to resolver flushnet", false);
823             return 0;
824         }
825     } else {
826         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
827         return 0;
828     }
829 
830     if (!rc) {
831         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
832     } else {
833         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
834     }
835 
836     return 0;
837 }
838 
BandwidthControlCmd()839 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
840     NetdCommand("bandwidth") {
841 }
842 
sendGenericSyntaxError(SocketClient * cli,const char * usageMsg)843 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
844     char *msg;
845     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
846     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
847     free(msg);
848 }
849 
sendGenericOkFail(SocketClient * cli,int cond)850 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
851     if (!cond) {
852         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
853     } else {
854         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
855     }
856 }
857 
sendGenericOpFailed(SocketClient * cli,const char * errMsg)858 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
859     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
860 }
861 
runCommand(SocketClient * cli,int argc,char ** argv)862 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
863     if (argc < 2) {
864         sendGenericSyntaxError(cli, "<cmds> <args...>");
865         return 0;
866     }
867 
868     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
869 
870     if (!strcmp(argv[1], "enable")) {
871         int rc = sBandwidthCtrl->enableBandwidthControl(true);
872         sendGenericOkFail(cli, rc);
873         return 0;
874 
875     }
876     if (!strcmp(argv[1], "disable")) {
877         int rc = sBandwidthCtrl->disableBandwidthControl();
878         sendGenericOkFail(cli, rc);
879         return 0;
880 
881     }
882     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
883         if (argc != 3) {
884             sendGenericSyntaxError(cli, "removequota <interface>");
885             return 0;
886         }
887         int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
888         sendGenericOkFail(cli, rc);
889         return 0;
890 
891     }
892     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
893         int64_t bytes;
894         if (argc != 2) {
895             sendGenericSyntaxError(cli, "getquota");
896             return 0;
897         }
898         int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
899         if (rc) {
900             sendGenericOpFailed(cli, "Failed to get quota");
901             return 0;
902         }
903 
904         char *msg;
905         asprintf(&msg, "%" PRId64, bytes);
906         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
907         free(msg);
908         return 0;
909 
910     }
911     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
912         int64_t bytes;
913         if (argc != 3) {
914             sendGenericSyntaxError(cli, "getiquota <iface>");
915             return 0;
916         }
917 
918         int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
919         if (rc) {
920             sendGenericOpFailed(cli, "Failed to get quota");
921             return 0;
922         }
923         char *msg;
924         asprintf(&msg, "%" PRId64, bytes);
925         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
926         free(msg);
927         return 0;
928 
929     }
930     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
931         if (argc != 4) {
932             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
933             return 0;
934         }
935         int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
936         sendGenericOkFail(cli, rc);
937         return 0;
938     }
939     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
940         int rc;
941         if (argc < 4) {
942             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
943             return 0;
944         }
945 
946         for (int q = 3; argc >= 4; q++, argc--) {
947             rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
948             if (rc) {
949                 char *msg;
950                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
951                 cli->sendMsg(ResponseCode::OperationFailed,
952                              msg, false);
953                 free(msg);
954                 return 0;
955             }
956         }
957         sendGenericOkFail(cli, rc);
958         return 0;
959 
960     }
961     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
962         int rc;
963         if (argc < 3) {
964             sendGenericSyntaxError(cli, "removequotas <interface> ...");
965             return 0;
966         }
967 
968         for (int q = 2; argc >= 3; q++, argc--) {
969             rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
970             if (rc) {
971                 char *msg;
972                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
973                 cli->sendMsg(ResponseCode::OperationFailed,
974                              msg, false);
975                 free(msg);
976                 return 0;
977             }
978         }
979         sendGenericOkFail(cli, rc);
980         return 0;
981 
982     }
983     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
984         if (argc != 3) {
985             sendGenericSyntaxError(cli, "removeiquota <interface>");
986             return 0;
987         }
988         int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
989         sendGenericOkFail(cli, rc);
990         return 0;
991 
992     }
993     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
994         if (argc != 4) {
995             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
996             return 0;
997         }
998         int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
999         sendGenericOkFail(cli, rc);
1000         return 0;
1001 
1002     }
1003     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1004         if (argc < 3) {
1005             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1006             return 0;
1007         }
1008         int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1009         sendGenericOkFail(cli, rc);
1010         return 0;
1011 
1012 
1013     }
1014     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1015         if (argc < 3) {
1016             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1017             return 0;
1018         }
1019         int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1020         sendGenericOkFail(cli, rc);
1021         return 0;
1022     }
1023     if (!strcmp(argv[1], "happybox")) {
1024         if (argc < 3) {
1025             sendGenericSyntaxError(cli, "happybox (enable | disable)");
1026             return 0;
1027         }
1028         if (!strcmp(argv[2], "enable")) {
1029             int rc = sBandwidthCtrl->enableHappyBox();
1030             sendGenericOkFail(cli, rc);
1031             return 0;
1032 
1033         }
1034         if (!strcmp(argv[2], "disable")) {
1035             int rc = sBandwidthCtrl->disableHappyBox();
1036             sendGenericOkFail(cli, rc);
1037             return 0;
1038         }
1039         sendGenericSyntaxError(cli, "happybox (enable | disable)");
1040         return 0;
1041     }
1042     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1043         if (argc < 3) {
1044             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1045             return 0;
1046         }
1047         int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1048         sendGenericOkFail(cli, rc);
1049         return 0;
1050     }
1051     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1052         if (argc < 3) {
1053             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1054             return 0;
1055         }
1056         int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1057         sendGenericOkFail(cli, rc);
1058         return 0;
1059     }
1060     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1061         if (argc != 3) {
1062             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1063             return 0;
1064         }
1065         int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1066         sendGenericOkFail(cli, rc);
1067         return 0;
1068     }
1069     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1070         if (argc != 4) {
1071             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1072             return 0;
1073         }
1074         /* We ignore the interfaces for now. */
1075         int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1076         sendGenericOkFail(cli, rc);
1077         return 0;
1078 
1079     }
1080     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1081         if (argc != 2) {
1082             sendGenericSyntaxError(cli, "removeglobalalert");
1083             return 0;
1084         }
1085         int rc = sBandwidthCtrl->removeGlobalAlert();
1086         sendGenericOkFail(cli, rc);
1087         return 0;
1088 
1089     }
1090     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1091         if (argc != 4) {
1092             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1093             return 0;
1094         }
1095         /* We ignore the interfaces for now. */
1096         int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1097         sendGenericOkFail(cli, rc);
1098         return 0;
1099 
1100     }
1101     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1102         if (argc != 3) {
1103             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1104             return 0;
1105         }
1106         int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1107         sendGenericOkFail(cli, rc);
1108         return 0;
1109 
1110     }
1111     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1112         if (argc != 2) {
1113             sendGenericSyntaxError(cli, "removesharedalert");
1114             return 0;
1115         }
1116         int rc = sBandwidthCtrl->removeSharedAlert();
1117         sendGenericOkFail(cli, rc);
1118         return 0;
1119 
1120     }
1121     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1122         if (argc != 4) {
1123             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1124             return 0;
1125         }
1126         int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1127         sendGenericOkFail(cli, rc);
1128         return 0;
1129 
1130     }
1131     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1132         if (argc != 3) {
1133             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1134             return 0;
1135         }
1136         int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1137         sendGenericOkFail(cli, rc);
1138         return 0;
1139 
1140     }
1141     if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1142         BandwidthController::TetherStats tetherStats;
1143         std::string extraProcessingInfo = "";
1144         if (argc < 2 || argc > 4) {
1145             sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1146             return 0;
1147         }
1148         tetherStats.intIface = argc > 2 ? argv[2] : "";
1149         tetherStats.extIface = argc > 3 ? argv[3] : "";
1150         // No filtering requested and there are no interface pairs to lookup.
1151         if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
1152             cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1153             return 0;
1154         }
1155         int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1156         if (rc) {
1157                 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1158                 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1159                 return 0;
1160         }
1161         return 0;
1162 
1163     }
1164 
1165     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1166     return 0;
1167 }
1168 
IdletimerControlCmd()1169 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1170     NetdCommand("idletimer") {
1171 }
1172 
runCommand(SocketClient * cli,int argc,char ** argv)1173 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1174   // TODO(ashish): Change the error statements
1175     if (argc < 2) {
1176         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1177         return 0;
1178     }
1179 
1180     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1181 
1182     if (!strcmp(argv[1], "enable")) {
1183       if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1184         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1185       } else {
1186         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1187       }
1188       return 0;
1189 
1190     }
1191     if (!strcmp(argv[1], "disable")) {
1192       if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1193         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1194       } else {
1195         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1196       }
1197       return 0;
1198     }
1199     if (!strcmp(argv[1], "add")) {
1200         if (argc != 5) {
1201             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1202             return 0;
1203         }
1204         if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1205                                         argv[2], atoi(argv[3]), argv[4])) {
1206           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1207         } else {
1208           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1209         }
1210         return 0;
1211     }
1212     if (!strcmp(argv[1], "remove")) {
1213         if (argc != 5) {
1214             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1215             return 0;
1216         }
1217         // ashish: fixme timeout
1218         if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1219                                         argv[2], atoi(argv[3]), argv[4])) {
1220           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1221         } else {
1222           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1223         }
1224         return 0;
1225     }
1226 
1227     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1228     return 0;
1229 }
1230 
FirewallCmd()1231 CommandListener::FirewallCmd::FirewallCmd() :
1232     NetdCommand("firewall") {
1233 }
1234 
sendGenericOkFail(SocketClient * cli,int cond)1235 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1236     if (!cond) {
1237         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1238     } else {
1239         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1240     }
1241     return 0;
1242 }
1243 
parseRule(const char * arg)1244 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1245     if (!strcmp(arg, "allow")) {
1246         return ALLOW;
1247     } else {
1248         return DENY;
1249     }
1250 }
1251 
runCommand(SocketClient * cli,int argc,char ** argv)1252 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1253         char **argv) {
1254     if (argc < 2) {
1255         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1256         return 0;
1257     }
1258 
1259     if (!strcmp(argv[1], "enable")) {
1260         int res = sFirewallCtrl->enableFirewall();
1261         return sendGenericOkFail(cli, res);
1262     }
1263     if (!strcmp(argv[1], "disable")) {
1264         int res = sFirewallCtrl->disableFirewall();
1265         return sendGenericOkFail(cli, res);
1266     }
1267     if (!strcmp(argv[1], "is_enabled")) {
1268         int res = sFirewallCtrl->isFirewallEnabled();
1269         return sendGenericOkFail(cli, res);
1270     }
1271 
1272     if (!strcmp(argv[1], "set_interface_rule")) {
1273         if (argc != 4) {
1274             cli->sendMsg(ResponseCode::CommandSyntaxError,
1275                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1276             return 0;
1277         }
1278 
1279         const char* iface = argv[2];
1280         FirewallRule rule = parseRule(argv[3]);
1281 
1282         int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1283         return sendGenericOkFail(cli, res);
1284     }
1285 
1286     if (!strcmp(argv[1], "set_egress_source_rule")) {
1287         if (argc != 4) {
1288             cli->sendMsg(ResponseCode::CommandSyntaxError,
1289                          "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1290                          false);
1291             return 0;
1292         }
1293 
1294         const char* addr = argv[2];
1295         FirewallRule rule = parseRule(argv[3]);
1296 
1297         int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1298         return sendGenericOkFail(cli, res);
1299     }
1300 
1301     if (!strcmp(argv[1], "set_egress_dest_rule")) {
1302         if (argc != 5) {
1303             cli->sendMsg(ResponseCode::CommandSyntaxError,
1304                          "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1305                          false);
1306             return 0;
1307         }
1308 
1309         const char* addr = argv[2];
1310         int port = atoi(argv[3]);
1311         FirewallRule rule = parseRule(argv[4]);
1312 
1313         int res = 0;
1314         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1315         res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1316         return sendGenericOkFail(cli, res);
1317     }
1318 
1319     if (!strcmp(argv[1], "set_uid_rule")) {
1320         if (argc != 4) {
1321             cli->sendMsg(ResponseCode::CommandSyntaxError,
1322                          "Usage: firewall set_uid_rule <1000> <allow|deny>",
1323                          false);
1324             return 0;
1325         }
1326 
1327         int uid = atoi(argv[2]);
1328         FirewallRule rule = parseRule(argv[3]);
1329 
1330         int res = sFirewallCtrl->setUidRule(uid, rule);
1331         return sendGenericOkFail(cli, res);
1332     }
1333 
1334     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1335     return 0;
1336 }
1337 
ClatdCmd()1338 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1339 }
1340 
runCommand(SocketClient * cli,int argc,char ** argv)1341 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1342                                                             char **argv) {
1343     int rc = 0;
1344     if (argc < 3) {
1345         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1346         return 0;
1347     }
1348 
1349     if (!strcmp(argv[1], "stop")) {
1350         rc = sClatdCtrl->stopClatd(argv[2]);
1351     } else if (!strcmp(argv[1], "status")) {
1352         char *tmp = NULL;
1353         asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted(argv[2]) ?
1354                                             "started" : "stopped"));
1355         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1356         free(tmp);
1357         return 0;
1358     } else if (!strcmp(argv[1], "start")) {
1359         rc = sClatdCtrl->startClatd(argv[2]);
1360     } else {
1361         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1362         return 0;
1363     }
1364 
1365     if (!rc) {
1366         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1367     } else {
1368         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1369     }
1370 
1371     return 0;
1372 }
1373 
NetworkCommand()1374 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1375 }
1376 
syntaxError(SocketClient * client,const char * message)1377 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1378     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1379     return 0;
1380 }
1381 
operationError(SocketClient * client,const char * message,int ret)1382 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1383                                                     int ret) {
1384     errno = -ret;
1385     client->sendMsg(ResponseCode::OperationFailed, message, true);
1386     return 0;
1387 }
1388 
success(SocketClient * client)1389 int CommandListener::NetworkCommand::success(SocketClient* client) {
1390     client->sendMsg(ResponseCode::CommandOkay, "success", false);
1391     return 0;
1392 }
1393 
runCommand(SocketClient * client,int argc,char ** argv)1394 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1395     if (argc < 2) {
1396         return syntaxError(client, "Missing argument");
1397     }
1398 
1399     //    0      1      2      3      4       5         6            7           8
1400     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1401     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1402     //
1403     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1404     if (!strcmp(argv[1], "route")) {
1405         if (argc < 6 || argc > 9) {
1406             return syntaxError(client, "Incorrect number of arguments");
1407         }
1408 
1409         int nextArg = 2;
1410         bool legacy = false;
1411         uid_t uid = 0;
1412         if (!strcmp(argv[nextArg], "legacy")) {
1413             ++nextArg;
1414             legacy = true;
1415             uid = strtoul(argv[nextArg++], NULL, 0);
1416         }
1417 
1418         bool add = false;
1419         if (!strcmp(argv[nextArg], "add")) {
1420             add = true;
1421         } else if (strcmp(argv[nextArg], "remove")) {
1422             return syntaxError(client, "Unknown argument");
1423         }
1424         ++nextArg;
1425 
1426         if (argc < nextArg + 3 || argc > nextArg + 4) {
1427             return syntaxError(client, "Incorrect number of arguments");
1428         }
1429 
1430         unsigned netId = stringToNetId(argv[nextArg++]);
1431         const char* interface = argv[nextArg++];
1432         const char* destination = argv[nextArg++];
1433         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1434 
1435         int ret;
1436         if (add) {
1437             ret = sNetCtrl->addRoute(netId, interface, destination, nexthop, legacy, uid);
1438         } else {
1439             ret = sNetCtrl->removeRoute(netId, interface, destination, nexthop, legacy, uid);
1440         }
1441         if (ret) {
1442             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1443         }
1444 
1445         return success(client);
1446     }
1447 
1448     //    0        1       2       3         4
1449     // network interface  add   <netId> <interface>
1450     // network interface remove <netId> <interface>
1451     if (!strcmp(argv[1], "interface")) {
1452         if (argc != 5) {
1453             return syntaxError(client, "Missing argument");
1454         }
1455         unsigned netId = stringToNetId(argv[3]);
1456         if (!strcmp(argv[2], "add")) {
1457             if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {
1458                 return operationError(client, "addInterfaceToNetwork() failed", ret);
1459             }
1460         } else if (!strcmp(argv[2], "remove")) {
1461             if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {
1462                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1463             }
1464         } else {
1465             return syntaxError(client, "Unknown argument");
1466         }
1467         return success(client);
1468     }
1469 
1470     //    0      1       2         3
1471     // network create <netId> [permission]
1472     //
1473     //    0      1       2     3     4        5
1474     // network create <netId> vpn <hasDns> <secure>
1475     if (!strcmp(argv[1], "create")) {
1476         if (argc < 3) {
1477             return syntaxError(client, "Missing argument");
1478         }
1479         unsigned netId = stringToNetId(argv[2]);
1480         if (argc == 6 && !strcmp(argv[3], "vpn")) {
1481             bool hasDns = atoi(argv[4]);
1482             bool secure = atoi(argv[5]);
1483             if (int ret = sNetCtrl->createVirtualNetwork(netId, hasDns, secure)) {
1484                 return operationError(client, "createVirtualNetwork() failed", ret);
1485             }
1486         } else if (argc > 4) {
1487             return syntaxError(client, "Unknown trailing argument(s)");
1488         } else {
1489             Permission permission = PERMISSION_NONE;
1490             if (argc == 4) {
1491                 permission = stringToPermission(argv[3]);
1492                 if (permission == PERMISSION_NONE) {
1493                     return syntaxError(client, "Unknown permission");
1494                 }
1495             }
1496             if (int ret = sNetCtrl->createPhysicalNetwork(netId, permission)) {
1497                 return operationError(client, "createPhysicalNetwork() failed", ret);
1498             }
1499         }
1500         return success(client);
1501     }
1502 
1503     //    0       1       2
1504     // network destroy <netId>
1505     if (!strcmp(argv[1], "destroy")) {
1506         if (argc != 3) {
1507             return syntaxError(client, "Incorrect number of arguments");
1508         }
1509         unsigned netId = stringToNetId(argv[2]);
1510         if (int ret = sNetCtrl->destroyNetwork(netId)) {
1511             return operationError(client, "destroyNetwork() failed", ret);
1512         }
1513         return success(client);
1514     }
1515 
1516     //    0       1      2      3
1517     // network default  set  <netId>
1518     // network default clear
1519     if (!strcmp(argv[1], "default")) {
1520         if (argc < 3) {
1521             return syntaxError(client, "Missing argument");
1522         }
1523         unsigned netId = NETID_UNSET;
1524         if (!strcmp(argv[2], "set")) {
1525             if (argc < 4) {
1526                 return syntaxError(client, "Missing netId");
1527             }
1528             netId = stringToNetId(argv[3]);
1529         } else if (strcmp(argv[2], "clear")) {
1530             return syntaxError(client, "Unknown argument");
1531         }
1532         if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
1533             return operationError(client, "setDefaultNetwork() failed", ret);
1534         }
1535         return success(client);
1536     }
1537 
1538     //    0        1         2      3        4          5
1539     // network permission   user   set  <permission>  <uid> ...
1540     // network permission   user  clear    <uid> ...
1541     // network permission network  set  <permission> <netId> ...
1542     // network permission network clear   <netId> ...
1543     if (!strcmp(argv[1], "permission")) {
1544         if (argc < 5) {
1545             return syntaxError(client, "Missing argument");
1546         }
1547         int nextArg = 4;
1548         Permission permission = PERMISSION_NONE;
1549         if (!strcmp(argv[3], "set")) {
1550             permission = stringToPermission(argv[4]);
1551             if (permission == PERMISSION_NONE) {
1552                 return syntaxError(client, "Unknown permission");
1553             }
1554             nextArg = 5;
1555         } else if (strcmp(argv[3], "clear")) {
1556             return syntaxError(client, "Unknown argument");
1557         }
1558         if (nextArg == argc) {
1559             return syntaxError(client, "Missing id");
1560         }
1561         std::vector<unsigned> ids;
1562         for (; nextArg < argc; ++nextArg) {
1563             char* endPtr;
1564             unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1565             if (!*argv[nextArg] || *endPtr) {
1566                 return syntaxError(client, "Invalid id");
1567             }
1568             ids.push_back(id);
1569         }
1570         if (!strcmp(argv[2], "user")) {
1571             sNetCtrl->setPermissionForUsers(permission, ids);
1572         } else if (!strcmp(argv[2], "network")) {
1573             if (int ret = sNetCtrl->setPermissionForNetworks(permission, ids)) {
1574                 return operationError(client, "setPermissionForNetworks() failed", ret);
1575             }
1576         } else {
1577             return syntaxError(client, "Unknown argument");
1578         }
1579         return success(client);
1580     }
1581 
1582     //    0      1     2       3           4
1583     // network users  add   <netId> [<uid>[-<uid>]] ...
1584     // network users remove <netId> [<uid>[-<uid>]] ...
1585     if (!strcmp(argv[1], "users")) {
1586         if (argc < 4) {
1587             return syntaxError(client, "Missing argument");
1588         }
1589         unsigned netId = stringToNetId(argv[3]);
1590         UidRanges uidRanges;
1591         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1592             return syntaxError(client, "Invalid UIDs");
1593         }
1594         if (!strcmp(argv[2], "add")) {
1595             if (int ret = sNetCtrl->addUsersToNetwork(netId, uidRanges)) {
1596                 return operationError(client, "addUsersToNetwork() failed", ret);
1597             }
1598         } else if (!strcmp(argv[2], "remove")) {
1599             if (int ret = sNetCtrl->removeUsersFromNetwork(netId, uidRanges)) {
1600                 return operationError(client, "removeUsersFromNetwork() failed", ret);
1601             }
1602         } else {
1603             return syntaxError(client, "Unknown argument");
1604         }
1605         return success(client);
1606     }
1607 
1608     //    0       1      2     3
1609     // network protect allow <uid> ...
1610     // network protect  deny <uid> ...
1611     if (!strcmp(argv[1], "protect")) {
1612         if (argc < 4) {
1613             return syntaxError(client, "Missing argument");
1614         }
1615         std::vector<uid_t> uids;
1616         for (int i = 3; i < argc; ++i) {
1617             uids.push_back(strtoul(argv[i], NULL, 0));
1618         }
1619         if (!strcmp(argv[2], "allow")) {
1620             sNetCtrl->allowProtect(uids);
1621         } else if (!strcmp(argv[2], "deny")) {
1622             sNetCtrl->denyProtect(uids);
1623         } else {
1624             return syntaxError(client, "Unknown argument");
1625         }
1626         return success(client);
1627     }
1628 
1629     return syntaxError(client, "Unknown argument");
1630 }
1631