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