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 <linux/if.h>
28
29 #define LOG_TAG "CommandListener"
30
31 #include <cutils/log.h>
32 #include <netutils/ifc.h>
33 #include <sysutils/SocketClient.h>
34
35 #include "CommandListener.h"
36 #include "ResponseCode.h"
37 #include "BandwidthController.h"
38 #include "IdletimerController.h"
39 #include "SecondaryTableController.h"
40 #include "oem_iptables_hook.h"
41 #include "NetdConstants.h"
42 #include "FirewallController.h"
43
44 TetherController *CommandListener::sTetherCtrl = NULL;
45 NatController *CommandListener::sNatCtrl = NULL;
46 PppController *CommandListener::sPppCtrl = NULL;
47 SoftapController *CommandListener::sSoftapCtrl = NULL;
48 BandwidthController * CommandListener::sBandwidthCtrl = NULL;
49 IdletimerController * CommandListener::sIdletimerCtrl = NULL;
50 InterfaceController *CommandListener::sInterfaceCtrl = NULL;
51 ResolverController *CommandListener::sResolverCtrl = NULL;
52 SecondaryTableController *CommandListener::sSecondaryTableCtrl = NULL;
53 FirewallController *CommandListener::sFirewallCtrl = NULL;
54 ClatdController *CommandListener::sClatdCtrl = NULL;
55
56 /**
57 * List of module chains to be created, along with explicit ordering. ORDERING
58 * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
59 */
60 static const char* FILTER_INPUT[] = {
61 // Bandwidth should always be early in input chain, to make sure we
62 // correctly count incoming traffic against data plan.
63 BandwidthController::LOCAL_INPUT,
64 FirewallController::LOCAL_INPUT,
65 NULL,
66 };
67
68 static const char* FILTER_FORWARD[] = {
69 OEM_IPTABLES_FILTER_FORWARD,
70 FirewallController::LOCAL_FORWARD,
71 BandwidthController::LOCAL_FORWARD,
72 NatController::LOCAL_FORWARD,
73 NULL,
74 };
75
76 static const char* FILTER_OUTPUT[] = {
77 OEM_IPTABLES_FILTER_OUTPUT,
78 FirewallController::LOCAL_OUTPUT,
79 BandwidthController::LOCAL_OUTPUT,
80 NULL,
81 };
82
83 static const char* RAW_PREROUTING[] = {
84 BandwidthController::LOCAL_RAW_PREROUTING,
85 IdletimerController::LOCAL_RAW_PREROUTING,
86 NULL,
87 };
88
89 static const char* MANGLE_POSTROUTING[] = {
90 BandwidthController::LOCAL_MANGLE_POSTROUTING,
91 IdletimerController::LOCAL_MANGLE_POSTROUTING,
92 SecondaryTableController::LOCAL_MANGLE_POSTROUTING,
93 NULL,
94 };
95
96 static const char* MANGLE_OUTPUT[] = {
97 SecondaryTableController::LOCAL_MANGLE_OUTPUT,
98 NULL,
99 };
100
101 static const char* NAT_PREROUTING[] = {
102 OEM_IPTABLES_NAT_PREROUTING,
103 NULL,
104 };
105
106 static const char* NAT_POSTROUTING[] = {
107 NatController::LOCAL_NAT_POSTROUTING,
108 SecondaryTableController::LOCAL_NAT_POSTROUTING,
109 NULL,
110 };
111
createChildChains(IptablesTarget target,const char * table,const char * parentChain,const char ** childChains)112 static void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
113 const char** childChains) {
114 const char** childChain = childChains;
115 do {
116 // Order is important:
117 // -D to delete any pre-existing jump rule (removes references
118 // that would prevent -X from working)
119 // -F to flush any existing chain
120 // -X to delete any existing chain
121 // -N to create the chain
122 // -A to append the chain to parent
123
124 execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
125 execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
126 execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
127 execIptables(target, "-t", table, "-N", *childChain, NULL);
128 execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
129 } while (*(++childChain) != NULL);
130 }
131
CommandListener(UidMarkMap * map)132 CommandListener::CommandListener(UidMarkMap *map) :
133 FrameworkListener("netd", true) {
134 registerCmd(new InterfaceCmd());
135 registerCmd(new IpFwdCmd());
136 registerCmd(new TetherCmd());
137 registerCmd(new NatCmd());
138 registerCmd(new ListTtysCmd());
139 registerCmd(new PppdCmd());
140 registerCmd(new SoftapCmd());
141 registerCmd(new BandwidthControlCmd());
142 registerCmd(new IdletimerControlCmd());
143 registerCmd(new ResolverCmd());
144 registerCmd(new FirewallCmd());
145 registerCmd(new ClatdCmd());
146
147 if (!sSecondaryTableCtrl)
148 sSecondaryTableCtrl = new SecondaryTableController(map);
149 if (!sTetherCtrl)
150 sTetherCtrl = new TetherController();
151 if (!sNatCtrl)
152 sNatCtrl = new NatController(sSecondaryTableCtrl);
153 if (!sPppCtrl)
154 sPppCtrl = new PppController();
155 if (!sSoftapCtrl)
156 sSoftapCtrl = new SoftapController();
157 if (!sBandwidthCtrl)
158 sBandwidthCtrl = new BandwidthController();
159 if (!sIdletimerCtrl)
160 sIdletimerCtrl = new IdletimerController();
161 if (!sResolverCtrl)
162 sResolverCtrl = new ResolverController();
163 if (!sFirewallCtrl)
164 sFirewallCtrl = new FirewallController();
165 if (!sInterfaceCtrl)
166 sInterfaceCtrl = new InterfaceController();
167 if (!sClatdCtrl)
168 sClatdCtrl = new ClatdController();
169
170 /*
171 * This is the only time we touch top-level chains in iptables; controllers
172 * should only mutate rules inside of their children chains, as created by
173 * the constants above.
174 *
175 * Modules should never ACCEPT packets (except in well-justified cases);
176 * they should instead defer to any remaining modules using RETURN, or
177 * otherwise DROP/REJECT.
178 */
179
180 // Create chains for children modules
181 createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
182 createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
183 createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
184 createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
185 createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
186 createChildChains(V4V6, "mangle", "OUTPUT", MANGLE_OUTPUT);
187 createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
188 createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
189
190 // Let each module setup their child chains
191 setupOemIptablesHook();
192
193 /* When enabled, DROPs all packets except those matching rules. */
194 sFirewallCtrl->setupIptablesHooks();
195
196 /* Does DROPs in FORWARD by default */
197 sNatCtrl->setupIptablesHooks();
198 /*
199 * Does REJECT in INPUT, OUTPUT. Does counting also.
200 * No DROP/REJECT allowed later in netfilter-flow hook order.
201 */
202 sBandwidthCtrl->setupIptablesHooks();
203 /*
204 * Counts in nat: PREROUTING, POSTROUTING.
205 * No DROP/REJECT allowed later in netfilter-flow hook order.
206 */
207 sIdletimerCtrl->setupIptablesHooks();
208
209 sBandwidthCtrl->enableBandwidthControl(false);
210
211 sSecondaryTableCtrl->setupIptablesHooks();
212 }
213
InterfaceCmd()214 CommandListener::InterfaceCmd::InterfaceCmd() :
215 NetdCommand("interface") {
216 }
217
runCommand(SocketClient * cli,int argc,char ** argv)218 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
219 int argc, char **argv) {
220 if (argc < 2) {
221 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
222 return 0;
223 }
224
225 if (!strcmp(argv[1], "list")) {
226 DIR *d;
227 struct dirent *de;
228
229 if (!(d = opendir("/sys/class/net"))) {
230 cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
231 return 0;
232 }
233
234 while((de = readdir(d))) {
235 if (de->d_name[0] == '.')
236 continue;
237 cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
238 }
239 closedir(d);
240 cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
241 return 0;
242 } else if (!strcmp(argv[1], "driver")) {
243 int rc;
244 char *rbuf;
245
246 if (argc < 4) {
247 cli->sendMsg(ResponseCode::CommandSyntaxError,
248 "Usage: interface driver <interface> <cmd> <args>", false);
249 return 0;
250 }
251 rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf);
252 if (rc) {
253 cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true);
254 } else {
255 cli->sendMsg(ResponseCode::CommandOkay, rbuf, false);
256 }
257 return 0;
258 } else {
259 /*
260 * These commands take a minimum of 3 arguments
261 */
262 if (argc < 3) {
263 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
264 return 0;
265 }
266
267 // 0 1 2 3 4 5 6 7
268 // interface route add/remove iface default/secondary dest prefix gateway
269 // interface fwmark rule add/remove iface
270 // interface fwmark route add/remove iface dest prefix
271 // interface fwmark uid add/remove iface uid_start uid_end
272 // interface fwmark exempt add/remove dest
273 // interface fwmark get protect
274 // interface fwmark get mark uid
275 if (!strcmp(argv[1], "fwmark")) {
276 if (!strcmp(argv[2], "rule")) {
277 if (argc < 5) {
278 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
279 return 0;
280 }
281 if (!strcmp(argv[3], "add")) {
282 if (!sSecondaryTableCtrl->addFwmarkRule(argv[4])) {
283 cli->sendMsg(ResponseCode::CommandOkay,
284 "Fwmark rule successfully added", false);
285 } else {
286 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add fwmark rule",
287 true);
288 }
289 } else if (!strcmp(argv[3], "remove")) {
290 if (!sSecondaryTableCtrl->removeFwmarkRule(argv[4])) {
291 cli->sendMsg(ResponseCode::CommandOkay,
292 "Fwmark rule successfully removed", false);
293 } else {
294 cli->sendMsg(ResponseCode::OperationFailed,
295 "Failed to remove fwmark rule", true);
296 }
297 } else {
298 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark rule cmd",
299 false);
300 }
301 return 0;
302 } else if (!strcmp(argv[2], "route")) {
303 if (argc < 7) {
304 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
305 return 0;
306 }
307 if (!strcmp(argv[3], "add")) {
308 if (!sSecondaryTableCtrl->addFwmarkRoute(argv[4], argv[5], atoi(argv[6]))) {
309 cli->sendMsg(ResponseCode::CommandOkay,
310 "Fwmark route successfully added", false);
311 } else {
312 cli->sendMsg(ResponseCode::OperationFailed,
313 "Failed to add fwmark route", true);
314 }
315 } else if (!strcmp(argv[3], "remove")) {
316 if (!sSecondaryTableCtrl->removeFwmarkRoute(argv[4], argv[5],
317 atoi(argv[6]))) {
318 cli->sendMsg(ResponseCode::CommandOkay,
319 "Fwmark route successfully removed", false);
320 } else {
321 cli->sendMsg(ResponseCode::OperationFailed,
322 "Failed to remove fwmark route", true);
323 }
324 } else {
325 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark route cmd",
326 false);
327 }
328 return 0;
329
330 } else if (!strcmp(argv[2], "uid")) {
331 if (argc < 7) {
332 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
333 return 0;
334 }
335 if (!strcmp(argv[3], "add")) {
336 if (!sSecondaryTableCtrl->addUidRule(argv[4], atoi(argv[5]), atoi(argv[6]))) {
337 cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully added",
338 false);
339 } else {
340 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add uid rule", true);
341 }
342 } else if (!strcmp(argv[3], "remove")) {
343 if (!sSecondaryTableCtrl->removeUidRule(argv[4],
344 atoi(argv[5]), atoi(argv[6]))) {
345 cli->sendMsg(ResponseCode::CommandOkay, "uid rule successfully removed",
346 false);
347 } else {
348 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove uid rule",
349 true);
350 }
351 } else {
352 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown uid cmd", false);
353 }
354 return 0;
355 } else if (!strcmp(argv[2], "exempt")) {
356 if (argc < 5) {
357 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
358 return 0;
359 }
360 if (!strcmp(argv[3], "add")) {
361 if (!sSecondaryTableCtrl->addHostExemption(argv[4])) {
362 cli->sendMsg(ResponseCode::CommandOkay, "exemption rule successfully added",
363 false);
364 } else {
365 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add exemption rule",
366 true);
367 }
368 } else if (!strcmp(argv[3], "remove")) {
369 if (!sSecondaryTableCtrl->removeHostExemption(argv[4])) {
370 cli->sendMsg(ResponseCode::CommandOkay,
371 "exemption rule successfully removed", false);
372 } else {
373 cli->sendMsg(ResponseCode::OperationFailed,
374 "Failed to remove exemption rule", true);
375 }
376 } else {
377 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown exemption cmd", false);
378 }
379 return 0;
380 } else if (!strcmp(argv[2], "get")) {
381 if (argc < 4) {
382 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
383 return 0;
384 }
385 if (!strcmp(argv[3], "protect")) {
386 sSecondaryTableCtrl->getProtectMark(cli);
387 return 0;
388 } else if (!strcmp(argv[3], "mark")) {
389 if (argc < 5) {
390 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
391 return 0;
392 }
393 sSecondaryTableCtrl->getUidMark(cli, atoi(argv[4]));
394 return 0;
395 } else {
396 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark get cmd", false);
397 return 0;
398 }
399 } else {
400 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown fwmark cmd", false);
401 return 0;
402 }
403 }
404 if (!strcmp(argv[1], "route")) {
405 int prefix_length = 0;
406 if (argc < 8) {
407 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
408 return 0;
409 }
410 if (sscanf(argv[6], "%d", &prefix_length) != 1) {
411 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
412 return 0;
413 }
414 if (!strcmp(argv[2], "add")) {
415 if (!strcmp(argv[4], "default")) {
416 if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
417 cli->sendMsg(ResponseCode::OperationFailed,
418 "Failed to add route to default table", true);
419 } else {
420 cli->sendMsg(ResponseCode::CommandOkay,
421 "Route added to default table", false);
422 }
423 } else if (!strcmp(argv[4], "secondary")) {
424 return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
425 prefix_length, argv[7]);
426 } else {
427 cli->sendMsg(ResponseCode::CommandParameterError,
428 "Invalid route type, expecting 'default' or 'secondary'", false);
429 return 0;
430 }
431 } else if (!strcmp(argv[2], "remove")) {
432 if (!strcmp(argv[4], "default")) {
433 if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
434 cli->sendMsg(ResponseCode::OperationFailed,
435 "Failed to remove route from default table", true);
436 } else {
437 cli->sendMsg(ResponseCode::CommandOkay,
438 "Route removed from default table", false);
439 }
440 } else if (!strcmp(argv[4], "secondary")) {
441 return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
442 prefix_length, argv[7]);
443 } else {
444 cli->sendMsg(ResponseCode::CommandParameterError,
445 "Invalid route type, expecting 'default' or 'secondary'", false);
446 return 0;
447 }
448 } else {
449 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
450 }
451 return 0;
452 }
453
454 if (!strcmp(argv[1], "getcfg")) {
455 struct in_addr addr;
456 int prefixLength;
457 unsigned char hwaddr[6];
458 unsigned flags = 0;
459
460 ifc_init();
461 memset(hwaddr, 0, sizeof(hwaddr));
462
463 if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
464 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
465 ifc_close();
466 return 0;
467 }
468
469 if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
470 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
471 }
472
473 char *addr_s = strdup(inet_ntoa(addr));
474 const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
475
476 updown = (flags & IFF_UP) ? "up" : "down";
477 brdcst = (flags & IFF_BROADCAST) ? " broadcast" : "";
478 loopbk = (flags & IFF_LOOPBACK) ? " loopback" : "";
479 ppp = (flags & IFF_POINTOPOINT) ? " point-to-point" : "";
480 running = (flags & IFF_RUNNING) ? " running" : "";
481 multi = (flags & IFF_MULTICAST) ? " multicast" : "";
482
483 char *flag_s;
484
485 asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
486
487 char *msg = NULL;
488 asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
489 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
490 addr_s, prefixLength, flag_s);
491
492 cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
493
494 free(addr_s);
495 free(flag_s);
496 free(msg);
497
498 ifc_close();
499 return 0;
500 } else if (!strcmp(argv[1], "setcfg")) {
501 // arglist: iface [addr prefixLength] flags
502 if (argc < 4) {
503 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
504 return 0;
505 }
506 ALOGD("Setting iface cfg");
507
508 struct in_addr addr;
509 unsigned flags = 0;
510 int index = 5;
511
512 ifc_init();
513
514 if (!inet_aton(argv[3], &addr)) {
515 // Handle flags only case
516 index = 3;
517 } else {
518 if (ifc_set_addr(argv[2], addr.s_addr)) {
519 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
520 ifc_close();
521 return 0;
522 }
523
524 // Set prefix length on a non zero address
525 if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
526 cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
527 ifc_close();
528 return 0;
529 }
530 }
531
532 /* Process flags */
533 for (int i = index; i < argc; i++) {
534 char *flag = argv[i];
535 if (!strcmp(flag, "up")) {
536 ALOGD("Trying to bring up %s", argv[2]);
537 if (ifc_up(argv[2])) {
538 ALOGE("Error upping interface");
539 cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
540 ifc_close();
541 return 0;
542 }
543 } else if (!strcmp(flag, "down")) {
544 ALOGD("Trying to bring down %s", argv[2]);
545 if (ifc_down(argv[2])) {
546 ALOGE("Error downing interface");
547 cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
548 ifc_close();
549 return 0;
550 }
551 } else if (!strcmp(flag, "broadcast")) {
552 // currently ignored
553 } else if (!strcmp(flag, "multicast")) {
554 // currently ignored
555 } else if (!strcmp(flag, "running")) {
556 // currently ignored
557 } else if (!strcmp(flag, "loopback")) {
558 // currently ignored
559 } else if (!strcmp(flag, "point-to-point")) {
560 // currently ignored
561 } else {
562 cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
563 ifc_close();
564 return 0;
565 }
566 }
567
568 cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
569 ifc_close();
570 return 0;
571 } else if (!strcmp(argv[1], "clearaddrs")) {
572 // arglist: iface
573 ALOGD("Clearing all IP addresses on %s", argv[2]);
574
575 ifc_clear_addresses(argv[2]);
576
577 cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
578 return 0;
579 } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
580 if (argc != 4) {
581 cli->sendMsg(ResponseCode::CommandSyntaxError,
582 "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
583 false);
584 return 0;
585 }
586 int enable = !strncmp(argv[3], "enable", 7);
587 if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
588 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
589 } else {
590 cli->sendMsg(ResponseCode::OperationFailed,
591 "Failed to set ipv6 privacy extensions", true);
592 }
593 return 0;
594 } else if (!strcmp(argv[1], "ipv6")) {
595 if (argc != 4) {
596 cli->sendMsg(ResponseCode::CommandSyntaxError,
597 "Usage: interface ipv6 <interface> <enable|disable>",
598 false);
599 return 0;
600 }
601
602 int enable = !strncmp(argv[3], "enable", 7);
603 if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
604 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
605 } else {
606 cli->sendMsg(ResponseCode::OperationFailed,
607 "Failed to change IPv6 state", true);
608 }
609 return 0;
610 } else if (!strcmp(argv[1], "getmtu")) {
611 char *msg = NULL;
612 int mtu = 0;
613 if (sInterfaceCtrl->getMtu(argv[2], &mtu) == 0) {
614 asprintf(&msg, "MTU = %d", mtu);
615 cli->sendMsg(ResponseCode::InterfaceGetMtuResult, msg, false);
616 free(msg);
617 } else {
618 cli->sendMsg(ResponseCode::OperationFailed,
619 "Failed to get MTU", true);
620 }
621 return 0;
622 } else if (!strcmp(argv[1], "setmtu")) {
623 if (argc != 4) {
624 cli->sendMsg(ResponseCode::CommandSyntaxError,
625 "Usage: interface setmtu <interface> <val>", false);
626 return 0;
627 }
628 if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
629 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
630 } else {
631 cli->sendMsg(ResponseCode::OperationFailed,
632 "Failed to get MTU", true);
633 }
634 return 0;
635 } else {
636 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
637 return 0;
638 }
639 }
640 return 0;
641 }
642
643
ListTtysCmd()644 CommandListener::ListTtysCmd::ListTtysCmd() :
645 NetdCommand("list_ttys") {
646 }
647
runCommand(SocketClient * cli,int argc,char ** argv)648 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
649 int argc, char **argv) {
650 TtyCollection *tlist = sPppCtrl->getTtyList();
651 TtyCollection::iterator it;
652
653 for (it = tlist->begin(); it != tlist->end(); ++it) {
654 cli->sendMsg(ResponseCode::TtyListResult, *it, false);
655 }
656
657 cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
658 return 0;
659 }
660
IpFwdCmd()661 CommandListener::IpFwdCmd::IpFwdCmd() :
662 NetdCommand("ipfwd") {
663 }
664
runCommand(SocketClient * cli,int argc,char ** argv)665 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
666 int argc, char **argv) {
667 int rc = 0;
668
669 if (argc < 2) {
670 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
671 return 0;
672 }
673
674 if (!strcmp(argv[1], "status")) {
675 char *tmp = NULL;
676
677 asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
678 cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
679 free(tmp);
680 return 0;
681 } else if (!strcmp(argv[1], "enable")) {
682 rc = sTetherCtrl->setIpFwdEnabled(true);
683 } else if (!strcmp(argv[1], "disable")) {
684 rc = sTetherCtrl->setIpFwdEnabled(false);
685 } else {
686 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
687 return 0;
688 }
689
690 if (!rc) {
691 cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
692 } else {
693 cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
694 }
695
696 return 0;
697 }
698
TetherCmd()699 CommandListener::TetherCmd::TetherCmd() :
700 NetdCommand("tether") {
701 }
702
runCommand(SocketClient * cli,int argc,char ** argv)703 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
704 int argc, char **argv) {
705 int rc = 0;
706
707 if (argc < 2) {
708 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
709 return 0;
710 }
711
712 if (!strcmp(argv[1], "stop")) {
713 rc = sTetherCtrl->stopTethering();
714 } else if (!strcmp(argv[1], "status")) {
715 char *tmp = NULL;
716
717 asprintf(&tmp, "Tethering services %s",
718 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
719 cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
720 free(tmp);
721 return 0;
722 } else if (argc == 3) {
723 if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
724 InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
725 InterfaceCollection::iterator it;
726 for (it = ilist->begin(); it != ilist->end(); ++it) {
727 cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
728 }
729 } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
730 NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
731 NetAddressCollection::iterator it;
732
733 for (it = dlist->begin(); it != dlist->end(); ++it) {
734 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
735 }
736 }
737 } else {
738 /*
739 * These commands take a minimum of 4 arguments
740 */
741 if (argc < 4) {
742 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
743 return 0;
744 }
745
746 if (!strcmp(argv[1], "start")) {
747 if (argc % 2 == 1) {
748 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
749 return 0;
750 }
751
752 int num_addrs = argc - 2;
753 int arg_index = 2;
754 int array_index = 0;
755 in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
756 while (array_index < num_addrs) {
757 if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
758 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
759 free(addrs);
760 return 0;
761 }
762 }
763 rc = sTetherCtrl->startTethering(num_addrs, addrs);
764 free(addrs);
765 } else if (!strcmp(argv[1], "interface")) {
766 if (!strcmp(argv[2], "add")) {
767 rc = sTetherCtrl->tetherInterface(argv[3]);
768 } else if (!strcmp(argv[2], "remove")) {
769 rc = sTetherCtrl->untetherInterface(argv[3]);
770 /* else if (!strcmp(argv[2], "list")) handled above */
771 } else {
772 cli->sendMsg(ResponseCode::CommandParameterError,
773 "Unknown tether interface operation", false);
774 return 0;
775 }
776 } else if (!strcmp(argv[1], "dns")) {
777 if (!strcmp(argv[2], "set")) {
778 rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
779 /* else if (!strcmp(argv[2], "list")) handled above */
780 } else {
781 cli->sendMsg(ResponseCode::CommandParameterError,
782 "Unknown tether interface operation", false);
783 return 0;
784 }
785 } else {
786 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
787 return 0;
788 }
789 }
790
791 if (!rc) {
792 cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
793 } else {
794 cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
795 }
796
797 return 0;
798 }
799
NatCmd()800 CommandListener::NatCmd::NatCmd() :
801 NetdCommand("nat") {
802 }
803
runCommand(SocketClient * cli,int argc,char ** argv)804 int CommandListener::NatCmd::runCommand(SocketClient *cli,
805 int argc, char **argv) {
806 int rc = 0;
807
808 if (argc < 5) {
809 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
810 return 0;
811 }
812
813 if (!strcmp(argv[1], "enable")) {
814 rc = sNatCtrl->enableNat(argc, argv);
815 if(!rc) {
816 /* Ignore ifaces for now. */
817 rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
818 }
819 } else if (!strcmp(argv[1], "disable")) {
820 /* Ignore ifaces for now. */
821 rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
822 rc |= sNatCtrl->disableNat(argc, argv);
823 } else {
824 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
825 return 0;
826 }
827
828 if (!rc) {
829 cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
830 } else {
831 cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
832 }
833
834 return 0;
835 }
836
PppdCmd()837 CommandListener::PppdCmd::PppdCmd() :
838 NetdCommand("pppd") {
839 }
840
runCommand(SocketClient * cli,int argc,char ** argv)841 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
842 int argc, char **argv) {
843 int rc = 0;
844
845 if (argc < 3) {
846 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
847 return 0;
848 }
849
850 if (!strcmp(argv[1], "attach")) {
851 struct in_addr l, r, dns1, dns2;
852
853 memset(&dns1, 0, sizeof(struct in_addr));
854 memset(&dns2, 0, sizeof(struct in_addr));
855
856 if (!inet_aton(argv[3], &l)) {
857 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
858 return 0;
859 }
860 if (!inet_aton(argv[4], &r)) {
861 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
862 return 0;
863 }
864 if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
865 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
866 return 0;
867 }
868 if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
869 cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
870 return 0;
871 }
872 rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
873 } else if (!strcmp(argv[1], "detach")) {
874 rc = sPppCtrl->detachPppd(argv[2]);
875 } else {
876 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
877 return 0;
878 }
879
880 if (!rc) {
881 cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
882 } else {
883 cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
884 }
885
886 return 0;
887 }
888
SoftapCmd()889 CommandListener::SoftapCmd::SoftapCmd() :
890 NetdCommand("softap") {
891 }
892
runCommand(SocketClient * cli,int argc,char ** argv)893 int CommandListener::SoftapCmd::runCommand(SocketClient *cli,
894 int argc, char **argv) {
895 int rc = ResponseCode::SoftapStatusResult;
896 int flag = 0;
897 char *retbuf = NULL;
898
899 if (sSoftapCtrl == NULL) {
900 cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
901 return -1;
902 }
903 if (argc < 2) {
904 cli->sendMsg(ResponseCode::CommandSyntaxError,
905 "Missing argument in a SoftAP command", false);
906 return 0;
907 }
908
909 if (!strcmp(argv[1], "startap")) {
910 rc = sSoftapCtrl->startSoftap();
911 } else if (!strcmp(argv[1], "stopap")) {
912 rc = sSoftapCtrl->stopSoftap();
913 } else if (!strcmp(argv[1], "fwreload")) {
914 rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
915 } else if (!strcmp(argv[1], "status")) {
916 asprintf(&retbuf, "Softap service %s running",
917 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
918 cli->sendMsg(rc, retbuf, false);
919 free(retbuf);
920 return 0;
921 } else if (!strcmp(argv[1], "set")) {
922 rc = sSoftapCtrl->setSoftap(argc, argv);
923 } else {
924 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
925 return 0;
926 }
927
928 if (rc >= 400 && rc < 600)
929 cli->sendMsg(rc, "SoftAP command has failed", false);
930 else
931 cli->sendMsg(rc, "Ok", false);
932
933 return 0;
934 }
935
ResolverCmd()936 CommandListener::ResolverCmd::ResolverCmd() :
937 NetdCommand("resolver") {
938 }
939
runCommand(SocketClient * cli,int argc,char ** margv)940 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
941 int rc = 0;
942 struct in_addr addr;
943 const char **argv = const_cast<const char **>(margv);
944
945 if (argc < 2) {
946 cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
947 return 0;
948 }
949
950 if (!strcmp(argv[1], "setdefaultif")) { // "resolver setdefaultif <iface>"
951 if (argc == 3) {
952 rc = sResolverCtrl->setDefaultInterface(argv[2]);
953 } else {
954 cli->sendMsg(ResponseCode::CommandSyntaxError,
955 "Wrong number of arguments to resolver setdefaultif", false);
956 return 0;
957 }
958 } else if (!strcmp(argv[1], "setifdns")) {
959 // "resolver setifdns <iface> <domains> <dns1> <dns2> ..."
960 if (argc >= 5) {
961 rc = sResolverCtrl->setInterfaceDnsServers(argv[2], argv[3], &argv[4], argc - 4);
962 } else {
963 cli->sendMsg(ResponseCode::CommandSyntaxError,
964 "Wrong number of arguments to resolver setifdns", false);
965 return 0;
966 }
967
968 // set the address of the interface to which the name servers
969 // are bound. Required in order to bind to right interface when
970 // doing the dns query.
971 if (!rc) {
972 ifc_init();
973 ifc_get_info(argv[2], &addr.s_addr, NULL, 0);
974
975 rc = sResolverCtrl->setInterfaceAddress(argv[2], &addr);
976 }
977 } else if (!strcmp(argv[1], "flushdefaultif")) { // "resolver flushdefaultif"
978 if (argc == 2) {
979 rc = sResolverCtrl->flushDefaultDnsCache();
980 } else {
981 cli->sendMsg(ResponseCode::CommandSyntaxError,
982 "Wrong number of arguments to resolver flushdefaultif", false);
983 return 0;
984 }
985 } else if (!strcmp(argv[1], "flushif")) { // "resolver flushif <iface>"
986 if (argc == 3) {
987 rc = sResolverCtrl->flushInterfaceDnsCache(argv[2]);
988 } else {
989 cli->sendMsg(ResponseCode::CommandSyntaxError,
990 "Wrong number of arguments to resolver setdefaultif", false);
991 return 0;
992 }
993 } else if (!strcmp(argv[1], "setifaceforpid")) { // resolver setifaceforpid <iface> <pid>
994 if (argc == 4) {
995 rc = sResolverCtrl->setDnsInterfaceForPid(argv[2], atoi(argv[3]));
996 } else {
997 cli->sendMsg(ResponseCode::CommandSyntaxError,
998 "Wrong number of arguments to resolver setifaceforpid", false);
999 return 0;
1000 }
1001 } else if (!strcmp(argv[1], "clearifaceforpid")) { // resolver clearifaceforpid <pid>
1002 if (argc == 3) {
1003 rc = sResolverCtrl->clearDnsInterfaceForPid(atoi(argv[2]));
1004 } else {
1005 cli->sendMsg(ResponseCode::CommandSyntaxError,
1006 "Wrong number of arguments to resolver clearifaceforpid", false);
1007 return 0;
1008 }
1009 } else if (!strcmp(argv[1], "setifaceforuidrange")) { // resolver setifaceforuid <iface> <l> <h>
1010 if (argc == 5) {
1011 rc = sResolverCtrl->setDnsInterfaceForUidRange(argv[2], atoi(argv[3]), atoi(argv[4]));
1012 } else {
1013 cli->sendMsg(ResponseCode::CommandSyntaxError,
1014 "Wrong number of arguments to resolver setifaceforuid", false);
1015 return 0;
1016 }
1017 } else if (!strcmp(argv[1], "clearifaceforuidrange")) {
1018 // resolver clearifaceforuid <if> <l> <h>
1019 if (argc == 5) {
1020 rc = sResolverCtrl->clearDnsInterfaceForUidRange(argv[2], atoi(argv[3]),
1021 atoi(argv[4]));
1022 } else {
1023 cli->sendMsg(ResponseCode::CommandSyntaxError,
1024 "Wrong number of arguments to resolver clearifaceforuid", false);
1025 return 0;
1026 }
1027 } else if (!strcmp(argv[1], "clearifacemapping")) {
1028 if (argc == 2) {
1029 rc = sResolverCtrl->clearDnsInterfaceMappings();
1030 } else {
1031 cli->sendMsg(ResponseCode::CommandSyntaxError,
1032 "Wrong number of arugments to resolver clearifacemapping", false);
1033 }
1034 } else {
1035 cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
1036 return 0;
1037 }
1038
1039 if (!rc) {
1040 cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
1041 } else {
1042 cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
1043 }
1044
1045 return 0;
1046 }
1047
BandwidthControlCmd()1048 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
1049 NetdCommand("bandwidth") {
1050 }
1051
sendGenericSyntaxError(SocketClient * cli,const char * usageMsg)1052 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
1053 char *msg;
1054 asprintf(&msg, "Usage: bandwidth %s", usageMsg);
1055 cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
1056 free(msg);
1057 }
1058
sendGenericOkFail(SocketClient * cli,int cond)1059 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1060 if (!cond) {
1061 cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
1062 } else {
1063 cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
1064 }
1065 }
1066
sendGenericOpFailed(SocketClient * cli,const char * errMsg)1067 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
1068 cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
1069 }
1070
runCommand(SocketClient * cli,int argc,char ** argv)1071 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1072 if (argc < 2) {
1073 sendGenericSyntaxError(cli, "<cmds> <args...>");
1074 return 0;
1075 }
1076
1077 ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1078
1079 if (!strcmp(argv[1], "enable")) {
1080 int rc = sBandwidthCtrl->enableBandwidthControl(true);
1081 sendGenericOkFail(cli, rc);
1082 return 0;
1083
1084 }
1085 if (!strcmp(argv[1], "disable")) {
1086 int rc = sBandwidthCtrl->disableBandwidthControl();
1087 sendGenericOkFail(cli, rc);
1088 return 0;
1089
1090 }
1091 if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
1092 if (argc != 3) {
1093 sendGenericSyntaxError(cli, "removequota <interface>");
1094 return 0;
1095 }
1096 int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
1097 sendGenericOkFail(cli, rc);
1098 return 0;
1099
1100 }
1101 if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
1102 int64_t bytes;
1103 if (argc != 2) {
1104 sendGenericSyntaxError(cli, "getquota");
1105 return 0;
1106 }
1107 int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
1108 if (rc) {
1109 sendGenericOpFailed(cli, "Failed to get quota");
1110 return 0;
1111 }
1112
1113 char *msg;
1114 asprintf(&msg, "%lld", bytes);
1115 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
1116 free(msg);
1117 return 0;
1118
1119 }
1120 if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
1121 int64_t bytes;
1122 if (argc != 3) {
1123 sendGenericSyntaxError(cli, "getiquota <iface>");
1124 return 0;
1125 }
1126
1127 int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
1128 if (rc) {
1129 sendGenericOpFailed(cli, "Failed to get quota");
1130 return 0;
1131 }
1132 char *msg;
1133 asprintf(&msg, "%lld", bytes);
1134 cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
1135 free(msg);
1136 return 0;
1137
1138 }
1139 if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
1140 if (argc != 4) {
1141 sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
1142 return 0;
1143 }
1144 int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
1145 sendGenericOkFail(cli, rc);
1146 return 0;
1147 }
1148 if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
1149 int rc;
1150 if (argc < 4) {
1151 sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
1152 return 0;
1153 }
1154
1155 for (int q = 3; argc >= 4; q++, argc--) {
1156 rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
1157 if (rc) {
1158 char *msg;
1159 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
1160 cli->sendMsg(ResponseCode::OperationFailed,
1161 msg, false);
1162 free(msg);
1163 return 0;
1164 }
1165 }
1166 sendGenericOkFail(cli, rc);
1167 return 0;
1168
1169 }
1170 if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
1171 int rc;
1172 if (argc < 3) {
1173 sendGenericSyntaxError(cli, "removequotas <interface> ...");
1174 return 0;
1175 }
1176
1177 for (int q = 2; argc >= 3; q++, argc--) {
1178 rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
1179 if (rc) {
1180 char *msg;
1181 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
1182 cli->sendMsg(ResponseCode::OperationFailed,
1183 msg, false);
1184 free(msg);
1185 return 0;
1186 }
1187 }
1188 sendGenericOkFail(cli, rc);
1189 return 0;
1190
1191 }
1192 if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
1193 if (argc != 3) {
1194 sendGenericSyntaxError(cli, "removeiquota <interface>");
1195 return 0;
1196 }
1197 int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
1198 sendGenericOkFail(cli, rc);
1199 return 0;
1200
1201 }
1202 if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
1203 if (argc != 4) {
1204 sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
1205 return 0;
1206 }
1207 int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
1208 sendGenericOkFail(cli, rc);
1209 return 0;
1210
1211 }
1212 if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1213 if (argc < 3) {
1214 sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
1215 return 0;
1216 }
1217 int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
1218 sendGenericOkFail(cli, rc);
1219 return 0;
1220
1221
1222 }
1223 if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1224 if (argc < 3) {
1225 sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1226 return 0;
1227 }
1228 int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
1229 sendGenericOkFail(cli, rc);
1230 return 0;
1231 }
1232 if (!strcmp(argv[1], "happybox")) {
1233 if (argc < 3) {
1234 sendGenericSyntaxError(cli, "happybox (enable | disable)");
1235 return 0;
1236 }
1237 if (!strcmp(argv[2], "enable")) {
1238 int rc = sBandwidthCtrl->enableHappyBox();
1239 sendGenericOkFail(cli, rc);
1240 return 0;
1241
1242 }
1243 if (!strcmp(argv[2], "disable")) {
1244 int rc = sBandwidthCtrl->disableHappyBox();
1245 sendGenericOkFail(cli, rc);
1246 return 0;
1247 }
1248 sendGenericSyntaxError(cli, "happybox (enable | disable)");
1249 return 0;
1250 }
1251 if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1252 if (argc < 3) {
1253 sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1254 return 0;
1255 }
1256 int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1257 sendGenericOkFail(cli, rc);
1258 return 0;
1259 }
1260 if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1261 if (argc < 3) {
1262 sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1263 return 0;
1264 }
1265 int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1266 sendGenericOkFail(cli, rc);
1267 return 0;
1268 }
1269 if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
1270 if (argc != 3) {
1271 sendGenericSyntaxError(cli, "setglobalalert <bytes>");
1272 return 0;
1273 }
1274 int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1275 sendGenericOkFail(cli, rc);
1276 return 0;
1277 }
1278 if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1279 if (argc != 4) {
1280 sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1281 return 0;
1282 }
1283 /* We ignore the interfaces for now. */
1284 int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1285 sendGenericOkFail(cli, rc);
1286 return 0;
1287
1288 }
1289 if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
1290 if (argc != 2) {
1291 sendGenericSyntaxError(cli, "removeglobalalert");
1292 return 0;
1293 }
1294 int rc = sBandwidthCtrl->removeGlobalAlert();
1295 sendGenericOkFail(cli, rc);
1296 return 0;
1297
1298 }
1299 if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1300 if (argc != 4) {
1301 sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1302 return 0;
1303 }
1304 /* We ignore the interfaces for now. */
1305 int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1306 sendGenericOkFail(cli, rc);
1307 return 0;
1308
1309 }
1310 if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
1311 if (argc != 3) {
1312 sendGenericSyntaxError(cli, "setsharedalert <bytes>");
1313 return 0;
1314 }
1315 int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1316 sendGenericOkFail(cli, rc);
1317 return 0;
1318
1319 }
1320 if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
1321 if (argc != 2) {
1322 sendGenericSyntaxError(cli, "removesharedalert");
1323 return 0;
1324 }
1325 int rc = sBandwidthCtrl->removeSharedAlert();
1326 sendGenericOkFail(cli, rc);
1327 return 0;
1328
1329 }
1330 if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
1331 if (argc != 4) {
1332 sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
1333 return 0;
1334 }
1335 int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1336 sendGenericOkFail(cli, rc);
1337 return 0;
1338
1339 }
1340 if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
1341 if (argc != 3) {
1342 sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
1343 return 0;
1344 }
1345 int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1346 sendGenericOkFail(cli, rc);
1347 return 0;
1348
1349 }
1350 if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1351 BandwidthController::TetherStats tetherStats;
1352 std::string extraProcessingInfo = "";
1353 if (argc < 2 || argc > 4) {
1354 sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1355 return 0;
1356 }
1357 tetherStats.intIface = argc > 2 ? argv[2] : "";
1358 tetherStats.extIface = argc > 3 ? argv[3] : "";
1359 int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1360 if (rc) {
1361 extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1362 sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1363 return 0;
1364 }
1365 return 0;
1366
1367 }
1368
1369 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
1370 return 0;
1371 }
1372
IdletimerControlCmd()1373 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
1374 NetdCommand("idletimer") {
1375 }
1376
runCommand(SocketClient * cli,int argc,char ** argv)1377 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
1378 // TODO(ashish): Change the error statements
1379 if (argc < 2) {
1380 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1381 return 0;
1382 }
1383
1384 ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
1385
1386 if (!strcmp(argv[1], "enable")) {
1387 if (0 != sIdletimerCtrl->enableIdletimerControl()) {
1388 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1389 } else {
1390 cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
1391 }
1392 return 0;
1393
1394 }
1395 if (!strcmp(argv[1], "disable")) {
1396 if (0 != sIdletimerCtrl->disableIdletimerControl()) {
1397 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1398 } else {
1399 cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
1400 }
1401 return 0;
1402 }
1403 if (!strcmp(argv[1], "add")) {
1404 if (argc != 5) {
1405 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1406 return 0;
1407 }
1408 if(0 != sIdletimerCtrl->addInterfaceIdletimer(
1409 argv[2], atoi(argv[3]), argv[4])) {
1410 cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1411 } else {
1412 cli->sendMsg(ResponseCode::CommandOkay, "Add success", false);
1413 }
1414 return 0;
1415 }
1416 if (!strcmp(argv[1], "remove")) {
1417 if (argc != 5) {
1418 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1419 return 0;
1420 }
1421 // ashish: fixme timeout
1422 if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
1423 argv[2], atoi(argv[3]), argv[4])) {
1424 cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1425 } else {
1426 cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1427 }
1428 return 0;
1429 }
1430
1431 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1432 return 0;
1433 }
1434
FirewallCmd()1435 CommandListener::FirewallCmd::FirewallCmd() :
1436 NetdCommand("firewall") {
1437 }
1438
sendGenericOkFail(SocketClient * cli,int cond)1439 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1440 if (!cond) {
1441 cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1442 } else {
1443 cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1444 }
1445 return 0;
1446 }
1447
parseRule(const char * arg)1448 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1449 if (!strcmp(arg, "allow")) {
1450 return ALLOW;
1451 } else {
1452 return DENY;
1453 }
1454 }
1455
runCommand(SocketClient * cli,int argc,char ** argv)1456 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1457 char **argv) {
1458 if (argc < 2) {
1459 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1460 return 0;
1461 }
1462
1463 if (!strcmp(argv[1], "enable")) {
1464 int res = sFirewallCtrl->enableFirewall();
1465 return sendGenericOkFail(cli, res);
1466 }
1467 if (!strcmp(argv[1], "disable")) {
1468 int res = sFirewallCtrl->disableFirewall();
1469 return sendGenericOkFail(cli, res);
1470 }
1471 if (!strcmp(argv[1], "is_enabled")) {
1472 int res = sFirewallCtrl->isFirewallEnabled();
1473 return sendGenericOkFail(cli, res);
1474 }
1475
1476 if (!strcmp(argv[1], "set_interface_rule")) {
1477 if (argc != 4) {
1478 cli->sendMsg(ResponseCode::CommandSyntaxError,
1479 "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1480 return 0;
1481 }
1482
1483 const char* iface = argv[2];
1484 FirewallRule rule = parseRule(argv[3]);
1485
1486 int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1487 return sendGenericOkFail(cli, res);
1488 }
1489
1490 if (!strcmp(argv[1], "set_egress_source_rule")) {
1491 if (argc != 4) {
1492 cli->sendMsg(ResponseCode::CommandSyntaxError,
1493 "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1494 false);
1495 return 0;
1496 }
1497
1498 const char* addr = argv[2];
1499 FirewallRule rule = parseRule(argv[3]);
1500
1501 int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1502 return sendGenericOkFail(cli, res);
1503 }
1504
1505 if (!strcmp(argv[1], "set_egress_dest_rule")) {
1506 if (argc != 5) {
1507 cli->sendMsg(ResponseCode::CommandSyntaxError,
1508 "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1509 false);
1510 return 0;
1511 }
1512
1513 const char* addr = argv[2];
1514 int port = atoi(argv[3]);
1515 FirewallRule rule = parseRule(argv[4]);
1516
1517 int res = 0;
1518 res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1519 res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1520 return sendGenericOkFail(cli, res);
1521 }
1522
1523 if (!strcmp(argv[1], "set_uid_rule")) {
1524 if (argc != 4) {
1525 cli->sendMsg(ResponseCode::CommandSyntaxError,
1526 "Usage: firewall set_uid_rule <1000> <allow|deny>",
1527 false);
1528 return 0;
1529 }
1530
1531 int uid = atoi(argv[2]);
1532 FirewallRule rule = parseRule(argv[3]);
1533
1534 int res = sFirewallCtrl->setUidRule(uid, rule);
1535 return sendGenericOkFail(cli, res);
1536 }
1537
1538 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1539 return 0;
1540 }
1541
ClatdCmd()1542 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1543 }
1544
runCommand(SocketClient * cli,int argc,char ** argv)1545 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1546 char **argv) {
1547 int rc = 0;
1548 if (argc < 2) {
1549 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1550 return 0;
1551 }
1552
1553 if(!strcmp(argv[1], "stop")) {
1554 rc = sClatdCtrl->stopClatd();
1555 } else if (!strcmp(argv[1], "status")) {
1556 char *tmp = NULL;
1557
1558 asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted() ?
1559 "started" : "stopped"));
1560 cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1561 free(tmp);
1562 return 0;
1563 } else if(!strcmp(argv[1], "start")) {
1564 if (argc < 3) {
1565 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1566 return 0;
1567 }
1568 rc = sClatdCtrl->startClatd(argv[2]);
1569 } else {
1570 cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1571 return 0;
1572 }
1573
1574 if (!rc) {
1575 cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1576 } else {
1577 cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1578 }
1579
1580 return 0;
1581 }
1582