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