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