OSDN Git Service

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