OSDN Git Service

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