CommandListener.cpp revision 47441ce12d8ac4e7f3c3fb1354a3ae50b802c2bd
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        /* Ignore ifaces for now. */
592        rc |= sBandwidthCtrl->removeGlobalAlertInForwardChain();
593    } else {
594        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
595        return 0;
596    }
597
598    if (!rc) {
599        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
600    } else {
601        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
602    }
603
604    return 0;
605}
606
607CommandListener::PppdCmd::PppdCmd() :
608                 NetdCommand("pppd") {
609}
610
611int CommandListener::PppdCmd::runCommand(SocketClient *cli,
612                                                      int argc, char **argv) {
613    int rc = 0;
614
615    if (argc < 3) {
616        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
617        return 0;
618    }
619
620    if (!strcmp(argv[1], "attach")) {
621        struct in_addr l, r, dns1, dns2;
622
623        memset(&dns1, sizeof(struct in_addr), 0);
624        memset(&dns2, sizeof(struct in_addr), 0);
625
626        if (!inet_aton(argv[3], &l)) {
627            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
628            return 0;
629        }
630        if (!inet_aton(argv[4], &r)) {
631            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
632            return 0;
633        }
634        if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
635            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
636            return 0;
637        }
638        if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
639            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
640            return 0;
641        }
642        rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
643    } else if (!strcmp(argv[1], "detach")) {
644        rc = sPppCtrl->detachPppd(argv[2]);
645    } else {
646        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
647        return 0;
648    }
649
650    if (!rc) {
651        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
652    } else {
653        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
654    }
655
656    return 0;
657}
658
659CommandListener::PanCmd::PanCmd() :
660                 NetdCommand("pan") {
661}
662
663int CommandListener::PanCmd::runCommand(SocketClient *cli,
664                                        int argc, char **argv) {
665    int rc = 0;
666
667    if (argc < 2) {
668        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
669        return 0;
670    }
671
672    if (!strcmp(argv[1], "start")) {
673        rc = sPanCtrl->startPan();
674    } else if (!strcmp(argv[1], "stop")) {
675        rc = sPanCtrl->stopPan();
676    } else if (!strcmp(argv[1], "status")) {
677        char *tmp = NULL;
678
679        asprintf(&tmp, "Pan services %s",
680                 (sPanCtrl->isPanStarted() ? "started" : "stopped"));
681        cli->sendMsg(ResponseCode::PanStatusResult, tmp, false);
682        free(tmp);
683        return 0;
684    } else {
685        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false);
686        return 0;
687    }
688
689    if (!rc) {
690        cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false);
691    } else {
692        cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true);
693    }
694
695    return 0;
696}
697
698CommandListener::SoftapCmd::SoftapCmd() :
699                 NetdCommand("softap") {
700}
701
702int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
703                                        int argc, char **argv) {
704    int rc = 0, flag = 0;
705    char *retbuf = NULL;
706
707    if (argc < 2) {
708        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
709        return 0;
710    }
711
712    if (!strcmp(argv[1], "start")) {
713        rc = sSoftapCtrl->startDriver(argv[2]);
714    } else if (!strcmp(argv[1], "stop")) {
715        rc = sSoftapCtrl->stopDriver(argv[2]);
716    } else if (!strcmp(argv[1], "startap")) {
717        rc = sSoftapCtrl->startSoftap();
718    } else if (!strcmp(argv[1], "stopap")) {
719        rc = sSoftapCtrl->stopSoftap();
720    } else if (!strcmp(argv[1], "fwreload")) {
721        rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
722    } else if (!strcmp(argv[1], "clients")) {
723        rc = sSoftapCtrl->clientsSoftap(&retbuf);
724        if (!rc) {
725            cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
726            free(retbuf);
727            return 0;
728        }
729    } else if (!strcmp(argv[1], "status")) {
730        asprintf(&retbuf, "Softap service %s",
731                 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
732        cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
733        free(retbuf);
734        return 0;
735    } else if (!strcmp(argv[1], "set")) {
736        rc = sSoftapCtrl->setSoftap(argc, argv);
737    } else {
738        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
739        return 0;
740    }
741
742    if (!rc) {
743        cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
744    } else {
745        cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
746    }
747
748    return 0;
749}
750
751CommandListener::ResolverCmd::ResolverCmd() :
752        NetdCommand("resolver") {
753}
754
755int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **argv) {
756    int rc = 0;
757    struct in_addr addr;
758
759    if (argc < 2) {
760        cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
761        return 0;
762    }
763
764    if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
765        if (argc == 3) {
766            rc = sResolverCtrl->setDefaultInterface(argv[2]);
767        } else {
768            cli->sendMsg(ResponseCode::CommandSyntaxError,
769                    "Wrong number of arguments to resolver setdefaultif", false);
770            return 0;
771        }
772    } else if (!strcmp(argv[1], "setifdns")) { // "resolver setifdns <iface> <dns1> <dns2> ..."
773        if (argc >= 4) {
774            rc = sResolverCtrl->setInterfaceDnsServers(argv[2], &argv[3], argc - 3);
775        } else {
776            cli->sendMsg(ResponseCode::CommandSyntaxError,
777                    "Wrong number of arguments to resolver setifdns", false);
778            return 0;
779        }
780
781        // set the address of the interface to which the name servers
782        // are bound. Required in order to bind to right interface when
783        // doing the dns query.
784        if (!rc) {
785            ifc_init();
786            ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
787
788            rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
789        }
790    } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
791        if (argc == 2) {
792            rc = sResolverCtrl->flushDefaultDnsCache();
793        } else {
794            cli->sendMsg(ResponseCode::CommandSyntaxError,
795                    "Wrong number of arguments to resolver flushdefaultif", false);
796            return 0;
797        }
798    } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
799        if (argc == 3) {
800            rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
801        } else {
802            cli->sendMsg(ResponseCode::CommandSyntaxError,
803                    "Wrong number of arguments to resolver setdefaultif", false);
804            return 0;
805        }
806    } else {
807        cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
808        return 0;
809    }
810
811    if (!rc) {
812        cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
813    } else {
814        cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
815    }
816
817    return 0;
818}
819
820int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
821    FILE *fp = fopen("/proc/net/dev", "r");
822    if (!fp) {
823        LOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
824        return -1;
825    }
826
827    char buffer[512];
828
829    fgets(buffer, sizeof(buffer), fp); // Header 1
830    fgets(buffer, sizeof(buffer), fp); // Header 2
831    while(fgets(buffer, sizeof(buffer), fp)) {
832        buffer[strlen(buffer)-1] = '\0';
833
834        char name[31];
835        unsigned long d;
836        sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
837                name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
838        char *rxString = strchr(name, ':');
839        *rxString = '\0';
840        rxString++;
841        // when the rx count gets too big it changes from "name: 999" to "name:1000"
842        // and the sscanf munge the two together.  Detect that and fix
843        // note that all the %lu will be off by one and the real tx value will be in d
844        if (*rxString != '\0') {
845            *tx = d;
846            sscanf(rxString, "%20lu", rx);
847        }
848        if (strcmp(name, iface)) {
849            continue;
850        }
851        fclose(fp);
852        return 0;
853    }
854
855    fclose(fp);
856    *rx = 0;
857    *tx = 0;
858    return 0;
859}
860
861CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
862    NetdCommand("bandwidth") {
863}
864
865void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
866    char *msg;
867    asprintf(&msg, "Usage: bandwidth %s", usageMsg);
868    cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
869    free(msg);
870}
871
872void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
873    if (!cond) {
874        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
875    } else {
876        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
877    }
878}
879
880void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
881    cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
882}
883
884int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
885    if (argc < 2) {
886        sendGenericSyntaxError(cli, "<cmds> <args...>");
887        return 0;
888    }
889
890    ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
891
892    if (!strcmp(argv[1], "enable")) {
893        int rc = sBandwidthCtrl->enableBandwidthControl();
894        sendGenericOkFail(cli, rc);
895        return 0;
896
897    }
898    if (!strcmp(argv[1], "disable")) {
899        int rc = sBandwidthCtrl->disableBandwidthControl();
900        sendGenericOkFail(cli, rc);
901        return 0;
902
903    }
904    if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
905        if (argc != 3) {
906            sendGenericSyntaxError(cli, "removequota <interface>");
907            return 0;
908        }
909        int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
910        sendGenericOkFail(cli, rc);
911        return 0;
912
913    }
914    if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
915        int64_t bytes;
916        if (argc != 2) {
917            sendGenericSyntaxError(cli, "getquota");
918            return 0;
919        }
920        int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
921        if (rc) {
922            sendGenericOpFailed(cli, "Failed to get quota");
923            return 0;
924        }
925
926        char *msg;
927        asprintf(&msg, "%lld", bytes);
928        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
929        free(msg);
930        return 0;
931
932    }
933    if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
934        int64_t bytes;
935        if (argc != 3) {
936            sendGenericSyntaxError(cli, "getiquota <iface>");
937            return 0;
938        }
939
940        int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
941        if (rc) {
942            sendGenericOpFailed(cli, "Failed to get quota");
943            return 0;
944        }
945        char *msg;
946        asprintf(&msg, "%lld", bytes);
947        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
948        free(msg);
949        return 0;
950
951    }
952    if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
953        if (argc != 4) {
954            sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
955            return 0;
956        }
957        int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
958        sendGenericOkFail(cli, rc);
959        return 0;
960    }
961    if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
962        int rc;
963        if (argc < 4) {
964            sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
965            return 0;
966        }
967
968        for (int q = 3; argc >= 4; q++, argc--) {
969            rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
970            if (rc) {
971                char *msg;
972                asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
973                cli->sendMsg(ResponseCode::OperationFailed,
974                             msg, false);
975                free(msg);
976                return 0;
977            }
978        }
979        sendGenericOkFail(cli, rc);
980        return 0;
981
982    }
983    if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
984        int rc;
985        if (argc < 3) {
986            sendGenericSyntaxError(cli, "removequotas <interface> ...");
987            return 0;
988        }
989
990        for (int q = 2; argc >= 3; q++, argc--) {
991            rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
992            if (rc) {
993                char *msg;
994                asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
995                cli->sendMsg(ResponseCode::OperationFailed,
996                             msg, false);
997                free(msg);
998                return 0;
999            }
1000        }
1001        sendGenericOkFail(cli, rc);
1002        return 0;
1003
1004    }
1005    if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1006        if (argc != 3) {
1007            sendGenericSyntaxError(cli, "removeiquota <interface>");
1008            return 0;
1009        }
1010        int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1011        sendGenericOkFail(cli, rc);
1012        return 0;
1013
1014    }
1015    if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1016        if (argc != 4) {
1017            sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1018            return 0;
1019        }
1020        int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1021        sendGenericOkFail(cli, rc);
1022        return 0;
1023
1024    }
1025    if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1026        if (argc < 3) {
1027            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1028            return 0;
1029        }
1030        int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1031        sendGenericOkFail(cli, rc);
1032        return 0;
1033
1034
1035    }
1036    if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1037        if (argc < 3) {
1038            sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1039            return 0;
1040        }
1041        int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1042        sendGenericOkFail(cli, rc);
1043        return 0;
1044
1045    }
1046    if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1047        if (argc != 3) {
1048            sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1049            return 0;
1050        }
1051        int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1052        sendGenericOkFail(cli, rc);
1053        return 0;
1054
1055    }
1056    if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1057        if (argc != 4) {
1058            sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1059            return 0;
1060        }
1061        /* We ignore the interfaces for now. */
1062        int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1063        sendGenericOkFail(cli, rc);
1064        return 0;
1065
1066    }
1067    if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1068        if (argc != 2) {
1069            sendGenericSyntaxError(cli, "removeglobalalert");
1070            return 0;
1071        }
1072        int rc = sBandwidthCtrl->removeGlobalAlert();
1073        sendGenericOkFail(cli, rc);
1074        return 0;
1075
1076    }
1077    if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1078        if (argc != 4) {
1079            sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1080            return 0;
1081        }
1082        /* We ignore the interfaces for now. */
1083        int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1084        sendGenericOkFail(cli, rc);
1085        return 0;
1086
1087    }
1088    if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1089        if (argc != 3) {
1090            sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1091            return 0;
1092        }
1093        int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1094        sendGenericOkFail(cli, rc);
1095        return 0;
1096
1097    }
1098    if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1099        if (argc != 2) {
1100            sendGenericSyntaxError(cli, "removesharedalert");
1101            return 0;
1102        }
1103        int rc = sBandwidthCtrl->removeSharedAlert();
1104        sendGenericOkFail(cli, rc);
1105        return 0;
1106
1107    }
1108    if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1109        if (argc != 4) {
1110            sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1111            return 0;
1112        }
1113        int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1114        sendGenericOkFail(cli, rc);
1115        return 0;
1116
1117    }
1118    if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1119        if (argc != 3) {
1120            sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1121            return 0;
1122        }
1123        int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1124        sendGenericOkFail(cli, rc);
1125        return 0;
1126
1127    }
1128    if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1129        BandwidthController::TetherStats tetherStats;
1130        if (argc != 4) {
1131            sendGenericSyntaxError(cli, "gettetherstats <interface0> <interface1>");
1132            return 0;
1133        }
1134
1135        tetherStats.ifaceIn = argv[2];
1136        tetherStats.ifaceOut = argv[3];
1137        int rc = sBandwidthCtrl->getTetherStats(tetherStats);
1138        if (rc) {
1139            sendGenericOpFailed(cli, "Failed to get tethering stats");
1140            return 0;
1141        }
1142
1143        char *msg = tetherStats.getStatsLine();
1144        cli->sendMsg(ResponseCode::TetheringStatsResult, msg, false);
1145        free(msg);
1146        return 0;
1147
1148    }
1149
1150    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1151    return 0;
1152}
1153