1d18304287dbabc7835be771400b85d4ae8b63de6San Mehat/*
2d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Copyright (C) 2008 The Android Open Source Project
3d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
4d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * you may not use this file except in compliance with the License.
6d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * You may obtain a copy of the License at
7d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
8d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
10d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Unless required by applicable law or agreed to in writing, software
11d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * See the License for the specific language governing permissions and
14d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * limitations under the License.
15d18304287dbabc7835be771400b85d4ae8b63de6San Mehat */
16d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
171fb02dfc26e06b83e756ab3538b7ebc2136f535dJP Abgrall// #define LOG_NDEBUG 0
18db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
19d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdlib.h>
20d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/socket.h>
21d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/types.h>
22d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <netinet/in.h>
23d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <arpa/inet.h>
24d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <dirent.h>
25d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <errno.h>
26ff2c0d8c13457e43f0d4bf06d3177271aac104c1Olivier Bailly#include <string.h>
275c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat#include <linux/if.h>
28a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak#include <resolv_netid.h>
2995f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai#include <resolv_params.h>
305c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
312a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#define __STDC_FORMAT_MACROS 1
322a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#include <inttypes.h>
332a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach
34d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#define LOG_TAG "CommandListener"
35d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
361ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti#include <cutils/log.h>
371ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti#include <netutils/ifc.h>
38d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sysutils/SocketClient.h>
39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
401cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai#include "Controllers.h"
41d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "CommandListener.h"
42d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "ResponseCode.h"
434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h"
440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "IdletimerController.h"
450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "oem_iptables_hook.h"
468e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey#include "NetdConstants.h"
47d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include "FirewallController.h"
485c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h"
49b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran#include "UidRanges.h"
505c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <string>
525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <vector>
535c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
541cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imaiusing android::net::gCtls;
551cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai
56379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandrannamespace {
57379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
58bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
59bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran
60ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission stringToPermission(const char* arg) {
61584dbee59ceb7750e22c48371342635aa6a98517Sreeram Ramachandran    if (!strcmp(arg, "NETWORK")) {
62ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        return PERMISSION_NETWORK;
63ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    }
64584dbee59ceb7750e22c48371342635aa6a98517Sreeram Ramachandran    if (!strcmp(arg, "SYSTEM")) {
65ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        return PERMISSION_SYSTEM;
66ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    }
67ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    return PERMISSION_NONE;
68379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}
69379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
7087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandranunsigned stringToNetId(const char* arg) {
7187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(arg, "local")) {
7287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        return NetworkController::LOCAL_NET_ID;
7387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    }
74bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    // OEM NetIds are "oem1", "oem2", .., "oem50".
75bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    if (!strncmp(arg, "oem", 3)) {
76bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        unsigned n = strtoul(arg + 3, NULL, 0);
77bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        if (1 <= n && n <= NUM_OEM_IDS) {
78bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran            return NetworkController::MIN_OEM_ID + n;
79bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        }
80bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        return NETID_UNSET;
81bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    }
8287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
8387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    return strtoul(arg, NULL, 0);
8487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran}
8587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran
86ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitticlass LockingFrameworkCommand : public FrameworkCommand {
87ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colittipublic:
88ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    LockingFrameworkCommand(FrameworkCommand *wrappedCmd, android::RWLock& lock) :
89ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti            FrameworkCommand(wrappedCmd->getCommand()),
90ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti            mWrappedCmd(wrappedCmd),
91ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti            mLock(lock) {}
92ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti
93ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    int runCommand(SocketClient *c, int argc, char **argv) {
94ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti        android::RWLock::AutoWLock lock(mLock);
95ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti        return mWrappedCmd->runCommand(c, argc, argv);
96ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    }
97ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti
98ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colittiprivate:
99ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    FrameworkCommand *mWrappedCmd;
100ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    android::RWLock& mLock;
101ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti};
102ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti
103ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti
104379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}  // namespace
105379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
1068e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey/**
1078e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey * List of module chains to be created, along with explicit ordering. ORDERING
1088e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
1098e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey */
1108e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_INPUT[] = {
111d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        // Bandwidth should always be early in input chain, to make sure we
112d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        // correctly count incoming traffic against data plan.
1138e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_INPUT,
114d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_INPUT,
1158e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1168e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1178e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1188e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_FORWARD[] = {
1198e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_FILTER_FORWARD,
120d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_FORWARD,
1218e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_FORWARD,
1228e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NatController::LOCAL_FORWARD,
1238e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1248e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1258e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1268e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_OUTPUT[] = {
1278e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_FILTER_OUTPUT,
128d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_OUTPUT,
129fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        StrictController::LOCAL_OUTPUT,
1308e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_OUTPUT,
1318e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1328e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1338e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1348e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* RAW_PREROUTING[] = {
1358e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_RAW_PREROUTING,
1365c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai        IdletimerController::LOCAL_RAW_PREROUTING,
1378e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1388e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1398e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1408e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* MANGLE_POSTROUTING[] = {
1418e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_MANGLE_POSTROUTING,
1425c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai        IdletimerController::LOCAL_MANGLE_POSTROUTING,
1439a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker        NULL,
1449a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker};
1459a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
146e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colittistatic const char* MANGLE_FORWARD[] = {
147e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti        NatController::LOCAL_MANGLE_FORWARD,
148e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti        NULL,
149e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti};
150e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti
1518e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* NAT_PREROUTING[] = {
1528e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_NAT_PREROUTING,
1538e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1548e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1558e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1568e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* NAT_POSTROUTING[] = {
1578e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NatController::LOCAL_NAT_POSTROUTING,
1588e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1598e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1608e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1618e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
1628e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        const char** childChains) {
1638e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    const char** childChain = childChains;
1648e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    do {
1658e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // Order is important:
1668e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -D to delete any pre-existing jump rule (removes references
1678e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        //    that would prevent -X from working)
1688e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -F to flush any existing chain
1698e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -X to delete any existing chain
1708e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -N to create the chain
1718e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -A to append the chain to parent
1728e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1738e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
1748e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
1758e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
1768e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptables(target, "-t", table, "-N", *childChain, NULL);
1778e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
1788e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    } while (*(++childChain) != NULL);
1798e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
1808e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
181ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colittivoid CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
182ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    registerCmd(new LockingFrameworkCommand(cmd, lock));
183ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti}
184ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti
185a0efaece8c05370f201efe099a537ceb014c6fdfSzymon JakubczakCommandListener::CommandListener() :
186a8e59f8c50aed3f91dead377b8ae21646978506cRobert Greenwalt                 FrameworkListener("netd", true) {
187e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new InterfaceCmd());
188e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new IpFwdCmd());
189e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new TetherCmd());
190e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new NatCmd());
191e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new ListTtysCmd());
192e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new PppdCmd());
193e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new SoftapCmd());
194dedd271d9961dbe8b99ffa7d54ffd63ac326f866Lorenzo Colitti    registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
195e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new IdletimerControlCmd());
196e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new ResolverCmd());
197ddf2d5bc87fe6de7cae2b73a17dbaf35033565caLorenzo Colitti    registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
198e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new ClatdCmd());
199e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new NetworkCommand());
200e4d626ea35b7a402388b524e2feafc81e6387697Lorenzo Colitti    registerLockingCmd(new StrictCmd());
2019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
2020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2038e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * This is the only time we touch top-level chains in iptables; controllers
2048e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * should only mutate rules inside of their children chains, as created by
2058e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * the constants above.
2068e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     *
2078e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * Modules should never ACCEPT packets (except in well-justified cases);
2088e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * they should instead defer to any remaining modules using RETURN, or
2098e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * otherwise DROP/REJECT.
2100031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2118e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
2128e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    // Create chains for children modules
2138e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
2148e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
2158e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
2168e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
2178e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
218e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti    createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
2198e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
2208e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
2218e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
2228e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    // Let each module setup their child chains
2230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    setupOemIptablesHook();
2248e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
225d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    /* When enabled, DROPs all packets except those matching rules. */
2261cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    gCtls->firewallCtrl.setupIptablesHooks();
227d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
2280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Does DROPs in FORWARD by default */
2291cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    gCtls->natCtrl.setupIptablesHooks();
2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Does REJECT in INPUT, OUTPUT. Does counting also.
2320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * No DROP/REJECT allowed later in netfilter-flow hook order.
2330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2341cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    gCtls->bandwidthCtrl.setupIptablesHooks();
2350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Counts in nat: PREROUTING, POSTROUTING.
2370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * No DROP/REJECT allowed later in netfilter-flow hook order.
2380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2391cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    gCtls->idletimerCtrl.setupIptablesHooks();
2400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2411cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    gCtls->bandwidthCtrl.enableBandwidthControl(false);
2422251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
24387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
244f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
245f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
246d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
247d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
2485c1b8af16dbbc20c89aaca2f93e725e12b16d055San MehatCommandListener::InterfaceCmd::InterfaceCmd() :
2495c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                 NetdCommand("interface") {
250d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
251d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
2525c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehatint CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
253d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
2545c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    if (argc < 2) {
2555c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
2565c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        return 0;
2575c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    }
2585c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2595c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    if (!strcmp(argv[1], "list")) {
2605c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        DIR *d;
2615c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        struct dirent *de;
2625c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2635c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (!(d = opendir("/sys/class/net"))) {
2645c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
2655c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
2665c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
2675c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2685c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        while((de = readdir(d))) {
2695c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            if (de->d_name[0] == '.')
2705c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                continue;
2715c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
2725c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
2735c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        closedir(d);
2745c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
2755c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        return 0;
2765c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    } else {
2775c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        /*
2785c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat         * These commands take a minimum of 3 arguments
2795c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat         */
2805c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (argc < 3) {
2815c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
2825c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
2835c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
284e019b65925217bcc3ad9b662aa3125f0593057afRobert Greenwalt
2855c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (!strcmp(argv[1], "getcfg")) {
2861d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            struct in_addr addr;
2871d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            int prefixLength;
2885c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            unsigned char hwaddr[6];
2895c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            unsigned flags = 0;
2905c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2915c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ifc_init();
2925c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            memset(hwaddr, 0, sizeof(hwaddr));
2935c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2941d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
2955c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
296e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                ifc_close();
2975c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                return 0;
2985c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
2995c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3005c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
3010e76b761a1514d5182675dd7b7d33725f62d6bc5Steve Block                ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
3025c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3035c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3045c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *addr_s = strdup(inet_ntoa(addr));
3055c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
3065c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3075c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            updown =  (flags & IFF_UP)           ? "up" : "down";
3085c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
3095c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
3105c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
3115c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            running = (flags & IFF_RUNNING)      ? " running" : "";
3125c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
3135c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3145c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *flag_s;
3155c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
31631ea0b03afeedd17f703b7a6d1e5c9feb2d6000dJeff Sharkey            asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
3175c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3185c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *msg = NULL;
3191d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
3205c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
3211d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt                     addr_s, prefixLength, flag_s);
3225c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
32301fed783828b592cda3b774deea4099a9e690e3dSan Mehat            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
3245c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3255c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(addr_s);
3265c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(flag_s);
3275c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(msg);
328e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
329e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            ifc_close();
3305c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
3315c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        } else if (!strcmp(argv[1], "setcfg")) {
332778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            // arglist: iface [addr prefixLength] flags
333778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            if (argc < 4) {
3345c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
3355c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                return 0;
3365c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3377b984e3f7e724f8a3547a707210319f3d479f261Steve Block            ALOGD("Setting iface cfg");
3385c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3391d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            struct in_addr addr;
340778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            int index = 5;
3415c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3425c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ifc_init();
3435c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
344778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            if (!inet_aton(argv[3], &addr)) {
345778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                // Handle flags only case
346778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                index = 3;
347778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            } else {
3485e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                if (ifc_set_addr(argv[2], 0)) {
3495e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to clear address", true);
350778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                    ifc_close();
351778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                    return 0;
352778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                }
3535e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                if (addr.s_addr != 0) {
3545e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                    if (ifc_add_address(argv[2], argv[3], atoi(argv[4]))) {
3555e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
3565e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                        ifc_close();
3575e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                        return 0;
3585e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                    }
3595e69c7f6c92678ccbc75e77dbb661d9bdc0dec83Erik Kline                }
3605c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3615c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3625c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            /* Process flags */
363778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            for (int i = index; i < argc; i++) {
364e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                char *flag = argv[i];
365e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                if (!strcmp(flag, "up")) {
3667b984e3f7e724f8a3547a707210319f3d479f261Steve Block                    ALOGD("Trying to bring up %s", argv[2]);
3675c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    if (ifc_up(argv[2])) {
3685ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                        ALOGE("Error upping interface");
3695c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
370e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                        ifc_close();
3715c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        return 0;
3725c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    }
373e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "down")) {
3747b984e3f7e724f8a3547a707210319f3d479f261Steve Block                    ALOGD("Trying to bring down %s", argv[2]);
3755c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    if (ifc_down(argv[2])) {
3765ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                        ALOGE("Error downing interface");
3775c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
378e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                        ifc_close();
3795c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        return 0;
3805c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    }
381e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "broadcast")) {
3827c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
383e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "multicast")) {
3847c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3857c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "running")) {
3867c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3877c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "loopback")) {
3887c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3897c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "point-to-point")) {
3907c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3915c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                } else {
3925c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
393e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                    ifc_close();
3945c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    return 0;
3955c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                }
3965c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
397e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
3985c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
399e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            ifc_close();
400e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            return 0;
401e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff        } else if (!strcmp(argv[1], "clearaddrs")) {
402e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            // arglist: iface
4037b984e3f7e724f8a3547a707210319f3d479f261Steve Block            ALOGD("Clearing all IP addresses on %s", argv[2]);
404e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
4051ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti            ifc_clear_addresses(argv[2]);
4061ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti
407e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
4085c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
40932a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff        } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
41032a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            if (argc != 4) {
41132a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::CommandSyntaxError,
41232a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
41332a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        false);
41432a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                return 0;
41532a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
41670afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            int enable = !strncmp(argv[3], "enable", 7);
4171cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (gCtls->interfaceCtrl.setIPv6PrivacyExtensions(argv[2], enable) == 0) {
41870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
41970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            } else {
42032a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::OperationFailed,
42132a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        "Failed to set ipv6 privacy extensions", true);
42232a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
423c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            return 0;
424c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync        } else if (!strcmp(argv[1], "ipv6")) {
425c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            if (argc != 4) {
426c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                cli->sendMsg(ResponseCode::CommandSyntaxError,
427c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        "Usage: interface ipv6 <interface> <enable|disable>",
428c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        false);
429c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                return 0;
430c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            }
431c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync
43270afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            int enable = !strncmp(argv[3], "enable", 7);
4331cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (gCtls->interfaceCtrl.setEnableIPv6(argv[2], enable) == 0) {
43470afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
43570afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            } else {
43632a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::OperationFailed,
437c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        "Failed to change IPv6 state", true);
43832a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
43932a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            return 0;
4400ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti        } else if (!strcmp(argv[1], "ipv6ndoffload")) {
4410ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            if (argc != 4) {
4420ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                cli->sendMsg(ResponseCode::CommandSyntaxError,
4430ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                        "Usage: interface ipv6ndoffload <interface> <enable|disable>",
4440ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                        false);
4450ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                return 0;
4460ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            }
4470ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            int enable = !strncmp(argv[3], "enable", 7);
4481cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (gCtls->interfaceCtrl.setIPv6NdOffload(argv[2], enable) == 0) {
4490ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 ND offload changed", false);
4500ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            } else {
4510ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                cli->sendMsg(ResponseCode::OperationFailed,
4520ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti                        "Failed to change IPv6 ND offload state", true);
4530ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            }
4540ea8ff87012f6bda41b6d2b4629d4fd0fd6f4794Lorenzo Colitti            return 0;
4556d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt        } else if (!strcmp(argv[1], "setmtu")) {
4566d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            if (argc != 4) {
4576d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::CommandSyntaxError,
4586d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                        "Usage: interface setmtu <interface> <val>", false);
4596d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                return 0;
4606d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            }
4611cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (gCtls->interfaceCtrl.setMtu(argv[2], argv[3]) == 0) {
4626d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
4636d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            } else {
4646d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::OperationFailed,
465a59c928252869242642edfed689902a488a6298fErik Kline                        "Failed to set MTU", true);
4666d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            }
4676d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            return 0;
4685c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        } else {
4695c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
4705c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
4715c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
4725c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    }
473d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
474d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
475d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
4764a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
477d5573d34c8fac49e16b20cf144486125bf940086San MehatCommandListener::ListTtysCmd::ListTtysCmd() :
478d5573d34c8fac49e16b20cf144486125bf940086San Mehat                 NetdCommand("list_ttys") {
479d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
480d5573d34c8fac49e16b20cf144486125bf940086San Mehat
481d5573d34c8fac49e16b20cf144486125bf940086San Mehatint CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
48256afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran                                             int /* argc */, char ** /* argv */) {
4831cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    TtyCollection *tlist = gCtls->pppCtrl.getTtyList();
484d5573d34c8fac49e16b20cf144486125bf940086San Mehat    TtyCollection::iterator it;
485d5573d34c8fac49e16b20cf144486125bf940086San Mehat
486d5573d34c8fac49e16b20cf144486125bf940086San Mehat    for (it = tlist->begin(); it != tlist->end(); ++it) {
487d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
488d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
489d5573d34c8fac49e16b20cf144486125bf940086San Mehat
490d5573d34c8fac49e16b20cf144486125bf940086San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
491d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
492d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
493d5573d34c8fac49e16b20cf144486125bf940086San Mehat
494d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::IpFwdCmd::IpFwdCmd() :
495d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("ipfwd") {
496d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
497d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
498799625cd5b0a2191632f5b042bf9ff559c18a848Lorenzo Colittiint CommandListener::IpFwdCmd::runCommand(SocketClient *cli, int argc, char **argv) {
49932d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti    bool matched = false;
500799625cd5b0a2191632f5b042bf9ff559c18a848Lorenzo Colitti    bool success;
5019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
50232d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti    if (argc == 2) {
50332d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        //   0     1
50432d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        // ipfwd status
50532d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        if (!strcmp(argv[1], "status")) {
50632d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            char *tmp = NULL;
5079d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
50832d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            asprintf(&tmp, "Forwarding %s",
5091cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                     ((gCtls->tetherCtrl.forwardingRequestCount() > 0) ? "enabled" : "disabled"));
51032d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
51132d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            free(tmp);
51232d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            return 0;
51332d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        }
51432d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti    } else if (argc == 3) {
51532d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        //  0      1         2
51632d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        // ipfwd enable  <requester>
51732d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        // ipfwd disable <requester>
51832d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        if (!strcmp(argv[1], "enable")) {
51932d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            matched = true;
5201cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            success = gCtls->tetherCtrl.enableForwarding(argv[2]);
52132d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        } else if (!strcmp(argv[1], "disable")) {
52232d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            matched = true;
5231cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            success = gCtls->tetherCtrl.disableForwarding(argv[2]);
52432d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        }
52532d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti    } else if (argc == 4) {
52632d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        //  0      1      2     3
52732d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        // ipfwd  add   wlan0 dummy0
52832d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        // ipfwd remove wlan0 dummy0
52932d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        int ret = 0;
53032d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        if (!strcmp(argv[1], "add")) {
53132d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            matched = true;
53232d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            ret = RouteController::enableTethering(argv[2], argv[3]);
53332d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        } else if (!strcmp(argv[1], "remove")) {
53432d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            matched = true;
53532d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti            ret = RouteController::disableTethering(argv[2], argv[3]);
53632d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        }
53732d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        success = (ret == 0);
53832d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti        errno = -ret;
5399d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
5409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
54132d768792bcd5860512998543f6904d91da1a9b7Lorenzo Colitti    if (!matched) {
5429d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
5439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
5449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
5459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
546799625cd5b0a2191632f5b042bf9ff559c18a848Lorenzo Colitti    if (success) {
5479d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
5489d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
5499d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
5509d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
551d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
552d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
553d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
554d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::TetherCmd::TetherCmd() :
555d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("tether") {
556d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
557d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
558d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint CommandListener::TetherCmd::runCommand(SocketClient *cli,
559d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
5609d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    int rc = 0;
5619d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
562d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (argc < 2) {
563d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
564d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return 0;
565d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
566d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
5679d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!strcmp(argv[1], "stop")) {
5681cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->tetherCtrl.stopTethering();
569d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    } else if (!strcmp(argv[1], "status")) {
5709d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        char *tmp = NULL;
5719d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
5729d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        asprintf(&tmp, "Tethering services %s",
5731cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                 (gCtls->tetherCtrl.isTetheringStarted() ? "started" : "stopped"));
5749d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
5759d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        free(tmp);
576d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return 0;
57736971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall    } else if (argc == 3) {
57836971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall        if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
5791cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            InterfaceCollection *ilist = gCtls->tetherCtrl.getTetheredInterfaceList();
58036971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            InterfaceCollection::iterator it;
58136971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            for (it = ilist->begin(); it != ilist->end(); ++it) {
58236971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall                cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
58336971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            }
58436971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall        } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
585667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti            char netIdStr[UINT32_STRLEN];
5861cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            snprintf(netIdStr, sizeof(netIdStr), "%u", gCtls->tetherCtrl.getDnsNetId());
587667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti            cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
588667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti
5891cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            for (const auto &fwdr : *(gCtls->tetherCtrl.getDnsForwarders())) {
590f90a8b92eaf5e74979f589f1f6d3fa403dc26680Erik Kline                cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, fwdr.c_str(), false);
59136971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            }
59220f95ed9db048261c18bbeb152d3204d9cbb58f1JP Abgrall        }
5939d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
5949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        /*
5959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat         * These commands take a minimum of 4 arguments
5969d10b341a0ba46f108cb96e46691197d778cbc06San Mehat         */
5979d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        if (argc < 4) {
5989d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
5999d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            return 0;
6009d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        }
6019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
6029d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        if (!strcmp(argv[1], "start")) {
6033208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            if (argc % 2 == 1) {
6043208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
6059d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
6069d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
6073208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt
60813fa01fab904679970e4b95357f8eed7327b6d49Erik Kline            const int num_addrs = argc - 2;
60913fa01fab904679970e4b95357f8eed7327b6d49Erik Kline            // TODO: consider moving this validation into TetherController.
61013fa01fab904679970e4b95357f8eed7327b6d49Erik Kline            struct in_addr tmp_addr;
61113fa01fab904679970e4b95357f8eed7327b6d49Erik Kline            for (int arg_index = 2; arg_index < argc; arg_index++) {
61213fa01fab904679970e4b95357f8eed7327b6d49Erik Kline                if (!inet_aton(argv[arg_index], &tmp_addr)) {
6133208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                    cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
6143208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                    return 0;
6153208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                }
6169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
61713fa01fab904679970e4b95357f8eed7327b6d49Erik Kline
6181cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            rc = gCtls->tetherCtrl.startTethering(num_addrs, &(argv[2]));
6199d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else if (!strcmp(argv[1], "interface")) {
6209d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            if (!strcmp(argv[2], "add")) {
6211cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                rc = gCtls->tetherCtrl.tetherInterface(argv[3]);
6229d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else if (!strcmp(argv[2], "remove")) {
6231cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                rc = gCtls->tetherCtrl.untetherInterface(argv[3]);
62420f95ed9db048261c18bbeb152d3204d9cbb58f1JP Abgrall            /* else if (!strcmp(argv[2], "list")) handled above */
6259d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else {
6269d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                cli->sendMsg(ResponseCode::CommandParameterError,
6279d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                             "Unknown tether interface operation", false);
6289d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
6299d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
6309d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else if (!strcmp(argv[1], "dns")) {
6319d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            if (!strcmp(argv[2], "set")) {
632667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                if (argc < 5) {
633667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                    cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
634667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                    return 0;
635667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                }
636667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                unsigned netId = stringToNetId(argv[3]);
6371cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                rc = gCtls->tetherCtrl.setDnsForwarders(netId, &argv[4], argc - 4);
63836971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            /* else if (!strcmp(argv[2], "list")) handled above */
6399d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else {
6409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                cli->sendMsg(ResponseCode::CommandParameterError,
6419d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                             "Unknown tether interface operation", false);
6429d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
6439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
6449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else {
6459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
6469d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            return 0;
6479d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        }
6489d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6499d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
6509d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!rc) {
6519d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
6529d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6539d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
654d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
655d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
656d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
657d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
658d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
659d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::NatCmd::NatCmd() :
660d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("nat") {
661d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
662d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
663d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint CommandListener::NatCmd::runCommand(SocketClient *cli,
664d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
6659d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    int rc = 0;
6669d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
667fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5) {
6689d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
6699d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
6709d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6719d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
67287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    //  0     1       2        3
67387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // nat  enable intiface extiface
67487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // nat disable intiface extiface
67587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(argv[1], "enable") && argc >= 4) {
6761cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->natCtrl.enableNat(argv[2], argv[3]);
677c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if(!rc) {
678c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            /* Ignore ifaces for now. */
6791cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
680c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
68187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    } else if (!strcmp(argv[1], "disable") && argc >= 4) {
682f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        /* Ignore ifaces for now. */
6831cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
6841cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc |= gCtls->natCtrl.disableNat(argv[2], argv[3]);
6859d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6869d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
6879d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
6889d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6899d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
6909d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!rc) {
6919d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
6929d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6939d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
6949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
695d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
696d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
697d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
698d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
699d5573d34c8fac49e16b20cf144486125bf940086San MehatCommandListener::PppdCmd::PppdCmd() :
700d5573d34c8fac49e16b20cf144486125bf940086San Mehat                 NetdCommand("pppd") {
701d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
702d5573d34c8fac49e16b20cf144486125bf940086San Mehat
703d5573d34c8fac49e16b20cf144486125bf940086San Mehatint CommandListener::PppdCmd::runCommand(SocketClient *cli,
704d5573d34c8fac49e16b20cf144486125bf940086San Mehat                                                      int argc, char **argv) {
705d5573d34c8fac49e16b20cf144486125bf940086San Mehat    int rc = 0;
706d5573d34c8fac49e16b20cf144486125bf940086San Mehat
707d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (argc < 3) {
708d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
709d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
710d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
711d5573d34c8fac49e16b20cf144486125bf940086San Mehat
712d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!strcmp(argv[1], "attach")) {
71374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        struct in_addr l, r, dns1, dns2;
71474d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt
7151c4a77955acdb730d017b15e9a92ca511e6ca106Wang Liyong        memset(&dns1, 0, sizeof(struct in_addr));
7161c4a77955acdb730d017b15e9a92ca511e6ca106Wang Liyong        memset(&dns2, 0, sizeof(struct in_addr));
717d5573d34c8fac49e16b20cf144486125bf940086San Mehat
718d5573d34c8fac49e16b20cf144486125bf940086San Mehat        if (!inet_aton(argv[3], &l)) {
719d5573d34c8fac49e16b20cf144486125bf940086San Mehat            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
720d5573d34c8fac49e16b20cf144486125bf940086San Mehat            return 0;
721d5573d34c8fac49e16b20cf144486125bf940086San Mehat        }
722d5573d34c8fac49e16b20cf144486125bf940086San Mehat        if (!inet_aton(argv[4], &r)) {
723d5573d34c8fac49e16b20cf144486125bf940086San Mehat            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
724d5573d34c8fac49e16b20cf144486125bf940086San Mehat            return 0;
725d5573d34c8fac49e16b20cf144486125bf940086San Mehat        }
72674d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
72774d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
72874d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            return 0;
72974d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        }
73074d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
73174d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
73274d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            return 0;
73374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        }
7341cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->pppCtrl.attachPppd(argv[2], l, r, dns1, dns2);
735d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else if (!strcmp(argv[1], "detach")) {
7361cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->pppCtrl.detachPppd(argv[2]);
737d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else {
738d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
739d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
740d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
741d5573d34c8fac49e16b20cf144486125bf940086San Mehat
742d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!rc) {
743d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
744d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else {
745d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
746d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
747d5573d34c8fac49e16b20cf144486125bf940086San Mehat
748d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
749d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
7501bdac9e98c1ef37ba568b6cf23bfbc09cfe6bf15San Mehat
7515af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry ShmidtCommandListener::SoftapCmd::SoftapCmd() :
7525af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt                 NetdCommand("softap") {
7535af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt}
7545af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7555af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidtint CommandListener::SoftapCmd::runCommand(SocketClient *cli,
7565af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt                                        int argc, char **argv) {
75725753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    int rc = ResponseCode::SoftapStatusResult;
758666fe255fa581965d2835bd581cd5a8959411067Dmitry Shmidt    char *retbuf = NULL;
7595af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7601cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai    if (gCtls == nullptr) {
76125753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
76225753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      return -1;
76325753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    }
7645af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    if (argc < 2) {
76525753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(ResponseCode::CommandSyntaxError,
76625753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy                     "Missing argument in a SoftAP command", false);
7675af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7685af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    }
7695af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7707e9eb7b48345af69283afa7ca58d3be0a329931bIrfan Sheriff    if (!strcmp(argv[1], "startap")) {
7711cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->softapCtrl.startSoftap();
772c3539e22bd7a59a12542b9ad961f7d7f0db9a8dfDmitry Shmidt    } else if (!strcmp(argv[1], "stopap")) {
7731cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->softapCtrl.stopSoftap();
77431fd6c5f3e9c39a13b028718dba5921a4300988cDmitry Shmidt    } else if (!strcmp(argv[1], "fwreload")) {
7751cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->softapCtrl.fwReloadSoftap(argc, argv);
7765af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else if (!strcmp(argv[1], "status")) {
77725753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        asprintf(&retbuf, "Softap service %s running",
7781cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai                 (gCtls->softapCtrl.isSoftapStarted() ? "is" : "is not"));
77925753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(rc, retbuf, false);
780666fe255fa581965d2835bd581cd5a8959411067Dmitry Shmidt        free(retbuf);
7815af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7825af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else if (!strcmp(argv[1], "set")) {
7831cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->softapCtrl.setSoftap(argc, argv);
7845af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else {
78525753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
7865af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7875af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    }
7885af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
78925753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    if (rc >= 400 && rc < 600)
79025753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(rc, "SoftAP command has failed", false);
79125753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    else
79225753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(rc, "Ok", false);
7935af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7945af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    return 0;
7955af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt}
7963e6ba3ce1abda6071d5b01f53ca6039bb7b5e2d3Robert Greenwalt
79789c1e975f0c03997808d35c7be10b244c5309f9fMattias FalkCommandListener::ResolverCmd::ResolverCmd() :
79889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        NetdCommand("resolver") {
79989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk}
80089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
801938ab2acc65ea12e84d66e5bc3f8166482d2165bSasha Levitskiyint CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
80289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    int rc = 0;
803938ab2acc65ea12e84d66e5bc3f8166482d2165bSasha Levitskiy    const char **argv = const_cast<const char **>(margv);
80489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
8059adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline    if (argc < 3) {
80689c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
80789c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        return 0;
80889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
80989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
8109adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline    unsigned netId = stringToNetId(argv[2]);
8119adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline    // TODO: Consider making NetworkController.isValidNetwork() public
8129adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline    // and making that check here.
8139adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline
81435c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen    if (!strcmp(argv[1], "setnetdns")) {
81595f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        if (!parseAndExecuteSetNetDns(netId, argc, argv)) {
81689c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk            cli->sendMsg(ResponseCode::CommandSyntaxError,
81795f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai                    "Wrong number of or invalid arguments to resolver setnetdns", false);
81889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk            return 0;
81989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        }
820dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti    } else if (!strcmp(argv[1], "clearnetdns")) { // "resolver clearnetdns <netId>"
821dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti        if (argc == 3) {
8221cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            rc = gCtls->resolverCtrl.clearDnsServers(netId);
823dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti        } else {
824dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti            cli->sendMsg(ResponseCode::CommandSyntaxError,
825dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti                    "Wrong number of arguments to resolver clearnetdns", false);
826dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti            return 0;
827dadc5f850ee7a4dbe9ed418ae9d363b237f7a0e8Lorenzo Colitti        }
82889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    } else {
82989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
83089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        return 0;
83189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
83289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
83389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    if (!rc) {
83489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
83589c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    } else {
83689c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
83789c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
83889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
83989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    return 0;
84089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk}
84189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
84295f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imaibool CommandListener::ResolverCmd::parseAndExecuteSetNetDns(int netId, int argc,
84395f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        const char** argv) {
84495f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    // "resolver setnetdns <netId> <domains> <dns1> [<dns2> ...] [--params <params>]"
84595f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    // TODO: This code has to be replaced by a Binder call ASAP
84695f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    if (argc < 5) {
84795f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        return false;
84895f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    }
84995f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    int end = argc;
85095f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    __res_params params;
85195f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    const __res_params* paramsPtr = nullptr;
85295f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    if (end > 6 && !strcmp(argv[end - 2], "--params")) {
85395f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        const char* paramsStr = argv[end - 1];
85495f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        end -= 2;
85595f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        if (sscanf(paramsStr, "%hu %hhu %hhu %hhu", &params.sample_validity,
85695f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai                &params.success_threshold, &params.min_samples, &params.max_samples) != 4) {
85795f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai            return false;
85895f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        }
85995f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai        paramsPtr = &params;
86095f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    }
86195f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai    return gCtls->resolverCtrl.setDnsServers(netId, argv[3], &argv[4], end - 4, paramsPtr) == 0;
86295f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai}
86395f5f94aa4c10893b9118b9b79138a1500b5d85bPierre Imai
8644a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallCommandListener::BandwidthControlCmd::BandwidthControlCmd() :
8650dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    NetdCommand("bandwidth") {
8664a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
8674a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
868db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
869db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *msg;
870db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    asprintf(&msg, "Usage: bandwidth %s", usageMsg);
871db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
872db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    free(msg);
873db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
874db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
875db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
876db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!cond) {
877db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
878db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    } else {
879db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
880db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
881db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
882db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
883db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
884db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
885db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
886db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
887fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
8884a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (argc < 2) {
889db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericSyntaxError(cli, "<cmds> <args...>");
8904a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        return 0;
8914a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
8924a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
8933fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
894db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
8954a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (!strcmp(argv[1], "enable")) {
8961cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.enableBandwidthControl(true);
897db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
898db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
899db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
900db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
901db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "disable")) {
9021cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.disableBandwidthControl();
903db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
904db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9050dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
906db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
907db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
908fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc != 3) {
909db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removequota <interface>");
910fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
911fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
9121cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[2]);
913db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
914db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
915fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
916db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
917db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
9188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        int64_t bytes;
9198a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
920db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "getquota");
9218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
9228a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
9231cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.getInterfaceSharedQuota(&bytes);
9248a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (rc) {
925db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericOpFailed(cli, "Failed to get quota");
9268a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
9278a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
928db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9298a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        char *msg;
9307776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev        asprintf(&msg, "%" PRId64, bytes);
9318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
9328a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(msg);
933db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9348a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
935db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
936db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
9378a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        int64_t bytes;
9388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
939db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "getiquota <iface>");
9408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
9418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
942db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9431cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.getInterfaceQuota(argv[2], &bytes);
9448a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (rc) {
945db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericOpFailed(cli, "Failed to get quota");
9468a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
9478a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
9488a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        char *msg;
9497776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev        asprintf(&msg, "%" PRId64, bytes);
9508a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
9518a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(msg);
952db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9538a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
954db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
955db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
956fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc != 4) {
957db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
958fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
959fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
9601cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[2], atoll(argv[3]));
961db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
962db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
963db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
964db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
965db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc;
966fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 4) {
967db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
968fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
969fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
970db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        for (int q = 3; argc >= 4; q++, argc--) {
9721cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            rc = gCtls->bandwidthCtrl.setInterfaceSharedQuota(argv[q], atoll(argv[2]));
9730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            if (rc) {
9740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                char *msg;
9750dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
9760dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                cli->sendMsg(ResponseCode::OperationFailed,
9770dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                             msg, false);
9780dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                free(msg);
979db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                return 0;
9800dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            }
9810dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
982db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
983db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9840dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
986db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc;
9880dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc < 3) {
989db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removequotas <interface> ...");
9900dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
9910dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
992db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        for (int q = 2; argc >= 3; q++, argc--) {
9941cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            rc = gCtls->bandwidthCtrl.removeInterfaceSharedQuota(argv[q]);
9950dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            if (rc) {
9960dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                char *msg;
9970dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
9980dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                cli->sendMsg(ResponseCode::OperationFailed,
9990dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                             msg, false);
10000dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                free(msg);
1001db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                return 0;
10020dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            }
10030dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
1004db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1005db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10060dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
1007db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1008db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
10090dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc != 3) {
1010db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeiquota <interface>");
10110dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
10120dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
10131cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeInterfaceQuota(argv[2]);
1014db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1015db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10160dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
1017db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1018db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
10190dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc != 4) {
1020db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
10210dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
10220dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
10231cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setInterfaceQuota(argv[2], atoll(argv[3]));
1024db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1025db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
1026fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
1027db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1028db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
1029fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 3) {
1030db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
10314a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return 0;
1032fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
10331cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.addNaughtyApps(argc - 2, argv + 2);
1034db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1035db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
1036db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1037fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
1038db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1039db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
1040fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 3) {
1041db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
1042fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
1043fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
10441cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeNaughtyApps(argc - 2, argv + 2);
1045db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1046db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
1047e478873947f995e44e8c559342462c177a420ae0JP Abgrall    }
1048e478873947f995e44e8c559342462c177a420ae0JP Abgrall    if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1049e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (argc < 3) {
1050e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1051e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1052e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
10531cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.addNiceApps(argc - 2, argv + 2);
1054e478873947f995e44e8c559342462c177a420ae0JP Abgrall        sendGenericOkFail(cli, rc);
1055e478873947f995e44e8c559342462c177a420ae0JP Abgrall        return 0;
1056e478873947f995e44e8c559342462c177a420ae0JP Abgrall    }
1057e478873947f995e44e8c559342462c177a420ae0JP Abgrall    if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1058e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (argc < 3) {
1059e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1060e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1061e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
10621cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeNiceApps(argc - 2, argv + 2);
1063e478873947f995e44e8c559342462c177a420ae0JP Abgrall        sendGenericOkFail(cli, rc);
1064e478873947f995e44e8c559342462c177a420ae0JP Abgrall        return 0;
1065db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1066db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
10678a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1068db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setglobalalert <bytes>");
10698a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
10711cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setGlobalAlert(atoll(argv[2]));
1072db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1073db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
1074db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1075c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1076c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (argc != 4) {
1077c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1078c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            return 0;
1079c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
1080c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        /* We ignore the interfaces for now. */
10811cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setGlobalAlertInForwardChain();
1082c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        sendGenericOkFail(cli, rc);
1083c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
1084c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
1085c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
1086db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
10878a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
1088db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeglobalalert");
10898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
10911cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeGlobalAlert();
1092db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1093db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10948a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1095db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1096c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1097c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (argc != 4) {
1098c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1099c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            return 0;
1100c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
1101c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        /* We ignore the interfaces for now. */
11021cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeGlobalAlertInForwardChain();
1103c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        sendGenericOkFail(cli, rc);
1104c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
1105c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
1106c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
1107db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
11088a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1109db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setsharedalert <bytes>");
11108a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
11121cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setSharedAlert(atoll(argv[2]));
1113db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1114db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11158a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1116db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1117db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
11188a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
1119db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removesharedalert");
11208a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11218a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
11221cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeSharedAlert();
1123db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1124db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11258a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1126db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1127db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
11288a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 4) {
1129db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
11308a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11318a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
11321cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.setInterfaceAlert(argv[2], atoll(argv[3]));
1133db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1134db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11358a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1136db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1137db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
11388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1139db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
11408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
11421cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.removeInterfaceAlert(argv[2]);
1143db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1144fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return 0;
1145db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
11464a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
1147db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1148db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        BandwidthController::TetherStats tetherStats;
1149a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall        std::string extraProcessingInfo = "";
1150baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (argc < 2 || argc > 4) {
1151baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1152db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            return 0;
1153db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1154baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        tetherStats.intIface = argc > 2 ? argv[2] : "";
1155baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        tetherStats.extIface = argc > 3 ? argv[3] : "";
1156f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        // No filtering requested and there are no interface pairs to lookup.
11571cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        if (argc <= 2 && gCtls->natCtrl.ifacePairList.empty()) {
1158f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1159f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            return 0;
1160f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        }
11611cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int rc = gCtls->bandwidthCtrl.getTetherStats(cli, tetherStats, extraProcessingInfo);
1162db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if (rc) {
1163a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1164a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1165baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                return 0;
1166db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1167db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
11694a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
1170db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1171db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
11724a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return 0;
11734a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
11740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11750031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallCommandListener::IdletimerControlCmd::IdletimerControlCmd() :
11760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    NetdCommand("idletimer") {
11770031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
11780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
11800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  // TODO(ashish): Change the error statements
11810031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (argc < 2) {
11820031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
11840031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
11870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "enable")) {
11891cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai      if (0 != gCtls->idletimerCtrl.enableIdletimerControl()) {
11900031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11910031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      } else {
11920031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
11930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      }
11940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      return 0;
11950031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11960031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11970031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "disable")) {
11981cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai      if (0 != gCtls->idletimerCtrl.disableIdletimerControl()) {
11990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
12000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      } else {
12010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
12020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      }
12030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      return 0;
12040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
12050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "add")) {
120698f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if (argc != 5) {
12070031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
12080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            return 0;
12090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
12101cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        if(0 != gCtls->idletimerCtrl.addInterfaceIdletimer(
121198f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                        argv[2], atoi(argv[3]), argv[4])) {
12120031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
12130031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        } else {
12140031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
12150031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
12160031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
12170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
12180031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "remove")) {
121998f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if (argc != 5) {
12200031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
12210031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            return 0;
12220031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
12230031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        // ashish: fixme timeout
12241cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        if (0 != gCtls->idletimerCtrl.removeInterfaceIdletimer(
122598f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                        argv[2], atoi(argv[3]), argv[4])) {
12260031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
12270031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        } else {
12280031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
12290031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
12300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
12310031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
12320031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
12330031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
12340031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
12350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1236d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1237d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyCommandListener::FirewallCmd::FirewallCmd() :
1238d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    NetdCommand("firewall") {
1239d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1240d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1241d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1242d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!cond) {
1243d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1244d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    } else {
1245d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1246d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1247d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    return 0;
1248d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1249d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1250d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyFirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1251d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(arg, "allow")) {
1252d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return ALLOW;
1253390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    } else if (!strcmp(arg, "deny")) {
1254d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return DENY;
1255390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    } else {
1256390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        ALOGE("failed to parse uid rule (%s)", arg);
1257390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        return ALLOW;
1258390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    }
1259390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani}
1260390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani
1261390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith YamasaniFirewallType CommandListener::FirewallCmd::parseFirewallType(const char* arg) {
1262390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    if (!strcmp(arg, "whitelist")) {
1263390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        return WHITELIST;
1264390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    } else if (!strcmp(arg, "blacklist")) {
1265390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        return BLACKLIST;
1266390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani    } else {
1267390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        ALOGE("failed to parse firewall type (%s)", arg);
1268390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        return BLACKLIST;
1269d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1270d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1271d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
12721cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui ChenChildChain CommandListener::FirewallCmd::parseChildChain(const char* arg) {
12731cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    if (!strcmp(arg, "dozable")) {
12741cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return DOZABLE;
12751cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    } else if (!strcmp(arg, "standby")) {
12761cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return STANDBY;
12773f62434145c43e85436b86ed9b95a550bbdf486bFelipe Leme    } else if (!strcmp(arg, "powersave")) {
12783f62434145c43e85436b86ed9b95a550bbdf486bFelipe Leme        return POWERSAVE;
12791cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    } else if (!strcmp(arg, "none")) {
12801cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return NONE;
12811cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    } else {
12821cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        ALOGE("failed to parse child firewall chain (%s)", arg);
12831cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return INVALID_CHAIN;
12841cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    }
12851cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen}
12861cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen
1287d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1288d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        char **argv) {
1289d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (argc < 2) {
1290d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1291d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return 0;
1292d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1293d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1294d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "enable")) {
1295390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        if (argc != 3) {
1296390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani            cli->sendMsg(ResponseCode::CommandSyntaxError,
1297390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani                        "Usage: firewall enable <whitelist|blacklist>", false);
1298390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani            return 0;
1299390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        }
1300390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani        FirewallType firewallType = parseFirewallType(argv[2]);
1301390e4ea8106f9e741bc80fb962aaee94d5b28cbbAmith Yamasani
13021cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.enableFirewall(firewallType);
1303d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1304d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1305d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "disable")) {
13061cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.disableFirewall();
1307d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1308d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1309d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "is_enabled")) {
13101cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.isFirewallEnabled();
1311d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1312d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1313d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1314d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_interface_rule")) {
1315d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 4) {
1316d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1317d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1318d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1319d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1320d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1321d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* iface = argv[2];
1322d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[3]);
1323d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
13241cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.setInterfaceRule(iface, rule);
1325d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1326d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1327d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1328d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_egress_source_rule")) {
1329d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 4) {
1330d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1331d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1332d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1333d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1334d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1335d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1336d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* addr = argv[2];
1337d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[3]);
1338d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
13391cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.setEgressSourceRule(addr, rule);
1340d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1341d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1342d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1343d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_egress_dest_rule")) {
1344d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 5) {
1345d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1346d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1347d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1348d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1349d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1350d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1351d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* addr = argv[2];
1352d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int port = atoi(argv[3]);
1353d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[4]);
1354d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1355d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = 0;
13561cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
13571cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        res |= gCtls->firewallCtrl.setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1358d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1359d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1360d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1361d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_uid_rule")) {
13621cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        if (argc != 5) {
1363d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
13641cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         "Usage: firewall set_uid_rule <dozable|standby|none> <1000> <allow|deny>",
1365d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1366d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1367d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1368d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
13691cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        ChildChain childChain = parseChildChain(argv[2]);
13701cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        if (childChain == INVALID_CHAIN) {
13711cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            cli->sendMsg(ResponseCode::CommandSyntaxError,
13721cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         "Invalid chain name. Valid names are: <dozable|standby|none>",
13731cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         false);
13741cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            return 0;
13751cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        }
13761cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        int uid = atoi(argv[3]);
13771cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        FirewallRule rule = parseRule(argv[4]);
13781cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.setUidRule(childChain, uid, rule);
13791cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return sendGenericOkFail(cli, res);
13801cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    }
13811cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen
13821cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    if (!strcmp(argv[1], "enable_chain")) {
13831cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        if (argc != 3) {
13841cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            cli->sendMsg(ResponseCode::CommandSyntaxError,
13851cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         "Usage: firewall enable_chain <dozable|standby>",
13861cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         false);
13871cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            return 0;
13881cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        }
13891cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen
13901cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        ChildChain childChain = parseChildChain(argv[2]);
13911cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.enableChildChains(childChain, true);
13921cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        return sendGenericOkFail(cli, res);
13931cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    }
13941cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen
13951cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen    if (!strcmp(argv[1], "disable_chain")) {
13961cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        if (argc != 3) {
13971cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            cli->sendMsg(ResponseCode::CommandSyntaxError,
13981cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         "Usage: firewall disable_chain <dozable|standby>",
13991cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen                         false);
14001cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen            return 0;
14011cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        }
14021cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen
14031cdfa9adfa584029cb6d9ac13a2896786001b3a1Xiaohui Chen        ChildChain childChain = parseChildChain(argv[2]);
14041cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->firewallCtrl.enableChildChains(childChain, false);
1405d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1406d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1407d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1408d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1409d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    return 0;
1410d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
14110da73fcecc30140439f856118056df8908609627Daniel Drown
14120da73fcecc30140439f856118056df8908609627Daniel DrownCommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
14130da73fcecc30140439f856118056df8908609627Daniel Drown}
14140da73fcecc30140439f856118056df8908609627Daniel Drown
14150da73fcecc30140439f856118056df8908609627Daniel Drownint CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
14160da73fcecc30140439f856118056df8908609627Daniel Drown                                                            char **argv) {
14170da73fcecc30140439f856118056df8908609627Daniel Drown    int rc = 0;
1418ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (argc < 3) {
14190da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
14200da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
14210da73fcecc30140439f856118056df8908609627Daniel Drown    }
14220da73fcecc30140439f856118056df8908609627Daniel Drown
1423ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    if (!strcmp(argv[1], "stop")) {
14241cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->clatdCtrl.stopClatd(argv[2]);
14250da73fcecc30140439f856118056df8908609627Daniel Drown    } else if (!strcmp(argv[1], "status")) {
14260da73fcecc30140439f856118056df8908609627Daniel Drown        char *tmp = NULL;
14271cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        asprintf(&tmp, "Clatd status: %s", (gCtls->clatdCtrl.isClatdStarted(argv[2]) ?
1428ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti                                            "started" : "stopped"));
14290da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
14300da73fcecc30140439f856118056df8908609627Daniel Drown        free(tmp);
14310da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
1432ac7fefcf3d90cf856b0f1664207d056ed1dd4725Lorenzo Colitti    } else if (!strcmp(argv[1], "start")) {
14331cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        rc = gCtls->clatdCtrl.startClatd(argv[2]);
14340da73fcecc30140439f856118056df8908609627Daniel Drown    } else {
14350da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
14360da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
14370da73fcecc30140439f856118056df8908609627Daniel Drown    }
14380da73fcecc30140439f856118056df8908609627Daniel Drown
14390da73fcecc30140439f856118056df8908609627Daniel Drown    if (!rc) {
14400da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
14410da73fcecc30140439f856118056df8908609627Daniel Drown    } else {
14420da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
14430da73fcecc30140439f856118056df8908609627Daniel Drown    }
14440da73fcecc30140439f856118056df8908609627Daniel Drown
14450da73fcecc30140439f856118056df8908609627Daniel Drown    return 0;
14460da73fcecc30140439f856118056df8908609627Daniel Drown}
1447d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
1448fbe497fcd808e4317572ad48c42545105309a347Jeff SharkeyCommandListener::StrictCmd::StrictCmd() :
1449fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    NetdCommand("strict") {
1450fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey}
1451fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1452fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkeyint CommandListener::StrictCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1453fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (!cond) {
1454fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        cli->sendMsg(ResponseCode::CommandOkay, "Strict command succeeded", false);
1455fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    } else {
1456fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        cli->sendMsg(ResponseCode::OperationFailed, "Strict command failed", false);
1457fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1458fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    return 0;
1459fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey}
1460fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1461fbe497fcd808e4317572ad48c42545105309a347Jeff SharkeyStrictPenalty CommandListener::StrictCmd::parsePenalty(const char* arg) {
1462fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (!strcmp(arg, "reject")) {
1463fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return REJECT;
1464fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    } else if (!strcmp(arg, "log")) {
1465fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return LOG;
1466fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    } else if (!strcmp(arg, "accept")) {
1467fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return ACCEPT;
1468fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    } else {
1469fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return INVALID;
1470fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1471fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey}
1472fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1473fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkeyint CommandListener::StrictCmd::runCommand(SocketClient *cli, int argc,
1474fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        char **argv) {
1475fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (argc < 2) {
1476fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1477fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return 0;
1478fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1479fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1480fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (!strcmp(argv[1], "enable")) {
14811cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->strictCtrl.enableStrict();
1482fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return sendGenericOkFail(cli, res);
1483fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1484fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (!strcmp(argv[1], "disable")) {
14851cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->strictCtrl.disableStrict();
1486fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return sendGenericOkFail(cli, res);
1487fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1488fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1489fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    if (!strcmp(argv[1], "set_uid_cleartext_policy")) {
1490fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        if (argc != 4) {
1491fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1492fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey                         "Usage: strict set_uid_cleartext_policy <uid> <accept|log|reject>",
1493fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey                         false);
1494fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            return 0;
1495fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        }
1496fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1497fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        errno = 0;
1498fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        unsigned long int uid = strtoul(argv[2], NULL, 0);
1499fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        if (errno || uid > UID_MAX) {
1500fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid UID", false);
1501fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            return 0;
1502fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        }
1503fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1504fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        StrictPenalty penalty = parsePenalty(argv[3]);
1505fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        if (penalty == INVALID) {
1506fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError, "Invalid penalty argument", false);
1507fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey            return 0;
1508fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        }
1509fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
15101cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        int res = gCtls->strictCtrl.setUidCleartextPenalty((uid_t) uid, penalty);
1511fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey        return sendGenericOkFail(cli, res);
1512fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    }
1513fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
1514fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1515fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey    return 0;
1516fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey}
1517fbe497fcd808e4317572ad48c42545105309a347Jeff Sharkey
15185c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram RamachandranCommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
15195c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
15205c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
15215c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
15225c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
15235c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return 0;
15245c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
15255c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1526f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1527f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                                    int ret) {
1528f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    errno = -ret;
15295c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::OperationFailed, message, true);
1530d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    return 0;
1531d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1532d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
15335c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::success(SocketClient* client) {
15345c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::CommandOkay, "success", false);
1535d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    return 0;
1536d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1537d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
15385c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1539d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (argc < 2) {
15405c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return syntaxError(client, "Missing argument");
1541d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
15425c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
15434c95a125e0930c112555437589f7620575482095Lorenzo Colitti    //    0      1      2      3      4       5         6            7           8
15444c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
15454c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
15464c95a125e0930c112555437589f7620575482095Lorenzo Colitti    //
15474c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1548f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (!strcmp(argv[1], "route")) {
1549f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (argc < 6 || argc > 9) {
1550f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
1551f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1552f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1553f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        int nextArg = 2;
1554f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        bool legacy = false;
1555f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        uid_t uid = 0;
1556f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[nextArg], "legacy")) {
1557f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ++nextArg;
1558f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            legacy = true;
1559f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            uid = strtoul(argv[nextArg++], NULL, 0);
1560f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1561f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1562f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        bool add = false;
1563f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[nextArg], "add")) {
1564f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            add = true;
1565f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else if (strcmp(argv[nextArg], "remove")) {
1566f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1567f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1568f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ++nextArg;
1569f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1570de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran        if (argc < nextArg + 3 || argc > nextArg + 4) {
1571de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
1572de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran        }
1573de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran
157487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[nextArg++]);
1575f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* interface = argv[nextArg++];
1576f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* destination = argv[nextArg++];
1577f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1578f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1579f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        int ret;
1580f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (add) {
15811cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            ret = gCtls->netCtrl.addRoute(netId, interface, destination, nexthop, legacy, uid);
1582f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else {
15831cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            ret = gCtls->netCtrl.removeRoute(netId, interface, destination, nexthop, legacy, uid);
1584f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1585f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (ret) {
1586f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1587f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1588f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1589f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return success(client);
1590f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
1591f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
159287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    //    0        1       2       3         4
159387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // network interface  add   <netId> <interface>
159487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // network interface remove <netId> <interface>
159587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(argv[1], "interface")) {
159687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        if (argc != 5) {
1597f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Missing argument");
1598f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
159987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[3]);
160087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        if (!strcmp(argv[2], "add")) {
16011cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.addInterfaceToNetwork(netId, argv[4])) {
1602f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "addInterfaceToNetwork() failed", ret);
1603f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            }
160487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        } else if (!strcmp(argv[2], "remove")) {
16051cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.removeInterfaceFromNetwork(netId, argv[4])) {
1606f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1607f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            }
160887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        } else {
160987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1610f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1611f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return success(client);
1612f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
1613f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1614ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    //    0      1       2         3
1615ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network create <netId> [permission]
16164043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    //
161795684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    //    0      1       2     3     4        5
161895684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    // network create <netId> vpn <hasDns> <secure>
1619d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (!strcmp(argv[1], "create")) {
1620ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        if (argc < 3) {
16215c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran            return syntaxError(client, "Missing argument");
16225c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
162387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[2]);
162495684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran        if (argc == 6 && !strcmp(argv[3], "vpn")) {
1625e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            bool hasDns = atoi(argv[4]);
162695684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran            bool secure = atoi(argv[5]);
16271cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.createVirtualNetwork(netId, hasDns, secure)) {
1628e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                return operationError(client, "createVirtualNetwork() failed", ret);
16294043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
1630ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        } else if (argc > 4) {
1631ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            return syntaxError(client, "Unknown trailing argument(s)");
16324043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        } else {
1633ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            Permission permission = PERMISSION_NONE;
1634ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            if (argc == 4) {
1635ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                permission = stringToPermission(argv[3]);
1636ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                if (permission == PERMISSION_NONE) {
1637ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                    return syntaxError(client, "Unknown permission");
1638ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                }
16394043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
16401cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.createPhysicalNetwork(netId, permission)) {
1641e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                return operationError(client, "createPhysicalNetwork() failed", ret);
16424043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
16435c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
16445c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return success(client);
1645d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
16465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1647d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    //    0       1       2
1648d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    // network destroy <netId>
1649d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (!strcmp(argv[1], "destroy")) {
1650379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (argc != 3) {
1651379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
16525c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
165387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[2]);
16541cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        if (int ret = gCtls->netCtrl.destroyNetwork(netId)) {
1655f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, "destroyNetwork() failed", ret);
16565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
16575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return success(client);
1658d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
16595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1660f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    //    0       1      2      3
1661f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    // network default  set  <netId>
1662f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    // network default clear
1663f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (!strcmp(argv[1], "default")) {
1664f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (argc < 3) {
1665ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen            return syntaxError(client, "Missing argument");
1666ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        }
1667f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        unsigned netId = NETID_UNSET;
1668f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[2], "set")) {
1669f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            if (argc < 4) {
1670f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return syntaxError(client, "Missing netId");
1671ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen            }
167287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            netId = stringToNetId(argv[3]);
1673f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else if (strcmp(argv[2], "clear")) {
1674f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1675f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
16761cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai        if (int ret = gCtls->netCtrl.setDefaultNetwork(netId)) {
1677f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, "setDefaultNetwork() failed", ret);
1678ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        }
1679ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        return success(client);
1680ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen    }
1681ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
1682ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    //    0        1         2      3        4          5
1683ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission   user   set  <permission>  <uid> ...
1684ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission   user  clear    <uid> ...
1685ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission network  set  <permission> <netId> ...
1686ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission network clear   <netId> ...
1687379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    if (!strcmp(argv[1], "permission")) {
1688379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (argc < 5) {
1689379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Missing argument");
1690379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1691379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        int nextArg = 4;
1692379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        Permission permission = PERMISSION_NONE;
1693379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (!strcmp(argv[3], "set")) {
1694ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            permission = stringToPermission(argv[4]);
1695ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            if (permission == PERMISSION_NONE) {
1696ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                return syntaxError(client, "Unknown permission");
1697ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            }
1698ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            nextArg = 5;
1699379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        } else if (strcmp(argv[3], "clear")) {
1700379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Unknown argument");
1701379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1702ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        if (nextArg == argc) {
1703ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            return syntaxError(client, "Missing id");
1704ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        }
17059adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline
17069adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        bool userPermissions = !strcmp(argv[2], "user");
17079adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        bool networkPermissions = !strcmp(argv[2], "network");
17089adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        if (!userPermissions && !networkPermissions) {
17099adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline            return syntaxError(client, "Unknown argument");
17109adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        }
17119adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline
1712379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        std::vector<unsigned> ids;
1713379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        for (; nextArg < argc; ++nextArg) {
17149adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline            if (userPermissions) {
17159adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                char* endPtr;
17169adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                unsigned id = strtoul(argv[nextArg], &endPtr, 0);
17179adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                if (!*argv[nextArg] || *endPtr) {
17189adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                    return syntaxError(client, "Invalid id");
17199adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                }
17209adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                ids.push_back(id);
17219adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline            } else {
17229adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                // networkPermissions
17239adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline                ids.push_back(stringToNetId(argv[nextArg]));
1724379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            }
1725379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
17269adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        if (userPermissions) {
17271cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            gCtls->netCtrl.setPermissionForUsers(permission, ids);
17289adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline        } else {
17299adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline            // networkPermissions
17301cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.setPermissionForNetworks(permission, ids)) {
1731f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "setPermissionForNetworks() failed", ret);
1732379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            }
1733379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
17349adc9f32a45d19b34b5b4c4be7a20396c7e20c22Erik Kline
1735379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        return success(client);
1736379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    }
1737379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
1738b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    //    0      1     2       3           4
1739b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    // network users  add   <netId> [<uid>[-<uid>]] ...
1740b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    // network users remove <netId> [<uid>[-<uid>]] ...
1741b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    if (!strcmp(argv[1], "users")) {
1742b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (argc < 4) {
1743b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Missing argument");
1744b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
174587475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[3]);
1746b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        UidRanges uidRanges;
1747b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1748b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Invalid UIDs");
1749b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
1750b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!strcmp(argv[2], "add")) {
17511cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.addUsersToNetwork(netId, uidRanges)) {
1752b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return operationError(client, "addUsersToNetwork() failed", ret);
1753b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
1754b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else if (!strcmp(argv[2], "remove")) {
17551cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            if (int ret = gCtls->netCtrl.removeUsersFromNetwork(netId, uidRanges)) {
1756b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return operationError(client, "removeUsersFromNetwork() failed", ret);
1757b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
1758b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else {
1759b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Unknown argument");
1760b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
1761b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return success(client);
1762b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
1763b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
176489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    //    0       1      2     3
176589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    // network protect allow <uid> ...
176689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    // network protect  deny <uid> ...
176789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    if (!strcmp(argv[1], "protect")) {
176889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        if (argc < 4) {
176989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            return syntaxError(client, "Missing argument");
177089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
177189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        std::vector<uid_t> uids;
177289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        for (int i = 3; i < argc; ++i) {
177389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            uids.push_back(strtoul(argv[i], NULL, 0));
177489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
177589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        if (!strcmp(argv[2], "allow")) {
17761cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            gCtls->netCtrl.allowProtect(uids);
177789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        } else if (!strcmp(argv[2], "deny")) {
17781cfa54374f5ba63d69d6fcca767c4f6647cb6de2Pierre Imai            gCtls->netCtrl.denyProtect(uids);
177989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        } else {
178089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
178189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
178289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        return success(client);
178389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    }
178489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran
17855c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return syntaxError(client, "Unknown argument");
1786d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1787