OSDN Git Service

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