OSDN Git Service

99e126963dbca89260af55debfaed9a5a41cd912
[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 <fcntl.h>
28 #include <linux/if.h>
29
30 #define LOG_TAG "CommandListener"
31
32 #include <cutils/log.h>
33 #include <netutils/ifc.h>
34 #include <sysutils/SocketClient.h>
35
36 #include "CommandListener.h"
37 #include "ResponseCode.h"
38 #include "ThrottleController.h"
39 #include "BandwidthController.h"
40 #include "SecondaryTableController.h"
41
42
43 TetherController *CommandListener::sTetherCtrl = NULL;
44 NatController *CommandListener::sNatCtrl = NULL;
45 PppController *CommandListener::sPppCtrl = NULL;
46 PanController *CommandListener::sPanCtrl = NULL;
47 SoftapController *CommandListener::sSoftapCtrl = NULL;
48 BandwidthController * CommandListener::sBandwidthCtrl = NULL;
49 ResolverController *CommandListener::sResolverCtrl = NULL;
50 SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
51
52 CommandListener::CommandListener() :
53                  FrameworkListener("netd") {
54     registerCmd(new InterfaceCmd());
55     registerCmd(new IpFwdCmd());
56     registerCmd(new TetherCmd());
57     registerCmd(new NatCmd());
58     registerCmd(new ListTtysCmd());
59     registerCmd(new PppdCmd());
60     registerCmd(new PanCmd());
61     registerCmd(new SoftapCmd());
62     registerCmd(new BandwidthControlCmd());
63     registerCmd(new ResolverCmd());
64
65     if (!sSecondaryTableCtrl)
66         sSecondaryTableCtrl = new SecondaryTableController();
67     if (!sTetherCtrl)
68         sTetherCtrl = new TetherController();
69     if (!sNatCtrl)
70         sNatCtrl = new NatController(sSecondaryTableCtrl);
71     if (!sPppCtrl)
72         sPppCtrl = new PppController();
73     if (!sPanCtrl)
74         sPanCtrl = new PanController();
75     if (!sSoftapCtrl)
76         sSoftapCtrl = new SoftapController();
77     if (!sBandwidthCtrl)
78         sBandwidthCtrl = new BandwidthController();
79     if (!sResolverCtrl)
80         sResolverCtrl = new ResolverController();
81 }
82
83 CommandListener::InterfaceCmd::InterfaceCmd() :
84                  NetdCommand("interface") {
85 }
86
87 int CommandListener::writeFile(const char *path, const char *value, int size) {
88     int fd = open(path, O_WRONLY);
89     if (fd < 0) {
90         LOGE("Failed to open %s: %s", path, strerror(errno));
91         return -1;
92     }
93
94     if (write(fd, value, size) != size) {
95         LOGE("Failed to write %s: %s", path, strerror(errno));
96         close(fd);
97         return -1;
98     }
99     close(fd);
100     return 0;
101 }
102
103 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
104                                                       int argc, char **argv) {
105     if (argc < 2) {
106         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
107         return 0;
108     }
109
110     if (!strcmp(argv[1], "list")) {
111         DIR *d;
112         struct dirent *de;
113
114         if (!(d = opendir("/sys/class/net"))) {
115             cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
116             return 0;
117         }
118
119         while((de = readdir(d))) {
120             if (de->d_name[0] == '.')
121                 continue;
122             cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
123         }
124         closedir(d);
125         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
126         return 0;
127     } else if (!strcmp(argv[1], "readrxcounter")) {
128         if (argc != 3) {
129             cli->sendMsg(ResponseCode::CommandSyntaxError,
130                     "Usage: interface readrxcounter <interface>", false);
131             return 0;
132         }
133         unsigned long rx = 0, tx = 0;
134         if (readInterfaceCounters(argv[2], &rx, &tx)) {
135             cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
136             return 0;
137         }
138
139         char *msg;
140         asprintf(&msg, "%lu", rx);
141         cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
142         free(msg);
143
144         return 0;
145     } else if (!strcmp(argv[1], "readtxcounter")) {
146         if (argc != 3) {
147             cli->sendMsg(ResponseCode::CommandSyntaxError,
148                     "Usage: interface readtxcounter <interface>", false);
149             return 0;
150         }
151         unsigned long rx = 0, tx = 0;
152         if (readInterfaceCounters(argv[2], &rx, &tx)) {
153             cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
154             return 0;
155         }
156
157         char *msg = NULL;
158         asprintf(&msg, "%lu", tx);
159         cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
160         free(msg);
161         return 0;
162     } else if (!strcmp(argv[1], "getthrottle")) {
163         if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
164             cli->sendMsg(ResponseCode::CommandSyntaxError,
165                     "Usage: interface getthrottle <interface> <rx|tx>", false);
166             return 0;
167         }
168         int val = 0;
169         int rc = 0;
170         int voldRc = ResponseCode::InterfaceRxThrottleResult;
171
172         if (!strcmp(argv[3], "rx")) {
173             rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
174         } else {
175             rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
176             voldRc = ResponseCode::InterfaceTxThrottleResult;
177         }
178         if (rc) {
179             cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
180         } else {
181             char *msg = NULL;
182             asprintf(&msg, "%u", val);
183             cli->sendMsg(voldRc, msg, false);
184             free(msg);
185             return 0;
186         }
187         return 0;
188     } else if (!strcmp(argv[1], "setthrottle")) {
189         if (argc != 5) {
190             cli->sendMsg(ResponseCode::CommandSyntaxError,
191                     "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
192             return 0;
193         }
194         if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
195             cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
196         } else {
197             cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
198         }
199         return 0;
200     } else {
201         /*
202          * These commands take a minimum of 3 arguments
203          */
204         if (argc < 3) {
205             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
206             return 0;
207         }
208
209         //     0       1       2        3          4           5     6      7
210         // interface route add/remove iface default/secondary dest prefix gateway
211         if (!strcmp(argv[1], "route")) {
212             int prefix_length = 0;
213             if (argc < 8) {
214                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
215                 return 0;
216             }
217             if (sscanf(argv[6], "%d", &prefix_length) != 1) {
218                 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
219                 return 0;
220             }
221             if (!strcmp(argv[2], "add")) {
222                 if (!strcmp(argv[4], "default")) {
223                     if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
224                         cli->sendMsg(ResponseCode::OperationFailed,
225                                 "Failed to add route to default table", true);
226                     } else {
227                         cli->sendMsg(ResponseCode::CommandOkay,
228                                 "Route added to default table", false);
229                     }
230                 } else if (!strcmp(argv[4], "secondary")) {
231                     return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
232                             prefix_length, argv[7]);
233                 } else {
234                     cli->sendMsg(ResponseCode::CommandParameterError,
235                             "Invalid route type, expecting 'default' or 'secondary'", false);
236                     return 0;
237                 }
238             } else if (!strcmp(argv[2], "remove")) {
239                 if (!strcmp(argv[4], "default")) {
240                     if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
241                         cli->sendMsg(ResponseCode::OperationFailed,
242                                 "Failed to remove route from default table", true);
243                     } else {
244                         cli->sendMsg(ResponseCode::CommandOkay,
245                                 "Route removed from default table", false);
246                     }
247                 } else if (!strcmp(argv[4], "secondary")) {
248                     return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
249                             prefix_length, argv[7]);
250                 } else {
251                     cli->sendMsg(ResponseCode::CommandParameterError,
252                             "Invalid route type, expecting 'default' or 'secondary'", false);
253                     return 0;
254                 }
255             } else {
256                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
257             }
258             return 0;
259         }
260
261         if (!strcmp(argv[1], "getcfg")) {
262             struct in_addr addr;
263             int prefixLength;
264             unsigned char hwaddr[6];
265             unsigned flags = 0;
266
267             ifc_init();
268             memset(hwaddr, 0, sizeof(hwaddr));
269
270             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
271                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
272                 ifc_close();
273                 return 0;
274             }
275
276             if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
277                 LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
278             }
279
280             char *addr_s = strdup(inet_ntoa(addr));
281             const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
282
283             updown =  (flags & IFF_UP)           ? "up" : "down";
284             brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
285             loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
286             ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
287             running = (flags & IFF_RUNNING)      ? " running" : "";
288             multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
289
290             char *flag_s;
291
292             asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
293
294             char *msg = NULL;
295             asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
296                      hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
297                      addr_s, prefixLength, flag_s);
298
299             cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
300
301             free(addr_s);
302             free(flag_s);
303             free(msg);
304
305             ifc_close();
306             return 0;
307         } else if (!strcmp(argv[1], "setcfg")) {
308             // arglist: iface addr prefixLength flags
309             if (argc < 5) {
310                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
311                 return 0;
312             }
313             LOGD("Setting iface cfg");
314
315             struct in_addr addr;
316             unsigned flags = 0;
317
318             if (!inet_aton(argv[3], &addr)) {
319                 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
320                 return 0;
321             }
322
323             ifc_init();
324             if (ifc_set_addr(argv[2], addr.s_addr)) {
325                 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
326                 ifc_close();
327                 return 0;
328             }
329
330             //Set prefix length on a non zero address
331             if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
332                 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
333                 ifc_close();
334                 return 0;
335             }
336
337             /* Process flags */
338             for (int i = 5; i < argc; i++) {
339                 char *flag = argv[i];
340                 if (!strcmp(flag, "up")) {
341                     LOGD("Trying to bring up %s", argv[2]);
342                     if (ifc_up(argv[2])) {
343                         LOGE("Error upping interface");
344                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
345                         ifc_close();
346                         return 0;
347                     }
348                 } else if (!strcmp(flag, "down")) {
349                     LOGD("Trying to bring down %s", argv[2]);
350                     if (ifc_down(argv[2])) {
351                         LOGE("Error downing interface");
352                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
353                         ifc_close();
354                         return 0;
355                     }
356                 } else if (!strcmp(flag, "broadcast")) {
357                     // currently ignored
358                 } else if (!strcmp(flag, "multicast")) {
359                     // currently ignored
360                 } else if (!strcmp(flag, "running")) {
361                     // currently ignored
362                 } else if (!strcmp(flag, "loopback")) {
363                     // currently ignored
364                 } else if (!strcmp(flag, "point-to-point")) {
365                     // currently ignored
366                 } else {
367                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
368                     ifc_close();
369                     return 0;
370                 }
371             }
372
373             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
374             ifc_close();
375             return 0;
376         } else if (!strcmp(argv[1], "clearaddrs")) {
377             // arglist: iface
378             LOGD("Clearing all IP addresses on %s", argv[2]);
379
380             ifc_clear_addresses(argv[2]);
381
382             cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
383             return 0;
384         } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
385             if (argc != 4) {
386                 cli->sendMsg(ResponseCode::CommandSyntaxError,
387                         "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
388                         false);
389                 return 0;
390             }
391
392             char *tmp;
393             asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]);
394
395             if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) {
396                 free(tmp);
397                 cli->sendMsg(ResponseCode::OperationFailed,
398                         "Failed to set ipv6 privacy extensions", true);
399                 return 0;
400             }
401
402             free(tmp);
403             cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
404             return 0;
405         } else if (!strcmp(argv[1], "ipv6")) {
406             if (argc != 4) {
407                 cli->sendMsg(ResponseCode::CommandSyntaxError,
408                         "Usage: interface ipv6 <interface> <enable|disable>",
409                         false);
410                 return 0;
411             }
412
413             char *tmp;
414             asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]);
415
416             if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) {
417                 free(tmp);
418                 cli->sendMsg(ResponseCode::OperationFailed,
419                         "Failed to change IPv6 state", true);
420                 return 0;
421             }
422
423             free(tmp);
424             cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
425             return 0;
426         } else {
427             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
428             return 0;
429         }
430     }
431     return 0;
432 }
433
434
435 CommandListener::ListTtysCmd::ListTtysCmd() :
436                  NetdCommand("list_ttys") {
437 }
438
439 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
440                                              int argc, char **argv) {
441     TtyCollection *tlist = sPppCtrl->getTtyList();
442     TtyCollection::iterator it;
443
444     for (it = tlist->begin(); it != tlist->end(); ++it) {
445         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
446     }
447
448     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
449     return 0;
450 }
451
452 CommandListener::IpFwdCmd::IpFwdCmd() :
453                  NetdCommand("ipfwd") {
454 }
455
456 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
457                                                       int argc, char **argv) {
458     int rc = 0;
459
460     if (argc < 2) {
461         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
462         return 0;
463     }
464
465     if (!strcmp(argv[1], "status")) {
466         char *tmp = NULL;
467
468         asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
469         cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
470         free(tmp);
471         return 0;
472     } else if (!strcmp(argv[1], "enable")) {
473         rc = sTetherCtrl->setIpFwdEnabled(true);
474     } else if (!strcmp(argv[1], "disable")) {
475         rc = sTetherCtrl->setIpFwdEnabled(false);
476     } else {
477         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
478         return 0;
479     }
480
481     if (!rc) {
482         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
483     } else {
484         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
485     }
486
487     return 0;
488 }
489
490 CommandListener::TetherCmd::TetherCmd() :
491                  NetdCommand("tether") {
492 }
493
494 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
495                                                       int argc, char **argv) {
496     int rc = 0;
497
498     if (argc < 2) {
499         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
500         return 0;
501     }
502
503     if (!strcmp(argv[1], "stop")) {
504         rc = sTetherCtrl->stopTethering();
505     } else if (!strcmp(argv[1], "status")) {
506         char *tmp = NULL;
507
508         asprintf(&tmp, "Tethering services %s",
509                  (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
510         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
511         free(tmp);
512         return 0;
513     } else {
514         /*
515          * These commands take a minimum of 4 arguments
516          */
517         if (argc < 4) {
518             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
519             return 0;
520         }
521
522         if (!strcmp(argv[1], "start")) {
523             if (argc % 2 == 1) {
524                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
525                 return 0;
526             }
527
528             int num_addrs = argc - 2;
529             int arg_index = 2;
530             int array_index = 0;
531             in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
532             while (array_index < num_addrs) {
533                 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
534                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
535                     free(addrs);
536                     return 0;
537                 }
538             }
539             rc = sTetherCtrl->startTethering(num_addrs, addrs);
540             free(addrs);
541         } else if (!strcmp(argv[1], "interface")) {
542             if (!strcmp(argv[2], "add")) {
543                 rc = sTetherCtrl->tetherInterface(argv[3]);
544             } else if (!strcmp(argv[2], "remove")) {
545                 rc = sTetherCtrl->untetherInterface(argv[3]);
546             } else if (!strcmp(argv[2], "list")) {
547                 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
548                 InterfaceCollection::iterator it;
549
550                 for (it = ilist->begin(); it != ilist->end(); ++it) {
551                     cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
552                 }
553             } else {
554                 cli->sendMsg(ResponseCode::CommandParameterError,
555                              "Unknown tether interface operation", false);
556                 return 0;
557             }
558         } else if (!strcmp(argv[1], "dns")) {
559             if (!strcmp(argv[2], "set")) {
560                 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
561             } else if (!strcmp(argv[2], "list")) {
562                 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
563                 NetAddressCollection::iterator it;
564
565                 for (it = dlist->begin(); it != dlist->end(); ++it) {
566                     cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
567                 }
568             } else {
569                 cli->sendMsg(ResponseCode::CommandParameterError,
570                              "Unknown tether interface operation", false);
571                 return 0;
572             }
573         } else {
574             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
575             return 0;
576         }
577     }
578
579     if (!rc) {
580         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
581     } else {
582         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
583     }
584
585     return 0;
586 }
587
588 CommandListener::NatCmd::NatCmd() :
589                  NetdCommand("nat") {
590 }
591
592 int CommandListener::NatCmd::runCommand(SocketClient *cli,
593                                                       int argc, char **argv) {
594     int rc = 0;
595
596     if (argc < 5) {
597         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
598         return 0;
599     }
600
601     if (!strcmp(argv[1], "enable")) {
602         rc = sNatCtrl->enableNat(argc, argv);
603         if(!rc) {
604             /* Ignore ifaces for now. */
605             rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
606         }
607     } else if (!strcmp(argv[1], "disable")) {
608         /* Ignore ifaces for now. */
609         rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
610         rc |= sNatCtrl->disableNat(argc, argv);
611     } else {
612         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
613         return 0;
614     }
615
616     if (!rc) {
617         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
618     } else {
619         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
620     }
621
622     return 0;
623 }
624
625 CommandListener::PppdCmd::PppdCmd() :
626                  NetdCommand("pppd") {
627 }
628
629 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
630                                                       int argc, char **argv) {
631     int rc = 0;
632
633     if (argc < 3) {
634         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
635         return 0;
636     }
637
638     if (!strcmp(argv[1], "attach")) {
639         struct in_addr l, r, dns1, dns2;
640
641         memset(&dns1, sizeof(struct in_addr), 0);
642         memset(&dns2, sizeof(struct in_addr), 0);
643
644         if (!inet_aton(argv[3], &l)) {
645             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
646             return 0;
647         }
648         if (!inet_aton(argv[4], &r)) {
649             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
650             return 0;
651         }
652         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
653             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
654             return 0;
655         }
656         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
657             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
658             return 0;
659         }
660         rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
661     } else if (!strcmp(argv[1], "detach")) {
662         rc = sPppCtrl->detachPppd(argv[2]);
663     } else {
664         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
665         return 0;
666     }
667
668     if (!rc) {
669         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
670     } else {
671         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
672     }
673
674     return 0;
675 }
676
677 CommandListener::PanCmd::PanCmd() :
678                  NetdCommand("pan") {
679 }
680
681 int CommandListener::PanCmd::runCommand(SocketClient *cli,
682                                         int argc, char **argv) {
683     int rc = 0;
684
685     if (argc < 2) {
686         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
687         return 0;
688     }
689
690     if (!strcmp(argv[1], "start")) {
691         rc = sPanCtrl->startPan();
692     } else if (!strcmp(argv[1], "stop")) {
693         rc = sPanCtrl->stopPan();
694     } else if (!strcmp(argv[1], "status")) {
695         char *tmp = NULL;
696
697         asprintf(&tmp, "Pan services %s",
698                  (sPanCtrl->isPanStarted() ? "started" : "stopped"));
699         cli->sendMsg(ResponseCode::PanStatusResult, tmp, false);
700         free(tmp);
701         return 0;
702     } else {
703         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false);
704         return 0;
705     }
706
707     if (!rc) {
708         cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false);
709     } else {
710         cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true);
711     }
712
713     return 0;
714 }
715
716 CommandListener::SoftapCmd::SoftapCmd() :
717                  NetdCommand("softap") {
718 }
719
720 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
721                                         int argc, char **argv) {
722     int rc = 0, flag = 0;
723     char *retbuf = NULL;
724
725     if (argc < 2) {
726         cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
727         return 0;
728     }
729
730     if (!strcmp(argv[1], "start")) {
731         rc = sSoftapCtrl->startDriver(argv[2]);
732     } else if (!strcmp(argv[1], "stop")) {
733         rc = sSoftapCtrl->stopDriver(argv[2]);
734     } else if (!strcmp(argv[1], "startap")) {
735         rc = sSoftapCtrl->startSoftap();
736     } else if (!strcmp(argv[1], "stopap")) {
737         rc = sSoftapCtrl->stopSoftap();
738     } else if (!strcmp(argv[1], "fwreload")) {
739         rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
740     } else if (!strcmp(argv[1], "clients")) {
741         rc = sSoftapCtrl->clientsSoftap(&retbuf);
742         if (!rc) {
743             cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
744             free(retbuf);
745             return 0;
746         }
747     } else if (!strcmp(argv[1], "status")) {
748         asprintf(&retbuf, "Softap service %s",
749                  (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
750         cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
751         free(retbuf);
752         return 0;
753     } else if (!strcmp(argv[1], "set")) {
754         rc = sSoftapCtrl->setSoftap(argc, argv);
755     } else {
756         cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
757         return 0;
758     }
759
760     if (!rc) {
761         cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
762     } else {
763         cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
764     }
765
766     return 0;
767 }
768
769 CommandListener::ResolverCmd::ResolverCmd() :
770         NetdCommand("resolver") {
771 }
772
773 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
774     int rc = 0;
775     struct in_addr addr;
776
777     if (argc < 2) {
778         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
779         return 0;
780     }
781
782     if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
783         if (argc == 3) {
784             rc = sResolverCtrl->setDefaultInterface(argv[2]);
785         } else {
786             cli->sendMsg(ResponseCode::CommandSyntaxError,
787                     "Wrong number of arguments to resolver setdefaultif", false);
788             return 0;
789         }
790     } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
791         if (argc >= 4) {
792             rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
793         } else {
794             cli->sendMsg(ResponseCode::CommandSyntaxError,
795                     "Wrong number of arguments to resolver setifdns", false);
796             return 0;
797         }
798
799         // set the address of the interface to which the name servers
800         // are bound. Required in order to bind to right interface when
801         // doing the dns query.
802         if (!rc) {
803             ifc_init();
804             ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
805
806             rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
807         }
808     } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
809         if (argc == 2) {
810             rc = sResolverCtrl->flushDefaultDnsCache();
811         } else {
812             cli->sendMsg(ResponseCode::CommandSyntaxError,
813                     "Wrong number of arguments to resolver flushdefaultif", false);
814             return 0;
815         }
816     } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
817         if (argc == 3) {
818             rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
819         } else {
820             cli->sendMsg(ResponseCode::CommandSyntaxError,
821                     "Wrong number of arguments to resolver setdefaultif", false);
822             return 0;
823         }
824     } else {
825         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
826         return 0;
827     }
828
829     if (!rc) {
830         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
831     } else {
832         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
833     }
834
835     return 0;
836 }
837
838 int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
839     FILE *fp = fopen("/proc/net/dev", "r");
840     if (!fp) {
841         LOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
842         return -1;
843     }
844
845     char buffer[512];
846
847     fgets(buffer, sizeof(buffer), fp); // Header 1
848     fgets(buffer, sizeof(buffer), fp); // Header 2
849     while(fgets(buffer, sizeof(buffer), fp)) {
850         buffer[strlen(buffer)-1] = '\0';
851
852         char name[31];
853         unsigned long d;
854         sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
855                 name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
856         char *rxString = strchr(name, ':');
857         *rxString = '\0';
858         rxString++;
859         // when the rx count gets too big it changes from "name: 999" to "name:1000"
860         // and the sscanf munge the two together.  Detect that and fix
861         // note that all the %lu will be off by one and the real tx value will be in d
862         if (*rxString != '\0') {
863             *tx = d;
864             sscanf(rxString, "%20lu", rx);
865         }
866         if (strcmp(name, iface)) {
867             continue;
868         }
869         fclose(fp);
870         return 0;
871     }
872
873     fclose(fp);
874     *rx = 0;
875     *tx = 0;
876     return 0;
877 }
878
879 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
880     NetdCommand("bandwidth") {
881 }
882
883 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
884     char *msg;
885     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
886     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
887     free(msg);
888 }
889
890 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
891     if (!cond) {
892         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
893     } else {
894         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
895     }
896 }
897
898 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
899     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
900 }
901
902 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
903     if (argc < 2) {
904         sendGenericSyntaxError(cli, "<cmds> <args...>");
905         return 0;
906     }
907
908     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
909
910     if (!strcmp(argv[1], "enable")) {
911         int rc = sBandwidthCtrl->enableBandwidthControl();
912         sendGenericOkFail(cli, rc);
913         return 0;
914
915     }
916     if (!strcmp(argv[1], "disable")) {
917         int rc = sBandwidthCtrl->disableBandwidthControl();
918         sendGenericOkFail(cli, rc);
919         return 0;
920
921     }
922     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
923         if (argc != 3) {
924             sendGenericSyntaxError(cli, "removequota <interface>");
925             return 0;
926         }
927         int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
928         sendGenericOkFail(cli, rc);
929         return 0;
930
931     }
932     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
933         int64_t bytes;
934         if (argc != 2) {
935             sendGenericSyntaxError(cli, "getquota");
936             return 0;
937         }
938         int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
939         if (rc) {
940             sendGenericOpFailed(cli, "Failed to get quota");
941             return 0;
942         }
943
944         char *msg;
945         asprintf(&msg, "%lld", bytes);
946         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
947         free(msg);
948         return 0;
949
950     }
951     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
952         int64_t bytes;
953         if (argc != 3) {
954             sendGenericSyntaxError(cli, "getiquota <iface>");
955             return 0;
956         }
957
958         int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
959         if (rc) {
960             sendGenericOpFailed(cli, "Failed to get quota");
961             return 0;
962         }
963         char *msg;
964         asprintf(&msg, "%lld", bytes);
965         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
966         free(msg);
967         return 0;
968
969     }
970     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
971         if (argc != 4) {
972             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
973             return 0;
974         }
975         int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
976         sendGenericOkFail(cli, rc);
977         return 0;
978     }
979     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
980         int rc;
981         if (argc < 4) {
982             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
983             return 0;
984         }
985
986         for (int q = 3; argc >= 4; q++, argc--) {
987             rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
988             if (rc) {
989                 char *msg;
990                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
991                 cli->sendMsg(ResponseCode::OperationFailed,
992                              msg, false);
993                 free(msg);
994                 return 0;
995             }
996         }
997         sendGenericOkFail(cli, rc);
998         return 0;
999
1000     }
1001     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
1002         int rc;
1003         if (argc < 3) {
1004             sendGenericSyntaxError(cli, "removequotas <interface> ...");
1005             return 0;
1006         }
1007
1008         for (int q = 2; argc >= 3; q++, argc--) {
1009             rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
1010             if (rc) {
1011                 char *msg;
1012                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1013                 cli->sendMsg(ResponseCode::OperationFailed,
1014                              msg, false);
1015                 free(msg);
1016                 return 0;
1017             }
1018         }
1019         sendGenericOkFail(cli, rc);
1020         return 0;
1021
1022     }
1023     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1024         if (argc != 3) {
1025             sendGenericSyntaxError(cli, "removeiquota <interface>");
1026             return 0;
1027         }
1028         int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1029         sendGenericOkFail(cli, rc);
1030         return 0;
1031
1032     }
1033     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1034         if (argc != 4) {
1035             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1036             return 0;
1037         }
1038         int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1039         sendGenericOkFail(cli, rc);
1040         return 0;
1041
1042     }
1043     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1044         if (argc < 3) {
1045             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1046             return 0;
1047         }
1048         int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1049         sendGenericOkFail(cli, rc);
1050         return 0;
1051
1052
1053     }
1054     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1055         if (argc < 3) {
1056             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1057             return 0;
1058         }
1059         int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1060         sendGenericOkFail(cli, rc);
1061         return 0;
1062
1063     }
1064     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1065         if (argc != 3) {
1066             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1067             return 0;
1068         }
1069         int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1070         sendGenericOkFail(cli, rc);
1071         return 0;
1072
1073     }
1074     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1075         if (argc != 4) {
1076             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1077             return 0;
1078         }
1079         /* We ignore the interfaces for now. */
1080         int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1081         sendGenericOkFail(cli, rc);
1082         return 0;
1083
1084     }
1085     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1086         if (argc != 2) {
1087             sendGenericSyntaxError(cli, "removeglobalalert");
1088             return 0;
1089         }
1090         int rc = sBandwidthCtrl->removeGlobalAlert();
1091         sendGenericOkFail(cli, rc);
1092         return 0;
1093
1094     }
1095     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1096         if (argc != 4) {
1097             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1098             return 0;
1099         }
1100         /* We ignore the interfaces for now. */
1101         int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1102         sendGenericOkFail(cli, rc);
1103         return 0;
1104
1105     }
1106     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1107         if (argc != 3) {
1108             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1109             return 0;
1110         }
1111         int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1112         sendGenericOkFail(cli, rc);
1113         return 0;
1114
1115     }
1116     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1117         if (argc != 2) {
1118             sendGenericSyntaxError(cli, "removesharedalert");
1119             return 0;
1120         }
1121         int rc = sBandwidthCtrl->removeSharedAlert();
1122         sendGenericOkFail(cli, rc);
1123         return 0;
1124
1125     }
1126     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1127         if (argc != 4) {
1128             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1129             return 0;
1130         }
1131         int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1132         sendGenericOkFail(cli, rc);
1133         return 0;
1134
1135     }
1136     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1137         if (argc != 3) {
1138             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1139             return 0;
1140         }
1141         int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1142         sendGenericOkFail(cli, rc);
1143         return 0;
1144
1145     }
1146     if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1147         BandwidthController::TetherStats tetherStats;
1148         std::string extraProcessingInfo = "";
1149         if (argc != 4) {
1150             sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
1151             return 0;
1152         }
1153
1154         tetherStats.ifaceIn = argv[2];
1155         tetherStats.ifaceOut = argv[3];
1156         int rc = sBandwidthCtrl->getTetherStats(tetherStats, extraProcessingInfo);
1157         if (rc) {
1158                 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1159                 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1160             return 0;
1161         }
1162
1163         char *msg = tetherStats.getStatsLine();
1164         cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
1165         free(msg);
1166         return 0;
1167
1168     }
1169
1170     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1171     return 0;
1172 }