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