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