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