• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <resolv_netid.h>
29 #include <resolv_params.h>
30 
31 #define __STDC_FORMAT_MACROS 1
32 #include <inttypes.h>
33 
34 #define LOG_TAG "CommandListener"
35 
36 #include <cutils/log.h>
37 #include <netdutils/Status.h>
38 #include <netdutils/StatusOr.h>
39 #include <netutils/ifc.h>
40 #include <sysutils/SocketClient.h>
41 
42 #include "Controllers.h"
43 #include "CommandListener.h"
44 #include "ResponseCode.h"
45 #include "BandwidthController.h"
46 #include "IdletimerController.h"
47 #include "InterfaceController.h"
48 #include "NetdConstants.h"
49 #include "FirewallController.h"
50 #include "RouteController.h"
51 #include "UidRanges.h"
52 
53 #include <string>
54 #include <vector>
55 
56 namespace android {
57 namespace net {
58 
59 namespace {
60 
61 const unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
62 
stringToNetId(const char * arg)63 unsigned stringToNetId(const char* arg) {
64     if (!strcmp(arg, "local")) {
65         return NetworkController::LOCAL_NET_ID;
66     }
67     // OEM NetIds are "oem1", "oem2", .., "oem50".
68     if (!strncmp(arg, "oem", 3)) {
69         unsigned n = strtoul(arg + 3, NULL, 0);
70         if (1 <= n && n <= NUM_OEM_IDS) {
71             return NetworkController::MIN_OEM_ID + n;
72         }
73         return NETID_UNSET;
74     } else if (!strncmp(arg, "handle", 6)) {
75         unsigned n = netHandleToNetId((net_handle_t)strtoull(arg + 6, NULL, 10));
76         if (NetworkController::MIN_OEM_ID <= n && n <= NetworkController::MAX_OEM_ID) {
77             return n;
78         }
79         return NETID_UNSET;
80     }
81     // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
82     return strtoul(arg, NULL, 0);
83 }
84 
85 class LockingFrameworkCommand : public FrameworkCommand {
86 public:
LockingFrameworkCommand(FrameworkCommand * wrappedCmd,android::RWLock & lock)87     LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
88             FrameworkCommand(wrappedCmd->getCommand()),
89             mWrappedCmd(wrappedCmd),
90             mLock(lock) {}
91 
runCommand(SocketClient * c,int argc,char ** argv)92     int runCommand(SocketClient *c, int argc, char **argv) {
93         android::RWLock::AutoWLock lock(mLock);
94         return mWrappedCmd->runCommand(c, argc, argv);
95     }
96 
97 private:
98     FrameworkCommand *mWrappedCmd;
99     android::RWLock& mLock;
100 };
101 
102 
103 }  // namespace
104 
registerLockingCmd(FrameworkCommand * cmd,android::RWLock & lock)105 void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
106     registerCmd(new LockingFrameworkCommand(cmd, lock));
107 }
108 
CommandListener()109 CommandListener::CommandListener() : FrameworkListener(SOCKET_NAME, true) {
110     registerLockingCmd(new InterfaceCmd());
111     registerLockingCmd(new IpFwdCmd(), gCtls->tetherCtrl.lock);
112     registerLockingCmd(new TetherCmd(), gCtls->tetherCtrl.lock);
113     registerLockingCmd(new NatCmd(), gCtls->tetherCtrl.lock);
114     registerLockingCmd(new ListTtysCmd());
115     registerLockingCmd(new PppdCmd());
116     registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
117     registerLockingCmd(new IdletimerControlCmd());
118     registerLockingCmd(new ResolverCmd());
119     registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
120     registerLockingCmd(new ClatdCmd());
121     registerLockingCmd(new NetworkCommand());
122     registerLockingCmd(new StrictCmd());
123 }
124 
InterfaceCmd()125 CommandListener::InterfaceCmd::InterfaceCmd() :
126                  NetdCommand("interface") {
127 }
128 
runCommand(SocketClient * cli,int argc,char ** argv)129 int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
130                                                       int argc, char **argv) {
131     if (argc < 2) {
132         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
133         return 0;
134     }
135 
136     if (!strcmp(argv[1], "list")) {
137         const auto ifacePairs =
138             InterfaceController::getIfaceList();
139         if (ifacePairs.status() != netdutils::status::ok) {
140             cli->sendMsg(ResponseCode::OperationFailed, "Failed to get interface list", true);
141             return 0;
142         }
143         for (const auto& ifacePair : ifacePairs.value()) {
144             cli->sendMsg(ResponseCode::InterfaceListResult, ifacePair.first.c_str(), false);
145         }
146 
147         cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
148         return 0;
149     } else {
150         /*
151          * These commands take a minimum of 3 arguments
152          */
153         if (argc < 3) {
154             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
155             return 0;
156         }
157 
158         if (!strcmp(argv[1], "getcfg")) {
159             struct in_addr addr;
160             int prefixLength;
161             unsigned char hwaddr[6];
162             unsigned flags = 0;
163 
164             ifc_init();
165             memset(hwaddr, 0, sizeof(hwaddr));
166 
167             if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
168                 cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
169                 ifc_close();
170                 return 0;
171             }
172 
173             if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
174                 ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
175             }
176 
177             char *addr_s = strdup(inet_ntoa(addr));
178             const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
179 
180             updown =  (flags & IFF_UP)           ? "up" : "down";
181             brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
182             loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
183             ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
184             running = (flags & IFF_RUNNING)      ? " running" : "";
185             multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
186 
187             char *flag_s;
188 
189             asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
190 
191             char *msg = NULL;
192             asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
193                      hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
194                      addr_s, prefixLength, flag_s);
195 
196             cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
197 
198             free(addr_s);
199             free(flag_s);
200             free(msg);
201 
202             ifc_close();
203             return 0;
204         } else if (!strcmp(argv[1], "setcfg")) {
205             // arglist: iface [addr prefixLength] flags
206             if (argc < 4) {
207                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
208                 return 0;
209             }
210             ALOGD("Setting iface cfg");
211 
212             struct in_addr addr;
213             int index = 5;
214 
215             ifc_init();
216 
217             if (!inet_aton(argv[3], &addr)) {
218                 // Handle flags only case
219                 index = 3;
220             } else {
221                 if (ifc_set_addr(argv[2], 0)) {
222                     cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
223                     ifc_close();
224                     return 0;
225                 }
226                 if (addr.s_addr != 0) {
227                     if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
228                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
229                         ifc_close();
230                         return 0;
231                     }
232                 }
233             }
234 
235             /* Process flags */
236             for (int i = index; i < argc; i++) {
237                 char *flag = argv[i];
238                 if (!strcmp(flag, "up")) {
239                     ALOGD("Trying to bring up %s", argv[2]);
240                     if (ifc_up(argv[2])) {
241                         ALOGE("Error upping interface");
242                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
243                         ifc_close();
244                         return 0;
245                     }
246                 } else if (!strcmp(flag, "down")) {
247                     ALOGD("Trying to bring down %s", argv[2]);
248                     if (ifc_down(argv[2])) {
249                         ALOGE("Error downing interface");
250                         cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
251                         ifc_close();
252                         return 0;
253                     }
254                 } else if (!strcmp(flag, "broadcast")) {
255                     // currently ignored
256                 } else if (!strcmp(flag, "multicast")) {
257                     // currently ignored
258                 } else if (!strcmp(flag, "running")) {
259                     // currently ignored
260                 } else if (!strcmp(flag, "loopback")) {
261                     // currently ignored
262                 } else if (!strcmp(flag, "point-to-point")) {
263                     // currently ignored
264                 } else {
265                     cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
266                     ifc_close();
267                     return 0;
268                 }
269             }
270 
271             cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
272             ifc_close();
273             return 0;
274         } else if (!strcmp(argv[1], "clearaddrs")) {
275             // arglist: iface
276             ALOGD("Clearing all IP addresses on %s", argv[2]);
277 
278             ifc_clear_addresses(argv[2]);
279 
280             cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
281             return 0;
282         } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
283             if (argc != 4) {
284                 cli->sendMsg(ResponseCode::CommandSyntaxError,
285                         "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
286                         false);
287                 return 0;
288             }
289             int enable = !strncmp(argv[3], "enable", 7);
290             if (InterfaceController::setIPv6PrivacyExtensions(argv[2], enable) == 0) {
291                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
292             } else {
293                 cli->sendMsg(ResponseCode::OperationFailed,
294                         "Failed to set ipv6 privacy extensions", true);
295             }
296             return 0;
297         } else if (!strcmp(argv[1], "ipv6")) {
298             if (argc != 4) {
299                 cli->sendMsg(ResponseCode::CommandSyntaxError,
300                         "Usage: interface ipv6 <interface> <enable|disable>",
301                         false);
302                 return 0;
303             }
304 
305             int enable = !strncmp(argv[3], "enable", 7);
306             if (InterfaceController::setEnableIPv6(argv[2], enable) == 0) {
307                 cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
308             } else {
309                 cli->sendMsg(ResponseCode::OperationFailed,
310                         "Failed to change IPv6 state", true);
311             }
312             return 0;
313         } else if (!strcmp(argv[1], "setmtu")) {
314             if (argc != 4) {
315                 cli->sendMsg(ResponseCode::CommandSyntaxError,
316                         "Usage: interface setmtu <interface> <val>", false);
317                 return 0;
318             }
319             if (InterfaceController::setMtu(argv[2], argv[3]) == 0) {
320                 cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
321             } else {
322                 cli->sendMsg(ResponseCode::OperationFailed,
323                         "Failed to set MTU", true);
324             }
325             return 0;
326         } else {
327             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
328             return 0;
329         }
330     }
331     return 0;
332 }
333 
334 
ListTtysCmd()335 CommandListener::ListTtysCmd::ListTtysCmd() :
336                  NetdCommand("list_ttys") {
337 }
338 
runCommand(SocketClient * cli,int,char **)339 int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
340                                              int /* argc */, char ** /* argv */) {
341     TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
342     TtyCollection::iterator it;
343 
344     for (it = tlist->begin(); it != tlist->end(); ++it) {
345         cli->sendMsg(ResponseCode::TtyListResult, *it, false);
346     }
347 
348     cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
349     return 0;
350 }
351 
IpFwdCmd()352 CommandListener::IpFwdCmd::IpFwdCmd() :
353                  NetdCommand("ipfwd") {
354 }
355 
runCommand(SocketClient * cli,int argc,char ** argv)356 int CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
357     bool matched = false;
358     bool success;
359 
360     if (argc == 2) {
361         //   0     1
362         // ipfwd status
363         if (!strcmp(argv[1], "status")) {
364             char *tmp = NULL;
365 
366             asprintf(&tmp, "Forwarding %s",
367                      ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
368             cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
369             free(tmp);
370             return 0;
371         }
372     } else if (argc == 3) {
373         //  0      1         2
374         // ipfwd enable  <requester>
375         // ipfwd disable <requester>
376         if (!strcmp(argv[1], "enable")) {
377             matched = true;
378             success = gCtls->tetherCtrl.enableForwarding(argv[2]);
379         } else if (!strcmp(argv[1], "disable")) {
380             matched = true;
381             success = gCtls->tetherCtrl.disableForwarding(argv[2]);
382         }
383     } else if (argc == 4) {
384         //  0      1      2     3
385         // ipfwd  add   wlan0 dummy0
386         // ipfwd remove wlan0 dummy0
387         int ret = 0;
388         if (!strcmp(argv[1], "add")) {
389             matched = true;
390             ret = RouteController::enableTethering(argv[2], argv[3]);
391         } else if (!strcmp(argv[1], "remove")) {
392             matched = true;
393             ret = RouteController::disableTethering(argv[2], argv[3]);
394         }
395         success = (ret == 0);
396         errno = -ret;
397     }
398 
399     if (!matched) {
400         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
401         return 0;
402     }
403 
404     if (success) {
405         cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
406     } else {
407         cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
408     }
409     return 0;
410 }
411 
TetherCmd()412 CommandListener::TetherCmd::TetherCmd() :
413                  NetdCommand("tether") {
414 }
415 
runCommand(SocketClient * cli,int argc,char ** argv)416 int CommandListener::TetherCmd::runCommand(SocketClient *cli,
417                                                       int argc, char **argv) {
418     int rc = 0;
419 
420     if (argc < 2) {
421         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
422         return 0;
423     }
424 
425     if (!strcmp(argv[1], "stop")) {
426         rc = gCtls->tetherCtrl.stopTethering();
427     } else if (!strcmp(argv[1], "status")) {
428         char *tmp = NULL;
429 
430         asprintf(&tmp, "Tethering services %s",
431                  (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
432         cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
433         free(tmp);
434         return 0;
435     } else if (argc == 3) {
436         if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
437             for (const auto &ifname : gCtls->tetherCtrl.getTetheredInterfaceList()) {
438                 cli->sendMsg(ResponseCode::TetherInterfaceListResult, ifname.c_str(), false);
439             }
440         } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
441             char netIdStr[UINT32_STRLEN];
442             snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
443             cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
444 
445             for (const auto &fwdr : gCtls->tetherCtrl.getDnsForwarders()) {
446                 cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
447             }
448         }
449     } else {
450         /*
451          * These commands take a minimum of 4 arguments
452          */
453         if (argc < 4) {
454             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
455             return 0;
456         }
457 
458         if (!strcmp(argv[1], "start")) {
459             if (argc % 2 == 1) {
460                 cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
461                 return 0;
462             }
463 
464             const int num_addrs = argc - 2;
465             // TODO: consider moving this validation into TetherController.
466             struct in_addr tmp_addr;
467             for (int arg_index = 2; arg_index < argc; arg_index++) {
468                 if (!inet_aton(argv[arg_index], &tmp_addr)) {
469                     cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
470                     return 0;
471                 }
472             }
473 
474             rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
475         } else if (!strcmp(argv[1], "interface")) {
476             if (!strcmp(argv[2], "add")) {
477                 rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
478             } else if (!strcmp(argv[2], "remove")) {
479                 rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
480             /* else if (!strcmp(argv[2], "list")) handled above */
481             } else {
482                 cli->sendMsg(ResponseCode::CommandParameterError,
483                              "Unknown tether interface operation", false);
484                 return 0;
485             }
486         } else if (!strcmp(argv[1], "dns")) {
487             if (!strcmp(argv[2], "set")) {
488                 if (argc < 5) {
489                     cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
490                     return 0;
491                 }
492                 unsigned netId = stringToNetId(argv[3]);
493                 rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
494             /* else if (!strcmp(argv[2], "list")) handled above */
495             } else {
496                 cli->sendMsg(ResponseCode::CommandParameterError,
497                              "Unknown tether interface operation", false);
498                 return 0;
499             }
500         } else {
501             cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
502             return 0;
503         }
504     }
505 
506     if (!rc) {
507         cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
508     } else {
509         cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
510     }
511 
512     return 0;
513 }
514 
NatCmd()515 CommandListener::NatCmd::NatCmd() :
516                  NetdCommand("nat") {
517 }
518 
runCommand(SocketClient * cli,int argc,char ** argv)519 int CommandListener::NatCmd::runCommand(SocketClient *cli,
520                                                       int argc, char **argv) {
521     int rc = 0;
522 
523     if (argc < 5) {
524         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
525         return 0;
526     }
527 
528     //  0     1       2        3
529     // nat  enable intiface extiface
530     // nat disable intiface extiface
531     if (!strcmp(argv[1], "enable") && argc >= 4) {
532         rc = gCtls->tetherCtrl.enableNat(argv[2], argv[3]);
533         if(!rc) {
534             /* Ignore ifaces for now. */
535             rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
536         }
537     } else if (!strcmp(argv[1], "disable") && argc >= 4) {
538         /* Ignore ifaces for now. */
539         rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
540         rc |= gCtls->tetherCtrl.disableNat(argv[2], argv[3]);
541     } else {
542         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
543         return 0;
544     }
545 
546     if (!rc) {
547         cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
548     } else {
549         cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
550     }
551 
552     return 0;
553 }
554 
PppdCmd()555 CommandListener::PppdCmd::PppdCmd() :
556                  NetdCommand("pppd") {
557 }
558 
runCommand(SocketClient * cli,int argc,char ** argv)559 int CommandListener::PppdCmd::runCommand(SocketClient *cli,
560                                                       int argc, char **argv) {
561     int rc = 0;
562 
563     if (argc < 3) {
564         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
565         return 0;
566     }
567 
568     if (!strcmp(argv[1], "attach")) {
569         struct in_addr l, r, dns1, dns2;
570 
571         memset(&dns1, 0, sizeof(struct in_addr));
572         memset(&dns2, 0, sizeof(struct in_addr));
573 
574         if (!inet_aton(argv[3], &l)) {
575             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
576             return 0;
577         }
578         if (!inet_aton(argv[4], &r)) {
579             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
580             return 0;
581         }
582         if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
583             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
584             return 0;
585         }
586         if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
587             cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
588             return 0;
589         }
590         rc = gCtls->pppCtrl.attachPppd(argv[2], l, r, dns1, dns2);
591     } else if (!strcmp(argv[1], "detach")) {
592         rc = gCtls->pppCtrl.detachPppd(argv[2]);
593     } else {
594         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
595         return 0;
596     }
597 
598     if (!rc) {
599         cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
600     } else {
601         cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
602     }
603 
604     return 0;
605 }
606 
ResolverCmd()607 CommandListener::ResolverCmd::ResolverCmd() :
608         NetdCommand("resolver") {
609 }
610 
runCommand(SocketClient * cli,int argc,char ** margv)611 int CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
612     int rc = 0;
613     const char **argv = const_cast<const char **>(margv);
614 
615     if (argc < 3) {
616         cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
617         return 0;
618     }
619 
620     unsigned netId = stringToNetId(argv[2]);
621     // TODO: Consider making NetworkController.isValidNetwork() public
622     // and making that check here.
623 
624     if (!strcmp(argv[1], "setnetdns")) {
625         if (!parseAndExecuteSetNetDns(netId, argc, argv)) {
626             cli->sendMsg(ResponseCode::CommandSyntaxError,
627                     "Wrong number of or invalid arguments to resolver setnetdns", false);
628             return 0;
629         }
630     } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
631         if (argc == 3) {
632             rc = gCtls->resolverCtrl.clearDnsServers(netId);
633         } else {
634             cli->sendMsg(ResponseCode::CommandSyntaxError,
635                     "Wrong number of arguments to resolver clearnetdns", false);
636             return 0;
637         }
638     } else {
639         cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
640         return 0;
641     }
642 
643     if (!rc) {
644         cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
645     } else {
646         cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
647     }
648 
649     return 0;
650 }
651 
parseAndExecuteSetNetDns(int netId,int argc,const char ** argv)652 bool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
653         const char** argv) {
654     // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
655     // TODO: This code has to be replaced by a Binder call ASAP
656     if (argc < 5) {
657         return false;
658     }
659     int end = argc;
660     __res_params params;
661     const __res_params* paramsPtr = nullptr;
662     if (end > 6 && !strcmp(argv[end - 2], "--params")) {
663         const char* paramsStr = argv[end - 1];
664         end -= 2;
665         if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", &params.sample_validity,
666                 &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
667             return false;
668         }
669         paramsPtr = &params;
670     }
671     return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
672 }
673 
BandwidthControlCmd()674 CommandListener::BandwidthControlCmd::BandwidthControlCmd() :
675     NetdCommand("bandwidth") {
676 }
677 
sendGenericSyntaxError(SocketClient * cli,const char * usageMsg)678 void CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
679     char *msg;
680     asprintf(&msg, "Usage: bandwidth %s", usageMsg);
681     cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
682     free(msg);
683 }
684 
sendGenericOkFail(SocketClient * cli,int cond)685 void CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
686     if (!cond) {
687         cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
688     } else {
689         cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
690     }
691 }
692 
sendGenericOpFailed(SocketClient * cli,const char * errMsg)693 void CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
694     cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
695 }
696 
runCommand(SocketClient * cli,int argc,char ** argv)697 int CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
698     if (argc < 2) {
699         sendGenericSyntaxError(cli, "<cmds> <args...>");
700         return 0;
701     }
702 
703     ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
704 
705     if (!strcmp(argv[1], "enable")) {
706         int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
707         sendGenericOkFail(cli, rc);
708         return 0;
709 
710     }
711     if (!strcmp(argv[1], "disable")) {
712         int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
713         sendGenericOkFail(cli, rc);
714         return 0;
715 
716     }
717     if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
718         if (argc != 3) {
719             sendGenericSyntaxError(cli, "removequota <interface>");
720             return 0;
721         }
722         int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
723         sendGenericOkFail(cli, rc);
724         return 0;
725 
726     }
727     if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
728         int64_t bytes;
729         if (argc != 2) {
730             sendGenericSyntaxError(cli, "getquota");
731             return 0;
732         }
733         int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
734         if (rc) {
735             sendGenericOpFailed(cli, "Failed to get quota");
736             return 0;
737         }
738 
739         char *msg;
740         asprintf(&msg, "%" PRId64, bytes);
741         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
742         free(msg);
743         return 0;
744 
745     }
746     if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
747         int64_t bytes;
748         if (argc != 3) {
749             sendGenericSyntaxError(cli, "getiquota <iface>");
750             return 0;
751         }
752 
753         int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
754         if (rc) {
755             sendGenericOpFailed(cli, "Failed to get quota");
756             return 0;
757         }
758         char *msg;
759         asprintf(&msg, "%" PRId64, bytes);
760         cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
761         free(msg);
762         return 0;
763 
764     }
765     if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
766         if (argc != 4) {
767             sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
768             return 0;
769         }
770         int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
771         sendGenericOkFail(cli, rc);
772         return 0;
773     }
774     if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
775         int rc;
776         if (argc < 4) {
777             sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
778             return 0;
779         }
780 
781         for (int q = 3; argc >= 4; q++, argc--) {
782             rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
783             if (rc) {
784                 char *msg;
785                 asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
786                 cli->sendMsg(ResponseCode::OperationFailed,
787                              msg, false);
788                 free(msg);
789                 return 0;
790             }
791         }
792         sendGenericOkFail(cli, rc);
793         return 0;
794 
795     }
796     if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
797         int rc;
798         if (argc < 3) {
799             sendGenericSyntaxError(cli, "removequotas <interface> ...");
800             return 0;
801         }
802 
803         for (int q = 2; argc >= 3; q++, argc--) {
804             rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
805             if (rc) {
806                 char *msg;
807                 asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
808                 cli->sendMsg(ResponseCode::OperationFailed,
809                              msg, false);
810                 free(msg);
811                 return 0;
812             }
813         }
814         sendGenericOkFail(cli, rc);
815         return 0;
816 
817     }
818     if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
819         if (argc != 3) {
820             sendGenericSyntaxError(cli, "removeiquota <interface>");
821             return 0;
822         }
823         int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
824         sendGenericOkFail(cli, rc);
825         return 0;
826 
827     }
828     if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
829         if (argc != 4) {
830             sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
831             return 0;
832         }
833         int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
834         sendGenericOkFail(cli, rc);
835         return 0;
836 
837     }
838     if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
839         if (argc < 3) {
840             sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
841             return 0;
842         }
843         int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
844         sendGenericOkFail(cli, rc);
845         return 0;
846 
847 
848     }
849     if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
850         if (argc < 3) {
851             sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
852             return 0;
853         }
854         int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
855         sendGenericOkFail(cli, rc);
856         return 0;
857     }
858     if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
859         if (argc < 3) {
860             sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
861             return 0;
862         }
863         int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
864         sendGenericOkFail(cli, rc);
865         return 0;
866     }
867     if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
868         if (argc < 3) {
869             sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
870             return 0;
871         }
872         int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
873         sendGenericOkFail(cli, rc);
874         return 0;
875     }
876     if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
877         if (argc != 3) {
878             sendGenericSyntaxError(cli, "setglobalalert <bytes>");
879             return 0;
880         }
881         int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
882         sendGenericOkFail(cli, rc);
883         return 0;
884     }
885     if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
886         if (argc != 4) {
887             sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
888             return 0;
889         }
890         /* We ignore the interfaces for now. */
891         int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
892         sendGenericOkFail(cli, rc);
893         return 0;
894 
895     }
896     if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
897         if (argc != 2) {
898             sendGenericSyntaxError(cli, "removeglobalalert");
899             return 0;
900         }
901         int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
902         sendGenericOkFail(cli, rc);
903         return 0;
904 
905     }
906     if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
907         if (argc != 4) {
908             sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
909             return 0;
910         }
911         /* We ignore the interfaces for now. */
912         int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
913         sendGenericOkFail(cli, rc);
914         return 0;
915 
916     }
917     if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
918         if (argc != 3) {
919             sendGenericSyntaxError(cli, "setsharedalert <bytes>");
920             return 0;
921         }
922         int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
923         sendGenericOkFail(cli, rc);
924         return 0;
925 
926     }
927     if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
928         if (argc != 2) {
929             sendGenericSyntaxError(cli, "removesharedalert");
930             return 0;
931         }
932         int rc = gCtls->bandwidthCtrl.removeSharedAlert();
933         sendGenericOkFail(cli, rc);
934         return 0;
935 
936     }
937     if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
938         if (argc != 4) {
939             sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
940             return 0;
941         }
942         int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
943         sendGenericOkFail(cli, rc);
944         return 0;
945 
946     }
947     if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
948         if (argc != 3) {
949             sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
950             return 0;
951         }
952         int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
953         sendGenericOkFail(cli, rc);
954         return 0;
955 
956     }
957 
958     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
959     return 0;
960 }
961 
IdletimerControlCmd()962 CommandListener::IdletimerControlCmd::IdletimerControlCmd() :
963     NetdCommand("idletimer") {
964 }
965 
runCommand(SocketClient * cli,int argc,char ** argv)966 int CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
967   // TODO(ashish): Change the error statements
968     if (argc < 2) {
969         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
970         return 0;
971     }
972 
973     ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
974 
975     if (!strcmp(argv[1], "enable")) {
976       if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
977         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
978       } else {
979         cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
980       }
981       return 0;
982 
983     }
984     if (!strcmp(argv[1], "disable")) {
985       if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
986         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
987       } else {
988         cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
989       }
990       return 0;
991     }
992     if (!strcmp(argv[1], "add")) {
993         if (argc != 5) {
994             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
995             return 0;
996         }
997         if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
998                                         argv[2], atoi(argv[3]), argv[4])) {
999           cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
1000         } else {
1001           cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
1002         }
1003         return 0;
1004     }
1005     if (!strcmp(argv[1], "remove")) {
1006         if (argc != 5) {
1007             cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1008             return 0;
1009         }
1010         // ashish: fixme timeout
1011         if (0 != gCtls->idletimerCtrl.removeInterfaceIdletimer(
1012                                         argv[2], atoi(argv[3]), argv[4])) {
1013           cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
1014         } else {
1015           cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
1016         }
1017         return 0;
1018     }
1019 
1020     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
1021     return 0;
1022 }
1023 
FirewallCmd()1024 CommandListener::FirewallCmd::FirewallCmd() :
1025     NetdCommand("firewall") {
1026 }
1027 
sendGenericOkFail(SocketClient * cli,int cond)1028 int CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1029     if (!cond) {
1030         cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1031     } else {
1032         cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1033     }
1034     return 0;
1035 }
1036 
parseRule(const char * arg)1037 FirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1038     if (!strcmp(arg, "allow")) {
1039         return ALLOW;
1040     } else if (!strcmp(arg, "deny")) {
1041         return DENY;
1042     } else {
1043         ALOGE("failed to parse uid rule (%s)", arg);
1044         return ALLOW;
1045     }
1046 }
1047 
parseFirewallType(const char * arg)1048 FirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1049     if (!strcmp(arg, "whitelist")) {
1050         return WHITELIST;
1051     } else if (!strcmp(arg, "blacklist")) {
1052         return BLACKLIST;
1053     } else {
1054         ALOGE("failed to parse firewall type (%s)", arg);
1055         return BLACKLIST;
1056     }
1057 }
1058 
parseChildChain(const char * arg)1059 ChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
1060     if (!strcmp(arg, "dozable")) {
1061         return DOZABLE;
1062     } else if (!strcmp(arg, "standby")) {
1063         return STANDBY;
1064     } else if (!strcmp(arg, "powersave")) {
1065         return POWERSAVE;
1066     } else if (!strcmp(arg, "none")) {
1067         return NONE;
1068     } else {
1069         ALOGE("failed to parse child firewall chain (%s)", arg);
1070         return INVALID_CHAIN;
1071     }
1072 }
1073 
runCommand(SocketClient * cli,int argc,char ** argv)1074 int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1075         char **argv) {
1076     if (argc < 2) {
1077         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1078         return 0;
1079     }
1080 
1081     if (!strcmp(argv[1], "enable")) {
1082         if (argc != 3) {
1083             cli->sendMsg(ResponseCode::CommandSyntaxError,
1084                         "Usage: firewall enable <whitelist|blacklist>", false);
1085             return 0;
1086         }
1087         FirewallType firewallType = parseFirewallType(argv[2]);
1088 
1089         int res = gCtls->firewallCtrl.enableFirewall(firewallType);
1090         return sendGenericOkFail(cli, res);
1091     }
1092     if (!strcmp(argv[1], "disable")) {
1093         int res = gCtls->firewallCtrl.disableFirewall();
1094         return sendGenericOkFail(cli, res);
1095     }
1096     if (!strcmp(argv[1], "is_enabled")) {
1097         int res = gCtls->firewallCtrl.isFirewallEnabled();
1098         return sendGenericOkFail(cli, res);
1099     }
1100 
1101     if (!strcmp(argv[1], "set_interface_rule")) {
1102         if (argc != 4) {
1103             cli->sendMsg(ResponseCode::CommandSyntaxError,
1104                          "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1105             return 0;
1106         }
1107 
1108         const char* iface = argv[2];
1109         FirewallRule rule = parseRule(argv[3]);
1110 
1111         int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
1112         return sendGenericOkFail(cli, res);
1113     }
1114 
1115     if (!strcmp(argv[1], "set_uid_rule")) {
1116         if (argc != 5) {
1117             cli->sendMsg(ResponseCode::CommandSyntaxError,
1118                          "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
1119                          false);
1120             return 0;
1121         }
1122 
1123         ChildChain childChain = parseChildChain(argv[2]);
1124         if (childChain == INVALID_CHAIN) {
1125             cli->sendMsg(ResponseCode::CommandSyntaxError,
1126                          "Invalid chain name. Valid names are: <dozable|standby|none>",
1127                          false);
1128             return 0;
1129         }
1130         int uid = atoi(argv[3]);
1131         FirewallRule rule = parseRule(argv[4]);
1132         int res = gCtls->firewallCtrl.setUidRule(childChain, uid, rule);
1133         return sendGenericOkFail(cli, res);
1134     }
1135 
1136     if (!strcmp(argv[1], "enable_chain")) {
1137         if (argc != 3) {
1138             cli->sendMsg(ResponseCode::CommandSyntaxError,
1139                          "Usage: firewall enable_chain <dozable|standby>",
1140                          false);
1141             return 0;
1142         }
1143 
1144         ChildChain childChain = parseChildChain(argv[2]);
1145         int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
1146         return sendGenericOkFail(cli, res);
1147     }
1148 
1149     if (!strcmp(argv[1], "disable_chain")) {
1150         if (argc != 3) {
1151             cli->sendMsg(ResponseCode::CommandSyntaxError,
1152                          "Usage: firewall disable_chain <dozable|standby>",
1153                          false);
1154             return 0;
1155         }
1156 
1157         ChildChain childChain = parseChildChain(argv[2]);
1158         int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
1159         return sendGenericOkFail(cli, res);
1160     }
1161 
1162     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1163     return 0;
1164 }
1165 
ClatdCmd()1166 CommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
1167 }
1168 
runCommand(SocketClient * cli,int argc,char ** argv)1169 int CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
1170                                                             char **argv) {
1171     int rc = 0;
1172     if (argc < 3) {
1173         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
1174         return 0;
1175     }
1176 
1177     if (!strcmp(argv[1], "stop")) {
1178         rc = gCtls->clatdCtrl.stopClatd(argv[2]);
1179     } else if (!strcmp(argv[1], "status")) {
1180         char *tmp = NULL;
1181         asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
1182                                             "started" : "stopped"));
1183         cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
1184         free(tmp);
1185         return 0;
1186     } else if (!strcmp(argv[1], "start")) {
1187         rc = gCtls->clatdCtrl.startClatd(argv[2]);
1188     } else {
1189         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
1190         return 0;
1191     }
1192 
1193     if (!rc) {
1194         cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
1195     } else {
1196         cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
1197     }
1198 
1199     return 0;
1200 }
1201 
StrictCmd()1202 CommandListener::StrictCmd::StrictCmd() :
1203     NetdCommand("strict") {
1204 }
1205 
sendGenericOkFail(SocketClient * cli,int cond)1206 int CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1207     if (!cond) {
1208         cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1209     } else {
1210         cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1211     }
1212     return 0;
1213 }
1214 
parsePenalty(const char * arg)1215 StrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1216     if (!strcmp(arg, "reject")) {
1217         return REJECT;
1218     } else if (!strcmp(arg, "log")) {
1219         return LOG;
1220     } else if (!strcmp(arg, "accept")) {
1221         return ACCEPT;
1222     } else {
1223         return INVALID;
1224     }
1225 }
1226 
runCommand(SocketClient * cli,int argc,char ** argv)1227 int CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1228         char **argv) {
1229     if (argc < 2) {
1230         cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1231         return 0;
1232     }
1233 
1234     if (!strcmp(argv[1], "enable")) {
1235         int res = gCtls->strictCtrl.enableStrict();
1236         return sendGenericOkFail(cli, res);
1237     }
1238     if (!strcmp(argv[1], "disable")) {
1239         int res = gCtls->strictCtrl.disableStrict();
1240         return sendGenericOkFail(cli, res);
1241     }
1242 
1243     if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1244         if (argc != 4) {
1245             cli->sendMsg(ResponseCode::CommandSyntaxError,
1246                          "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1247                          false);
1248             return 0;
1249         }
1250 
1251         errno = 0;
1252         unsigned long int uid = strtoul(argv[2], NULL, 0);
1253         if (errno || uid > UID_MAX) {
1254             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1255             return 0;
1256         }
1257 
1258         StrictPenalty penalty = parsePenalty(argv[3]);
1259         if (penalty == INVALID) {
1260             cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1261             return 0;
1262         }
1263 
1264         int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
1265         return sendGenericOkFail(cli, res);
1266     }
1267 
1268     cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1269     return 0;
1270 }
1271 
NetworkCommand()1272 CommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
1273 }
1274 
syntaxError(SocketClient * client,const char * message)1275 int CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
1276     client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
1277     return 0;
1278 }
1279 
operationError(SocketClient * client,const char * message,int ret)1280 int CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1281                                                     int ret) {
1282     errno = -ret;
1283     client->sendMsg(ResponseCode::OperationFailed, message, true);
1284     return 0;
1285 }
1286 
success(SocketClient * client)1287 int CommandListener::NetworkCommand::success(SocketClient* client) {
1288     client->sendMsg(ResponseCode::CommandOkay, "success", false);
1289     return 0;
1290 }
1291 
runCommand(SocketClient * client,int argc,char ** argv)1292 int CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1293     if (argc < 2) {
1294         return syntaxError(client, "Missing argument");
1295     }
1296 
1297     //    0      1      2      3      4       5         6            7           8
1298     // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
1299     // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
1300     //
1301     // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1302     if (!strcmp(argv[1], "route")) {
1303         if (argc < 6 || argc > 9) {
1304             return syntaxError(client, "Incorrect number of arguments");
1305         }
1306 
1307         int nextArg = 2;
1308         bool legacy = false;
1309         uid_t uid = 0;
1310         if (!strcmp(argv[nextArg], "legacy")) {
1311             ++nextArg;
1312             legacy = true;
1313             uid = strtoul(argv[nextArg++], NULL, 0);
1314         }
1315 
1316         bool add = false;
1317         if (!strcmp(argv[nextArg], "add")) {
1318             add = true;
1319         } else if (strcmp(argv[nextArg], "remove")) {
1320             return syntaxError(client, "Unknown argument");
1321         }
1322         ++nextArg;
1323 
1324         if (argc < nextArg + 3 || argc > nextArg + 4) {
1325             return syntaxError(client, "Incorrect number of arguments");
1326         }
1327 
1328         unsigned netId = stringToNetId(argv[nextArg++]);
1329         const char* interface = argv[nextArg++];
1330         const char* destination = argv[nextArg++];
1331         const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1332 
1333         int ret;
1334         if (add) {
1335             ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
1336         } else {
1337             ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
1338         }
1339         if (ret) {
1340             return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1341         }
1342 
1343         return success(client);
1344     }
1345 
1346     //    0        1       2       3         4
1347     // network interface  add   <netId> <interface>
1348     // network interface remove <netId> <interface>
1349     if (!strcmp(argv[1], "interface")) {
1350         if (argc != 5) {
1351             return syntaxError(client, "Missing argument");
1352         }
1353         unsigned netId = stringToNetId(argv[3]);
1354         if (!strcmp(argv[2], "add")) {
1355             if (int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, argv[4])) {
1356                 return operationError(client, "addInterfaceToNetwork() failed", ret);
1357             }
1358         } else if (!strcmp(argv[2], "remove")) {
1359             if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
1360                 return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1361             }
1362         } else {
1363             return syntaxError(client, "Unknown argument");
1364         }
1365         return success(client);
1366     }
1367 
1368     //    0      1       2         3
1369     // network create <netId> [permission]
1370     //
1371     //    0      1       2     3     4        5
1372     // network create <netId> vpn <hasDns> <secure>
1373     if (!strcmp(argv[1], "create")) {
1374         if (argc < 3) {
1375             return syntaxError(client, "Missing argument");
1376         }
1377         unsigned netId = stringToNetId(argv[2]);
1378         if (argc == 6 && !strcmp(argv[3], "vpn")) {
1379             bool hasDns = atoi(argv[4]);
1380             bool secure = atoi(argv[5]);
1381             if (int ret = gCtls->netCtrl.createVirtualNetwork(netId, hasDns, secure)) {
1382                 return operationError(client, "createVirtualNetwork() failed", ret);
1383             }
1384         } else if (argc > 4) {
1385             return syntaxError(client, "Unknown trailing argument(s)");
1386         } else {
1387             Permission permission = PERMISSION_NONE;
1388             if (argc == 4) {
1389                 permission = stringToPermission(argv[3]);
1390                 if (permission == PERMISSION_NONE) {
1391                     return syntaxError(client, "Unknown permission");
1392                 }
1393             }
1394             if (int ret = gCtls->netCtrl.createPhysicalNetwork(netId, permission)) {
1395                 return operationError(client, "createPhysicalNetwork() failed", ret);
1396             }
1397         }
1398         return success(client);
1399     }
1400 
1401     //    0       1       2
1402     // network destroy <netId>
1403     if (!strcmp(argv[1], "destroy")) {
1404         if (argc != 3) {
1405             return syntaxError(client, "Incorrect number of arguments");
1406         }
1407         unsigned netId = stringToNetId(argv[2]);
1408         // Both of these functions manage their own locking internally.
1409         if (int ret = gCtls->netCtrl.destroyNetwork(netId)) {
1410             return operationError(client, "destroyNetwork() failed", ret);
1411         }
1412         gCtls->resolverCtrl.clearDnsServers(netId);
1413         return success(client);
1414     }
1415 
1416     //    0       1      2      3
1417     // network default  set  <netId>
1418     // network default clear
1419     if (!strcmp(argv[1], "default")) {
1420         if (argc < 3) {
1421             return syntaxError(client, "Missing argument");
1422         }
1423         unsigned netId = NETID_UNSET;
1424         if (!strcmp(argv[2], "set")) {
1425             if (argc < 4) {
1426                 return syntaxError(client, "Missing netId");
1427             }
1428             netId = stringToNetId(argv[3]);
1429         } else if (strcmp(argv[2], "clear")) {
1430             return syntaxError(client, "Unknown argument");
1431         }
1432         if (int ret = gCtls->netCtrl.setDefaultNetwork(netId)) {
1433             return operationError(client, "setDefaultNetwork() failed", ret);
1434         }
1435         return success(client);
1436     }
1437 
1438     //    0        1         2      3        4          5
1439     // network permission   user   set  <permission>  <uid> ...
1440     // network permission   user  clear    <uid> ...
1441     // network permission network  set  <permission> <netId> ...
1442     // network permission network clear   <netId> ...
1443     if (!strcmp(argv[1], "permission")) {
1444         if (argc < 5) {
1445             return syntaxError(client, "Missing argument");
1446         }
1447         int nextArg = 4;
1448         Permission permission = PERMISSION_NONE;
1449         if (!strcmp(argv[3], "set")) {
1450             permission = stringToPermission(argv[4]);
1451             if (permission == PERMISSION_NONE) {
1452                 return syntaxError(client, "Unknown permission");
1453             }
1454             nextArg = 5;
1455         } else if (strcmp(argv[3], "clear")) {
1456             return syntaxError(client, "Unknown argument");
1457         }
1458         if (nextArg == argc) {
1459             return syntaxError(client, "Missing id");
1460         }
1461 
1462         bool userPermissions = !strcmp(argv[2], "user");
1463         bool networkPermissions = !strcmp(argv[2], "network");
1464         if (!userPermissions && !networkPermissions) {
1465             return syntaxError(client, "Unknown argument");
1466         }
1467 
1468         std::vector<unsigned> ids;
1469         for (; nextArg < argc; ++nextArg) {
1470             if (userPermissions) {
1471                 char* endPtr;
1472                 unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1473                 if (!*argv[nextArg] || *endPtr) {
1474                     return syntaxError(client, "Invalid id");
1475                 }
1476                 ids.push_back(id);
1477             } else {
1478                 // networkPermissions
1479                 ids.push_back(stringToNetId(argv[nextArg]));
1480             }
1481         }
1482         if (userPermissions) {
1483             gCtls->netCtrl.setPermissionForUsers(permission, ids);
1484         } else {
1485             // networkPermissions
1486             if (int ret = gCtls->netCtrl.setPermissionForNetworks(permission, ids)) {
1487                 return operationError(client, "setPermissionForNetworks() failed", ret);
1488             }
1489         }
1490 
1491         return success(client);
1492     }
1493 
1494     //    0      1     2       3           4
1495     // network users  add   <netId> [<uid>[-<uid>]] ...
1496     // network users remove <netId> [<uid>[-<uid>]] ...
1497     if (!strcmp(argv[1], "users")) {
1498         if (argc < 4) {
1499             return syntaxError(client, "Missing argument");
1500         }
1501         unsigned netId = stringToNetId(argv[3]);
1502         UidRanges uidRanges;
1503         if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1504             return syntaxError(client, "Invalid UIDs");
1505         }
1506         if (!strcmp(argv[2], "add")) {
1507             if (int ret = gCtls->netCtrl.addUsersToNetwork(netId, uidRanges)) {
1508                 return operationError(client, "addUsersToNetwork() failed", ret);
1509             }
1510         } else if (!strcmp(argv[2], "remove")) {
1511             if (int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, uidRanges)) {
1512                 return operationError(client, "removeUsersFromNetwork() failed", ret);
1513             }
1514         } else {
1515             return syntaxError(client, "Unknown argument");
1516         }
1517         return success(client);
1518     }
1519 
1520     //    0       1      2     3
1521     // network protect allow <uid> ...
1522     // network protect  deny <uid> ...
1523     if (!strcmp(argv[1], "protect")) {
1524         if (argc < 4) {
1525             return syntaxError(client, "Missing argument");
1526         }
1527         std::vector<uid_t> uids;
1528         for (int i = 3; i < argc; ++i) {
1529             uids.push_back(strtoul(argv[i], NULL, 0));
1530         }
1531         if (!strcmp(argv[2], "allow")) {
1532             gCtls->netCtrl.allowProtect(uids);
1533         } else if (!strcmp(argv[2], "deny")) {
1534             gCtls->netCtrl.denyProtect(uids);
1535         } else {
1536             return syntaxError(client, "Unknown argument");
1537         }
1538         return success(client);
1539     }
1540 
1541     return syntaxError(client, "Unknown argument");
1542 }
1543 
1544 }  // namespace net
1545 }  // namespace android
1546