CommandListener.cpp revision fa6f46d3370ae5475fc3bc8273bbe04ee7348d60
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
26#include <linux/if.h>
27
28#define LOG_TAG "CommandListener"
29#include <cutils/log.h>
30
31#include <sysutils/SocketClient.h>
32
33#include "CommandListener.h"
34#include "ResponseCode.h"
35#include "ThrottleController.h"
36#include "BandwidthController.h"
37
38
39extern "C" int ifc_init(void);
40extern "C" int ifc_close(void);
41extern "C" int ifc_get_hwaddr(const char *name, void *ptr);
42extern "C" int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags);
43extern "C" int ifc_get_addr(const char *name, in_addr_t *addr);
44extern "C" int ifc_set_addr(const char *name, in_addr_t addr);
45extern "C" int ifc_set_prefixLength(const char *name, int prefixLength);
46extern "C" int ifc_up(const char *name);
47extern "C" int ifc_down(const char *name);
48extern "C" int ifc_add_route(const char *name, const char *dst, int prefix_length, const char *gw);
49extern "C" int ifc_remove_route(const char *name, const char *dst, int p_length, const char *gw);
50
51TetherController *CommandListener::sTetherCtrl = NULL;
52NatController *CommandListener::sNatCtrl = NULL;
53PppController *CommandListener::sPppCtrl = NULL;
54PanController *CommandListener::sPanCtrl = NULL;
55SoftapController *CommandListener::sSoftapCtrl = NULL;
56BandwidthController * CommandListener::sBandwidthCtrl = NULL;
57
58CommandListener::CommandListener() :
59                 FrameworkListener("netd") {
60    registerCmd(new InterfaceCmd());
61    registerCmd(new IpFwdCmd());
62    registerCmd(new TetherCmd());
63    registerCmd(new NatCmd());
64    registerCmd(new ListTtysCmd());
65    registerCmd(new PppdCmd());
66    registerCmd(new PanCmd());
67    registerCmd(new SoftapCmd());
68    registerCmd(new BandwidthControlCmd());
69
70    if (!sTetherCtrl)
71        sTetherCtrl = new TetherController();
72    if (!sNatCtrl)
73        sNatCtrl = new NatController();
74    if (!sPppCtrl)
75        sPppCtrl = new PppController();
76    if (!sPanCtrl)
77        sPanCtrl = new PanController();
78    if (!sSoftapCtrl)
79        sSoftapCtrl = new SoftapController();
80    if (!sBandwidthCtrl)
81        sBandwidthCtrl = new BandwidthController();
82}
83
84CommandListener::InterfaceCmd::InterfaceCmd() :
85                 NetdCommand("interface") {
86}
87
88int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
89                                                      int argc, char **argv) {
90    if (argc < 2) {
91        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
92        return 0;
93    }
94
95    if (!strcmp(argv[1], "list")) {
96        DIR *d;
97        struct dirent *de;
98
99        if (!(d = opendir("/sys/class/net"))) {
100            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
101            return 0;
102        }
103
104        while((de = readdir(d))) {
105            if (de->d_name[0] == '.')
106                continue;
107            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
108        }
109        closedir(d);
110        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
111        return 0;
112    } else if (!strcmp(argv[1], "readrxcounter")) {
113        if (argc != 3) {
114            cli->sendMsg(ResponseCode::CommandSyntaxError,
115                    "Usage: interface readrxcounter <interface>", false);
116            return 0;
117        }
118        unsigned long rx = 0, tx = 0;
119        if (readInterfaceCounters(argv[2], &rx, &tx)) {
120            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
121            return 0;
122        }
123
124        char *msg;
125        asprintf(&msg, "%lu", rx);
126        cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
127        free(msg);
128
129        return 0;
130    } else if (!strcmp(argv[1], "readtxcounter")) {
131        if (argc != 3) {
132            cli->sendMsg(ResponseCode::CommandSyntaxError,
133                    "Usage: interface readtxcounter <interface>", false);
134            return 0;
135        }
136        unsigned long rx = 0, tx = 0;
137        if (readInterfaceCounters(argv[2], &rx, &tx)) {
138            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
139            return 0;
140        }
141
142        char *msg = NULL;
143        asprintf(&msg, "%lu", tx);
144        cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
145        free(msg);
146        return 0;
147    } else if (!strcmp(argv[1], "getthrottle")) {
148        if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
149            cli->sendMsg(ResponseCode::CommandSyntaxError,
150                    "Usage: interface getthrottle <interface> <rx|tx>", false);
151            return 0;
152        }
153        int val = 0;
154        int rc = 0;
155        int voldRc = ResponseCode::InterfaceRxThrottleResult;
156
157        if (!strcmp(argv[3], "rx")) {
158            rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
159        } else {
160            rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
161            voldRc = ResponseCode::InterfaceTxThrottleResult;
162        }
163        if (rc) {
164            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
165        } else {
166            char *msg = NULL;
167            asprintf(&msg, "%u", val);
168            cli->sendMsg(voldRc, msg, false);
169            free(msg);
170            return 0;
171        }
172        return 0;
173    } else if (!strcmp(argv[1], "setthrottle")) {
174        if (argc != 5) {
175            cli->sendMsg(ResponseCode::CommandSyntaxError,
176                    "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
177            return 0;
178        }
179        if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
180            cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
181        } else {
182            cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
183        }
184        return 0;
185    } else {
186        /*
187         * These commands take a minimum of 3 arguments
188         */
189        if (argc < 3) {
190            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
191            return 0;
192        }
193
194        if (!strcmp(argv[1], "route")) {
195            int prefix_length = 0;
196            if (argc < 7) {
197                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
198                return 0;
199            }
200            if (sscanf(argv[5], "%d", &prefix_length) != 1) {
201                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
202                return 0;
203            }
204            if (!strcmp(argv[2], "add")) {
205                if (ifc_add_route(argv[3], argv[4], prefix_length, argv[6])) {
206                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to add route", true);
207                } else {
208                    cli->sendMsg(ResponseCode::CommandOkay, "Route added", false);
209                }
210            } else if (!strcmp(argv[2], "remove")) {
211                if (ifc_remove_route(argv[3], argv[4], prefix_length, argv[6])) {
212                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove route", true);
213                } else {
214                    cli->sendMsg(ResponseCode::CommandOkay, "Route removed", false);
215                }
216            } else {
217                cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
218            }
219            return 0;
220        }
221
222        if (!strcmp(argv[1], "getcfg")) {
223            struct in_addr addr;
224            int prefixLength;
225            unsigned char hwaddr[6];
226            unsigned flags = 0;
227
228            ifc_init();
229            memset(hwaddr, 0, sizeof(hwaddr));
230
231            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
232                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
233                ifc_close();
234                return 0;
235            }
236
237            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
238                LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
239            }
240
241            char *addr_s = strdup(inet_ntoa(addr));
242            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
243
244            updown =  (flags & IFF_UP)           ? "up" : "down";
245            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
246            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
247            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
248            running = (flags & IFF_RUNNING)      ? " running" : "";
249            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
250
251            char *flag_s;
252
253            asprintf(&flag_s, "[%s%s%s%s%s%s]", updown, brdcst, loopbk, ppp, running, multi);
254
255            char *msg = NULL;
256            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
257                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
258                     addr_s, prefixLength, flag_s);
259
260            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
261
262            free(addr_s);
263            free(flag_s);
264            free(msg);
265
266            ifc_close();
267            return 0;
268        } else if (!strcmp(argv[1], "setcfg")) {
269            // arglist: iface addr prefixLength [flags]
270            if (argc < 5) {
271                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
272                return 0;
273            }
274            LOGD("Setting iface cfg");
275
276            struct in_addr addr;
277            unsigned flags = 0;
278
279            if (!inet_aton(argv[3], &addr)) {
280                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
281                return 0;
282            }
283
284            ifc_init();
285            if (ifc_set_addr(argv[2], addr.s_addr)) {
286                cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
287                ifc_close();
288                return 0;
289            }
290
291            if (ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
292                cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
293                ifc_close();
294                return 0;
295            }
296
297            /* Process flags */
298            /* read from "[XX" arg to "YY]" arg */
299            bool bStarted = false;
300            for (int i = 5; i < argc; i++) {
301                char *flag = argv[i];
302                if (!bStarted) {
303                    if (*flag == '[') {
304                        flag++;
305                        bStarted = true;
306                    } else {
307                        continue;
308                    }
309                }
310                int len = strlen(flag);
311                if (flag[len-1] == ']') {
312                    i = argc;  // stop after this loop
313                    flag[len-1] = 0;
314                }
315                if (!strcmp(flag, "up")) {
316                    LOGD("Trying to bring up %s", argv[2]);
317                    if (ifc_up(argv[2])) {
318                        LOGE("Error upping interface");
319                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
320                        ifc_close();
321                        return 0;
322                    }
323                } else if (!strcmp(flag, "down")) {
324                    LOGD("Trying to bring down %s", argv[2]);
325                    if (ifc_down(argv[2])) {
326                        LOGE("Error downing interface");
327                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
328                        ifc_close();
329                        return 0;
330                    }
331                } else if (!strcmp(flag, "broadcast")) {
332                    LOGD("broadcast flag ignored");
333                } else if (!strcmp(flag, "multicast")) {
334                    LOGD("multicast flag ignored");
335                } else {
336                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
337                    ifc_close();
338                    return 0;
339                }
340            }
341
342            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
343            ifc_close();
344            return 0;
345        } else if (!strcmp(argv[1], "clearaddrs")) {
346            // arglist: iface
347            unsigned count, addr;
348
349            //IPv4 only right now
350            LOGD("Clearing all IP addresses on %s", argv[2]);
351
352            ifc_init();
353            for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
354                if (ifc_get_addr(argv[2], &addr) < 0)
355                    break;
356                if (addr)
357                    ifc_set_addr(argv[2], 0);
358            }
359            ifc_close();
360            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
361            return 0;
362        } else {
363            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
364            return 0;
365        }
366    }
367    return 0;
368}
369
370
371CommandListener::ListTtysCmd::ListTtysCmd() :
372                 NetdCommand("list_ttys") {
373}
374
375int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
376                                             int argc, char **argv) {
377    TtyCollection *tlist = sPppCtrl->getTtyList();
378    TtyCollection::iterator it;
379
380    for (it = tlist->begin(); it != tlist->end(); ++it) {
381        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
382    }
383
384    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
385    return 0;
386}
387
388CommandListener::IpFwdCmd::IpFwdCmd() :
389                 NetdCommand("ipfwd") {
390}
391
392int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
393                                                      int argc, char **argv) {
394    int rc = 0;
395
396    if (argc < 2) {
397        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
398        return 0;
399    }
400
401    if (!strcmp(argv[1], "status")) {
402        char *tmp = NULL;
403
404        asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
405        cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
406        free(tmp);
407        return 0;
408    } else if (!strcmp(argv[1], "enable")) {
409        rc = sTetherCtrl->setIpFwdEnabled(true);
410    } else if (!strcmp(argv[1], "disable")) {
411        rc = sTetherCtrl->setIpFwdEnabled(false);
412    } else {
413        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
414        return 0;
415    }
416
417    if (!rc) {
418        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
419    } else {
420        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
421    }
422
423    return 0;
424}
425
426CommandListener::TetherCmd::TetherCmd() :
427                 NetdCommand("tether") {
428}
429
430int CommandListener::TetherCmd::runCommand(SocketClient *cli,
431                                                      int argc, char **argv) {
432    int rc = 0;
433
434    if (argc < 2) {
435        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
436        return 0;
437    }
438
439    if (!strcmp(argv[1], "stop")) {
440        rc = sTetherCtrl->stopTethering();
441    } else if (!strcmp(argv[1], "status")) {
442        char *tmp = NULL;
443
444        asprintf(&tmp, "Tethering services %s",
445                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
446        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
447        free(tmp);
448        return 0;
449    } else {
450        /*
451         * These commands take a minimum of 4 arguments
452         */
453        if (argc < 4) {
454            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
455            return 0;
456        }
457
458        if (!strcmp(argv[1], "start")) {
459            if (argc % 2 == 1) {
460                cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
461                return 0;
462            }
463
464            int num_addrs = argc - 2;
465            int arg_index = 2;
466            int array_index = 0;
467            in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
468            while (array_index < num_addrs) {
469                if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
470                    cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
471                    free(addrs);
472                    return 0;
473                }
474            }
475            rc = sTetherCtrl->startTethering(num_addrs, addrs);
476            free(addrs);
477        } else if (!strcmp(argv[1], "interface")) {
478            if (!strcmp(argv[2], "add")) {
479                rc = sTetherCtrl->tetherInterface(argv[3]);
480            } else if (!strcmp(argv[2], "remove")) {
481                rc = sTetherCtrl->untetherInterface(argv[3]);
482            } else if (!strcmp(argv[2], "list")) {
483                InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
484                InterfaceCollection::iterator it;
485
486                for (it = ilist->begin(); it != ilist->end(); ++it) {
487                    cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
488                }
489            } else {
490                cli->sendMsg(ResponseCode::CommandParameterError,
491                             "Unknown tether interface operation", false);
492                return 0;
493            }
494        } else if (!strcmp(argv[1], "dns")) {
495            if (!strcmp(argv[2], "set")) {
496                rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
497            } else if (!strcmp(argv[2], "list")) {
498                NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
499                NetAddressCollection::iterator it;
500
501                for (it = dlist->begin(); it != dlist->end(); ++it) {
502                    cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
503                }
504            } else {
505                cli->sendMsg(ResponseCode::CommandParameterError,
506                             "Unknown tether interface operation", false);
507                return 0;
508            }
509        } else {
510            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
511            return 0;
512        }
513    }
514
515    if (!rc) {
516        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
517    } else {
518        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
519    }
520
521    return 0;
522}
523
524CommandListener::NatCmd::NatCmd() :
525                 NetdCommand("nat") {
526}
527
528int CommandListener::NatCmd::runCommand(SocketClient *cli,
529                                                      int argc, char **argv) {
530    int rc = 0;
531
532    if (argc < 3) {
533        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
534        return 0;
535    }
536
537    if (!strcmp(argv[1], "enable")) {
538        rc = sNatCtrl->enableNat(argv[2], argv[3]);
539    } else if (!strcmp(argv[1], "disable")) {
540        rc = sNatCtrl->disableNat(argv[2], argv[3]);
541    } else {
542        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
543        return 0;
544    }
545
546    if (!rc) {
547        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
548    } else {
549        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
550    }
551
552    return 0;
553}
554
555CommandListener::PppdCmd::PppdCmd() :
556                 NetdCommand("pppd") {
557}
558
559int CommandListener::PppdCmd::runCommand(SocketClient *cli,
560                                                      int argc, char **argv) {
561    int rc = 0;
562
563    if (argc < 3) {
564        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
565        return 0;
566    }
567
568    if (!strcmp(argv[1], "attach")) {
569        struct in_addr l, r, dns1, dns2;
570
571        memset(&dns1, sizeof(struct in_addr), 0);
572        memset(&dns2, sizeof(struct in_addr), 0);
573
574        if (!inet_aton(argv[3], &l)) {
575            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
576            return 0;
577        }
578        if (!inet_aton(argv[4], &r)) {
579            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
580            return 0;
581        }
582        if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
583            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
584            return 0;
585        }
586        if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
587            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
588            return 0;
589        }
590        rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
591    } else if (!strcmp(argv[1], "detach")) {
592        rc = sPppCtrl->detachPppd(argv[2]);
593    } else {
594        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
595        return 0;
596    }
597
598    if (!rc) {
599        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
600    } else {
601        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
602    }
603
604    return 0;
605}
606
607CommandListener::PanCmd::PanCmd() :
608                 NetdCommand("pan") {
609}
610
611int CommandListener::PanCmd::runCommand(SocketClient *cli,
612                                        int argc, char **argv) {
613    int rc = 0;
614
615    if (argc < 2) {
616        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
617        return 0;
618    }
619
620    if (!strcmp(argv[1], "start")) {
621        rc = sPanCtrl->startPan();
622    } else if (!strcmp(argv[1], "stop")) {
623        rc = sPanCtrl->stopPan();
624    } else if (!strcmp(argv[1], "status")) {
625        char *tmp = NULL;
626
627        asprintf(&tmp, "Pan services %s",
628                 (sPanCtrl->isPanStarted() ? "started" : "stopped"));
629        cli->sendMsg(ResponseCode::PanStatusResult, tmp, false);
630        free(tmp);
631        return 0;
632    } else {
633        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pan cmd", false);
634        return 0;
635    }
636
637    if (!rc) {
638        cli->sendMsg(ResponseCode::CommandOkay, "Pan operation succeeded", false);
639    } else {
640        cli->sendMsg(ResponseCode::OperationFailed, "Pan operation failed", true);
641    }
642
643    return 0;
644}
645
646CommandListener::SoftapCmd::SoftapCmd() :
647                 NetdCommand("softap") {
648}
649
650int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
651                                        int argc, char **argv) {
652    int rc = 0, flag = 0;
653    char *retbuf = NULL;
654
655    if (argc < 2) {
656        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Missing argument", false);
657        return 0;
658    }
659
660    if (!strcmp(argv[1], "start")) {
661        rc = sSoftapCtrl->startDriver(argv[2]);
662    } else if (!strcmp(argv[1], "stop")) {
663        rc = sSoftapCtrl->stopDriver(argv[2]);
664    } else if (!strcmp(argv[1], "startap")) {
665        rc = sSoftapCtrl->startSoftap();
666    } else if (!strcmp(argv[1], "stopap")) {
667        rc = sSoftapCtrl->stopSoftap();
668    } else if (!strcmp(argv[1], "fwreload")) {
669        rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
670    } else if (!strcmp(argv[1], "clients")) {
671        rc = sSoftapCtrl->clientsSoftap(&retbuf);
672        if (!rc) {
673            cli->sendMsg(ResponseCode::CommandOkay, retbuf, false);
674            free(retbuf);
675            return 0;
676        }
677    } else if (!strcmp(argv[1], "status")) {
678        asprintf(&retbuf, "Softap service %s",
679                 (sSoftapCtrl->isSoftapStarted() ? "started" : "stopped"));
680        cli->sendMsg(ResponseCode::SoftapStatusResult, retbuf, false);
681        free(retbuf);
682        return 0;
683    } else if (!strcmp(argv[1], "set")) {
684        rc = sSoftapCtrl->setSoftap(argc, argv);
685    } else {
686        cli->sendMsg(ResponseCode::CommandSyntaxError, "Softap Unknown cmd", false);
687        return 0;
688    }
689
690    if (!rc) {
691        cli->sendMsg(ResponseCode::CommandOkay, "Softap operation succeeded", false);
692    } else {
693        cli->sendMsg(ResponseCode::OperationFailed, "Softap operation failed", true);
694    }
695
696    return 0;
697}
698
699int CommandListener::readInterfaceCounters(const char *iface, unsigned long *rx, unsigned long *tx) {
700    FILE *fp = fopen("/proc/net/dev", "r");
701    if (!fp) {
702        LOGE("Failed to open /proc/net/dev (%s)", strerror(errno));
703        return -1;
704    }
705
706    char buffer[512];
707
708    fgets(buffer, sizeof(buffer), fp); // Header 1
709    fgets(buffer, sizeof(buffer), fp); // Header 2
710    while(fgets(buffer, sizeof(buffer), fp)) {
711        buffer[strlen(buffer)-1] = '\0';
712
713        char name[31];
714        unsigned long d;
715        sscanf(buffer, "%30s %lu %lu %lu %lu %lu %lu %lu %lu %lu",
716                name, rx, &d, &d, &d, &d, &d, &d, &d, tx);
717        char *rxString = strchr(name, ':');
718        *rxString = '\0';
719        rxString++;
720        // when the rx count gets too big it changes from "name: 999" to "name:1000"
721        // and the sscanf munge the two together.  Detect that and fix
722        // note that all the %lu will be off by one and the real tx value will be in d
723        if (*rxString != '\0') {
724            *tx = d;
725            sscanf(rxString, "%20lu", rx);
726        }
727        if (strcmp(name, iface)) {
728            continue;
729        }
730        fclose(fp);
731        return 0;
732    }
733
734    fclose(fp);
735    *rx = 0;
736    *tx = 0;
737    return 0;
738}
739
740CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
741    NetdCommand("b") {
742}
743
744int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
745    int rc = 0;
746    LOGD("bwctrlcmd: argc=%d argv[0]=%s", argc, argv[0]);
747    if (argc < 2) {
748        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
749        return 0;
750    }
751
752    if (!strcmp(argv[1], "enable")) {
753        rc = sBandwidthCtrl->enableBandwidthControl();
754    } else if (!strcmp(argv[1], "disable")) {
755        rc = sBandwidthCtrl->disableBandwidthControl();
756    } else if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
757        if (argc != 3) {
758            cli->sendMsg(ResponseCode::CommandSyntaxError,
759                         "Usage: bandwidth removequota <interface>", false);
760            return 0;
761        }
762        rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
763
764    } else if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
765        if (argc != 4) {
766            cli->sendMsg(ResponseCode::CommandSyntaxError,
767                         "Usage: bandwidth setquota <interface> <bytes>", false);
768            return 0;
769        }
770        rc = sBandwidthCtrl->setInterfaceSharedQuota(atoll(argv[3]), argv[2]);
771
772    } else if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
773        if (argc < 4) {
774            cli->sendMsg(ResponseCode::CommandSyntaxError,
775                         "Usage: bandwidth setquotas <bytes> <interface> ...", false);
776            return 0;
777        }
778        /* TODO: rc = sBandwidthCtrl->setInterfaceQuotas(argv[2], argc - 3, argv + 3)); */
779        rc = -1;
780
781    } else if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
782        if (argc < 3) {
783            cli->sendMsg(ResponseCode::CommandSyntaxError,
784                         "Usage: bandwidth addnaughtyapps <appUid> ...", false);
785            return 0;
786        }
787        rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
788
789    } else if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
790        if (argc < 3) {
791            cli->sendMsg(ResponseCode::CommandSyntaxError,
792                         "Usage: bandwidth remnaughtyapps <appUid> ...", false);
793            return 0;
794        }
795        rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
796
797    } else {
798        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
799        return 0;
800    }
801
802    if (!rc) {
803        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
804    } else {
805        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", true);
806    }
807    return 0;
808}
809