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