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>
295c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
302a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#define __STDC_FORMAT_MACROS 1
312a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach#include <inttypes.h>
322a54d96c5ae809216965e6f86e70cdae2ed7e09cMatthew Leach
33d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#define LOG_TAG "CommandListener"
34d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
351ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti#include <cutils/log.h>
361ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti#include <netutils/ifc.h>
37d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sysutils/SocketClient.h>
38d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "CommandListener.h"
40d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "ResponseCode.h"
414a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall#include "BandwidthController.h"
420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "IdletimerController.h"
430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall#include "oem_iptables_hook.h"
448e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey#include "NetdConstants.h"
45d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey#include "FirewallController.h"
465c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include "RouteController.h"
47b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran#include "UidRanges.h"
485c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
495c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <string>
505c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran#include <vector>
515c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
52379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandrannamespace {
53379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
54bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandranconst unsigned NUM_OEM_IDS = NetworkController::MAX_OEM_ID - NetworkController::MIN_OEM_ID + 1;
55bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran
56ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram RamachandranPermission stringToPermission(const char* arg) {
57ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    if (!strcmp(arg, "android.permission.CHANGE_NETWORK_STATE")) {
58ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        return PERMISSION_NETWORK;
59ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    }
60ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    if (!strcmp(arg, "android.permission.CONNECTIVITY_INTERNAL")) {
61ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        return PERMISSION_SYSTEM;
62ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    }
63ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    return PERMISSION_NONE;
64379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}
65379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
6687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandranunsigned stringToNetId(const char* arg) {
6787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(arg, "local")) {
6887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        return NetworkController::LOCAL_NET_ID;
6987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    }
70bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    // OEM NetIds are "oem1", "oem2", .., "oem50".
71bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    if (!strncmp(arg, "oem", 3)) {
72bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        unsigned n = strtoul(arg + 3, NULL, 0);
73bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        if (1 <= n && n <= NUM_OEM_IDS) {
74bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran            return NetworkController::MIN_OEM_ID + n;
75bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        }
76bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran        return NETID_UNSET;
77bbdde9909b7b4fd31c5857156ceb00049bf4992dSreeram Ramachandran    }
7887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
7987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    return strtoul(arg, NULL, 0);
8087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran}
8187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran
82379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran}  // namespace
83379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
84a0efaece8c05370f201efe099a537ceb014c6fdfSzymon JakubczakNetworkController *CommandListener::sNetCtrl = NULL;
859d10b341a0ba46f108cb96e46691197d778cbc06San MehatTetherController *CommandListener::sTetherCtrl = NULL;
869ff78fb7da7158f5bd7c86d89a842691820259cfSan MehatNatController *CommandListener::sNatCtrl = NULL;
87d5573d34c8fac49e16b20cf144486125bf940086San MehatPppController *CommandListener::sPppCtrl = NULL;
885af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry ShmidtSoftapController *CommandListener::sSoftapCtrl = NULL;
894a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallBandwidthController * CommandListener::sBandwidthCtrl = NULL;
900031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallIdletimerController * CommandListener::sIdletimerCtrl = NULL;
912eab1f762badb7ba46b95716e62ea4548a979903Dmitry ShmidtInterfaceController *CommandListener::sInterfaceCtrl = NULL;
9289c1e975f0c03997808d35c7be10b244c5309f9fMattias FalkResolverController *CommandListener::sResolverCtrl = NULL;
93d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyFirewallController *CommandListener::sFirewallCtrl = NULL;
940da73fcecc30140439f856118056df8908609627Daniel DrownClatdController *CommandListener::sClatdCtrl = NULL;
959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
968e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey/**
978e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey * List of module chains to be created, along with explicit ordering. ORDERING
988e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
998e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey */
1008e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_INPUT[] = {
101d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        // Bandwidth should always be early in input chain, to make sure we
102d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        // correctly count incoming traffic against data plan.
1038e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_INPUT,
104d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_INPUT,
1058e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1068e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1078e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1088e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_FORWARD[] = {
1098e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_FILTER_FORWARD,
110d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_FORWARD,
1118e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_FORWARD,
1128e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NatController::LOCAL_FORWARD,
1138e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1148e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1158e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1168e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* FILTER_OUTPUT[] = {
1178e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_FILTER_OUTPUT,
118d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallController::LOCAL_OUTPUT,
1198e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_OUTPUT,
1208e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1218e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1228e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1238e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* RAW_PREROUTING[] = {
1248e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_RAW_PREROUTING,
1255c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai        IdletimerController::LOCAL_RAW_PREROUTING,
1268e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1278e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1288e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1298e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* MANGLE_POSTROUTING[] = {
1308e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        BandwidthController::LOCAL_MANGLE_POSTROUTING,
1315c4faf7602de0268aa09a3a525b427f83d617b5cHaoyu Bai        IdletimerController::LOCAL_MANGLE_POSTROUTING,
1329a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker        NULL,
1339a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker};
1349a50889a22c1d93c9e1a14873cde8fc1508f66fdChad Brubaker
135e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colittistatic const char* MANGLE_FORWARD[] = {
136e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti        NatController::LOCAL_MANGLE_FORWARD,
137e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti        NULL,
138e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti};
139e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti
1408e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* NAT_PREROUTING[] = {
1418e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        OEM_IPTABLES_NAT_PREROUTING,
1428e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1438e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1448e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1458e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic const char* NAT_POSTROUTING[] = {
1468e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NatController::LOCAL_NAT_POSTROUTING,
1478e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        NULL,
1488e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey};
1498e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1508e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkeystatic void createChildChains(IptablesTarget target, const char* table, const char* parentChain,
1518e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        const char** childChains) {
1528e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    const char** childChain = childChains;
1538e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    do {
1548e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // Order is important:
1558e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -D to delete any pre-existing jump rule (removes references
1568e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        //    that would prevent -X from working)
1578e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -F to flush any existing chain
1588e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -X to delete any existing chain
1598e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -N to create the chain
1608e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        // -A to append the chain to parent
1618e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
1628e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-D", parentChain, "-j", *childChain, NULL);
1638e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-F", *childChain, NULL);
1648e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptablesSilently(target, "-t", table, "-X", *childChain, NULL);
1658e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptables(target, "-t", table, "-N", *childChain, NULL);
1668e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey        execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
1678e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    } while (*(++childChain) != NULL);
1688e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey}
1698e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
170a0efaece8c05370f201efe099a537ceb014c6fdfSzymon JakubczakCommandListener::CommandListener() :
171a8e59f8c50aed3f91dead377b8ae21646978506cRobert Greenwalt                 FrameworkListener("netd", true) {
1725c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    registerCmd(new InterfaceCmd());
173d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    registerCmd(new IpFwdCmd());
174d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    registerCmd(new TetherCmd());
175d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    registerCmd(new NatCmd());
176d5573d34c8fac49e16b20cf144486125bf940086San Mehat    registerCmd(new ListTtysCmd());
177d5573d34c8fac49e16b20cf144486125bf940086San Mehat    registerCmd(new PppdCmd());
1785af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    registerCmd(new SoftapCmd());
1794a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    registerCmd(new BandwidthControlCmd());
1800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    registerCmd(new IdletimerControlCmd());
18189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    registerCmd(new ResolverCmd());
182d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    registerCmd(new FirewallCmd());
1830da73fcecc30140439f856118056df8908609627Daniel Drown    registerCmd(new ClatdCmd());
1845c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    registerCmd(new NetworkCommand());
1859d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
186a0efaece8c05370f201efe099a537ceb014c6fdfSzymon Jakubczak    if (!sNetCtrl)
187f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        sNetCtrl = new NetworkController();
1889d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!sTetherCtrl)
18987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        sTetherCtrl = new TetherController();
1909ff78fb7da7158f5bd7c86d89a842691820259cfSan Mehat    if (!sNatCtrl)
19187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        sNatCtrl = new NatController();
192d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!sPppCtrl)
193d5573d34c8fac49e16b20cf144486125bf940086San Mehat        sPppCtrl = new PppController();
1945af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    if (!sSoftapCtrl)
1955af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        sSoftapCtrl = new SoftapController();
1964a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (!sBandwidthCtrl)
1974a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        sBandwidthCtrl = new BandwidthController();
1980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!sIdletimerCtrl)
1990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        sIdletimerCtrl = new IdletimerController();
20089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    if (!sResolverCtrl)
20189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        sResolverCtrl = new ResolverController();
202d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!sFirewallCtrl)
203d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        sFirewallCtrl = new FirewallController();
2042eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt    if (!sInterfaceCtrl)
2052eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt        sInterfaceCtrl = new InterfaceController();
2060da73fcecc30140439f856118056df8908609627Daniel Drown    if (!sClatdCtrl)
20784c1d035fdef996602ab8878d952c4fcb1f6963dPaul Jensen        sClatdCtrl = new ClatdController(sNetCtrl);
2080031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2090031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2108e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * This is the only time we touch top-level chains in iptables; controllers
2118e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * should only mutate rules inside of their children chains, as created by
2128e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * the constants above.
2138e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     *
2148e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * Modules should never ACCEPT packets (except in well-justified cases);
2158e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * they should instead defer to any remaining modules using RETURN, or
2168e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey     * otherwise DROP/REJECT.
2170031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2188e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
2198e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    // Create chains for children modules
2208e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
2218e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
2228e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
2238e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
2248e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
225e8164ddc8204b626c1144a0a504754bf6622c6fdLorenzo Colitti    createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
2268e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
2278e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
2288e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
2298e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey    // Let each module setup their child chains
2300031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    setupOemIptablesHook();
2318e188ed5c989ddcc07f0f5e9839493c22d17e7b6Jeff Sharkey
232d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    /* When enabled, DROPs all packets except those matching rules. */
233d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    sFirewallCtrl->setupIptablesHooks();
234d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
2350031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /* Does DROPs in FORWARD by default */
2360031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    sNatCtrl->setupIptablesHooks();
2370031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2380031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Does REJECT in INPUT, OUTPUT. Does counting also.
2390031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * No DROP/REJECT allowed later in netfilter-flow hook order.
2400031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2410031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    sBandwidthCtrl->setupIptablesHooks();
2420031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    /*
2430031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * Counts in nat: PREROUTING, POSTROUTING.
2440031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     * No DROP/REJECT allowed later in netfilter-flow hook order.
2450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall     */
2460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    sIdletimerCtrl->setupIptablesHooks();
2470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
2480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    sBandwidthCtrl->enableBandwidthControl(false);
2492251c0fbcf24a9c8fd77b23851f60304087bab2bChad Brubaker
25087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
251f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
252f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
253d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
254d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
2555c1b8af16dbbc20c89aaca2f93e725e12b16d055San MehatCommandListener::InterfaceCmd::InterfaceCmd() :
2565c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                 NetdCommand("interface") {
257d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
258d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
2595c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehatint CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
260d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
2615c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    if (argc < 2) {
2625c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
2635c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        return 0;
2645c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    }
2655c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2665c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    if (!strcmp(argv[1], "list")) {
2675c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        DIR *d;
2685c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        struct dirent *de;
2695c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2705c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (!(d = opendir("/sys/class/net"))) {
2715c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
2725c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
2735c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
2745c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2755c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        while((de = readdir(d))) {
2765c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            if (de->d_name[0] == '.')
2775c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                continue;
2785c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
2795c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
2805c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        closedir(d);
2815c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
2825c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        return 0;
2835c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    } else {
2845c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        /*
2855c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat         * These commands take a minimum of 3 arguments
2865c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat         */
2875c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (argc < 3) {
2885c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
2895c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
2905c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
291e019b65925217bcc3ad9b662aa3125f0593057afRobert Greenwalt
2925c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        if (!strcmp(argv[1], "getcfg")) {
2931d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            struct in_addr addr;
2941d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            int prefixLength;
2955c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            unsigned char hwaddr[6];
2965c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            unsigned flags = 0;
2975c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
2985c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ifc_init();
2995c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            memset(hwaddr, 0, sizeof(hwaddr));
3005c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3011d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
3025c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
303e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                ifc_close();
3045c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                return 0;
3055c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3065c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3075c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
3080e76b761a1514d5182675dd7b7d33725f62d6bc5Steve Block                ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
3095c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3105c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3115c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *addr_s = strdup(inet_ntoa(addr));
3125c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;
3135c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3145c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            updown =  (flags & IFF_UP)           ? "up" : "down";
3155c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
3165c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
3175c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
3185c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            running = (flags & IFF_RUNNING)      ? " running" : "";
3195c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";
3205c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3215c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *flag_s;
3225c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
32331ea0b03afeedd17f703b7a6d1e5c9feb2d6000dJeff Sharkey            asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);
3245c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3255c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            char *msg = NULL;
3261d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
3275c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
3281d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt                     addr_s, prefixLength, flag_s);
3295c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
33001fed783828b592cda3b774deea4099a9e690e3dSan Mehat            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);
3315c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3325c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(addr_s);
3335c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(flag_s);
3345c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            free(msg);
335e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
336e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            ifc_close();
3375c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
3385c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        } else if (!strcmp(argv[1], "setcfg")) {
339778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            // arglist: iface [addr prefixLength] flags
340778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            if (argc < 4) {
3415c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
3425c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                return 0;
3435c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3447b984e3f7e724f8a3547a707210319f3d479f261Steve Block            ALOGD("Setting iface cfg");
3455c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3461d93e170f13b221362ee268fdc94b25db06c21c9Robert Greenwalt            struct in_addr addr;
347778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            int index = 5;
3485c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3495c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            ifc_init();
3505c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
351778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            if (!inet_aton(argv[3], &addr)) {
352778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                // Handle flags only case
353778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                index = 3;
354778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            } else {
355778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                if (ifc_set_addr(argv[2], addr.s_addr)) {
356778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
357778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                    ifc_close();
358778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                    return 0;
359778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                }
360778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt
361778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                // Set prefix length on a non zero address
362778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
363778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                   cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
364778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                   ifc_close();
365778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt                   return 0;
366778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt               }
3675c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
3685c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat
3695c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            /* Process flags */
370778ffe4d3dcab5453b57a0d960ea7f066374b953Dmitry Shmidt            for (int i = index; i < argc; i++) {
371e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                char *flag = argv[i];
372e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                if (!strcmp(flag, "up")) {
3737b984e3f7e724f8a3547a707210319f3d479f261Steve Block                    ALOGD("Trying to bring up %s", argv[2]);
3745c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    if (ifc_up(argv[2])) {
3755ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                        ALOGE("Error upping interface");
3765c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
377e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                        ifc_close();
3785c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        return 0;
3795c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    }
380e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "down")) {
3817b984e3f7e724f8a3547a707210319f3d479f261Steve Block                    ALOGD("Trying to bring down %s", argv[2]);
3825c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    if (ifc_down(argv[2])) {
3835ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block                        ALOGE("Error downing interface");
3845c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
385e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                        ifc_close();
3865c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                        return 0;
3875c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    }
388e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "broadcast")) {
3897c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
390e7b9422f0dc7a18041536c63efe74c7095496258Robert Greenwalt                } else if (!strcmp(flag, "multicast")) {
3917c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3927c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "running")) {
3937c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3947c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "loopback")) {
3957c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3967c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                } else if (!strcmp(flag, "point-to-point")) {
3977c2ddd84ec501aaedb806a3ecec5de00d618a036Jeff Sharkey                    // currently ignored
3985c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                } else {
3995c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
400e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff                    ifc_close();
4015c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                    return 0;
4025c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat                }
4035c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            }
404e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
4055c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
406e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            ifc_close();
407e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            return 0;
408e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff        } else if (!strcmp(argv[1], "clearaddrs")) {
409e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            // arglist: iface
4107b984e3f7e724f8a3547a707210319f3d479f261Steve Block            ALOGD("Clearing all IP addresses on %s", argv[2]);
411e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff
4121ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti            ifc_clear_addresses(argv[2]);
4131ed47c4a016e420a855ee46922e512150245ff61Lorenzo Colitti
414e734edd35d8d02da96330d77420650c044a12527Irfan Sheriff            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
4155c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
41632a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff        } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
41732a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            if (argc != 4) {
41832a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::CommandSyntaxError,
41932a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
42032a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        false);
42132a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                return 0;
42232a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
42370afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            int enable = !strncmp(argv[3], "enable", 7);
42470afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            if (sInterfaceCtrl->setIPv6PrivacyExtensions(argv[2], enable) == 0) {
42570afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
42670afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            } else {
42732a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::OperationFailed,
42832a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                        "Failed to set ipv6 privacy extensions", true);
42932a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
430c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            return 0;
431c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync        } else if (!strcmp(argv[1], "ipv6")) {
432c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            if (argc != 4) {
433c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                cli->sendMsg(ResponseCode::CommandSyntaxError,
434c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        "Usage: interface ipv6 <interface> <enable|disable>",
435c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        false);
436c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                return 0;
437c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync            }
438c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync
43970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            int enable = !strncmp(argv[3], "enable", 7);
44070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            if (sInterfaceCtrl->setEnableIPv6(argv[2], enable) == 0) {
44170afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti                cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
44270afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti            } else {
44332a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff                cli->sendMsg(ResponseCode::OperationFailed,
444c1b3870147acd0dd42e2e767df08b4d64d5d2423repo sync                        "Failed to change IPv6 state", true);
44532a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            }
44632a9dc6f484deb3462d11084caca21e3f1f662b2Irfan Sheriff            return 0;
4476d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt        } else if (!strcmp(argv[1], "setmtu")) {
4486d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            if (argc != 4) {
4496d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::CommandSyntaxError,
4506d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                        "Usage: interface setmtu <interface> <val>", false);
4516d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                return 0;
4526d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            }
4536d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            if (sInterfaceCtrl->setMtu(argv[2], argv[3]) == 0) {
4546d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::CommandOkay, "MTU changed", false);
4556d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            } else {
4566d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                cli->sendMsg(ResponseCode::OperationFailed,
4576d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt                        "Failed to get MTU", true);
4586d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            }
4596d6c0e6f1164e3182538cb48c2b95d90a2eb780cDmitry Shmidt            return 0;
4605c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        } else {
4615c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
4625c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat            return 0;
4635c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat        }
4645c1b8af16dbbc20c89aaca2f93e725e12b16d055San Mehat    }
465d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
466d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
467d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
4684a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
469d5573d34c8fac49e16b20cf144486125bf940086San MehatCommandListener::ListTtysCmd::ListTtysCmd() :
470d5573d34c8fac49e16b20cf144486125bf940086San Mehat                 NetdCommand("list_ttys") {
471d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
472d5573d34c8fac49e16b20cf144486125bf940086San Mehat
473d5573d34c8fac49e16b20cf144486125bf940086San Mehatint CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
47456afacf838d24cf8e54d2cf0d8ab9182ab704125Sreeram Ramachandran                                             int /* argc */, char ** /* argv */) {
475d5573d34c8fac49e16b20cf144486125bf940086San Mehat    TtyCollection *tlist = sPppCtrl->getTtyList();
476d5573d34c8fac49e16b20cf144486125bf940086San Mehat    TtyCollection::iterator it;
477d5573d34c8fac49e16b20cf144486125bf940086San Mehat
478d5573d34c8fac49e16b20cf144486125bf940086San Mehat    for (it = tlist->begin(); it != tlist->end(); ++it) {
479d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
480d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
481d5573d34c8fac49e16b20cf144486125bf940086San Mehat
482d5573d34c8fac49e16b20cf144486125bf940086San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
483d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
484d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
485d5573d34c8fac49e16b20cf144486125bf940086San Mehat
486d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::IpFwdCmd::IpFwdCmd() :
487d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("ipfwd") {
488d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
489d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
490d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
491d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
4929d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    int rc = 0;
4939d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
4949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (argc < 2) {
4959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
4969d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
4979d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
4989d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
4999d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!strcmp(argv[1], "status")) {
5009d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        char *tmp = NULL;
5019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
5029d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
5039d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
5049d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        free(tmp);
5059d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
5069d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else if (!strcmp(argv[1], "enable")) {
5079d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        rc = sTetherCtrl->setIpFwdEnabled(true);
5089d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else if (!strcmp(argv[1], "disable")) {
5099d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        rc = sTetherCtrl->setIpFwdEnabled(false);
5109d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
5119d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
5129d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
5139d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
5149d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
5159d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!rc) {
5169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
5179d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
5189d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
5199d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
520d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
521d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
522d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
523d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
524d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::TetherCmd::TetherCmd() :
525d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("tether") {
526d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
527d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
528d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint CommandListener::TetherCmd::runCommand(SocketClient *cli,
529d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
5309d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    int rc = 0;
5319d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
532d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (argc < 2) {
533d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
534d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return 0;
535d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
536d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
5379d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!strcmp(argv[1], "stop")) {
5389d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        rc = sTetherCtrl->stopTethering();
539d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    } else if (!strcmp(argv[1], "status")) {
5409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        char *tmp = NULL;
5419d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
5429d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        asprintf(&tmp, "Tethering services %s",
5439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
5449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
5459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        free(tmp);
546d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return 0;
54736971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall    } else if (argc == 3) {
54836971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall        if (!strcmp(argv[1], "interface") && !strcmp(argv[2], "list")) {
54936971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
55036971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            InterfaceCollection::iterator it;
55136971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            for (it = ilist->begin(); it != ilist->end(); ++it) {
55236971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall                cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
55336971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            }
55436971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall        } else if (!strcmp(argv[1], "dns") && !strcmp(argv[2], "list")) {
555667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti            char netIdStr[UINT32_STRLEN];
556667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti            snprintf(netIdStr, sizeof(netIdStr), "%u", sTetherCtrl->getDnsNetId());
557667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti            cli->sendMsg(ResponseCode::TetherDnsFwdNetIdResult, netIdStr, false);
558667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti
55936971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
56036971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            NetAddressCollection::iterator it;
56136971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall
56236971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            for (it = dlist->begin(); it != dlist->end(); ++it) {
56336971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall                cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
56436971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            }
56520f95ed9db048261c18bbeb152d3204d9cbb58f1JP Abgrall        }
5669d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
5679d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        /*
5689d10b341a0ba46f108cb96e46691197d778cbc06San Mehat         * These commands take a minimum of 4 arguments
5699d10b341a0ba46f108cb96e46691197d778cbc06San Mehat         */
5709d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        if (argc < 4) {
5719d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
5729d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            return 0;
5739d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        }
5749d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
5759d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        if (!strcmp(argv[1], "start")) {
5763208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            if (argc % 2 == 1) {
5773208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                cli->sendMsg(ResponseCode::CommandSyntaxError, "Bad number of arguments", false);
5789d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
5799d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
5803208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt
5813208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            int num_addrs = argc - 2;
5823208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            int arg_index = 2;
5833208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            int array_index = 0;
5843208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            in_addr *addrs = (in_addr *)malloc(sizeof(in_addr) * num_addrs);
5853208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            while (array_index < num_addrs) {
5863208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                if (!inet_aton(argv[arg_index++], &(addrs[array_index++]))) {
5873208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                    cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
5883208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                    free(addrs);
5893208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                    return 0;
5903208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt                }
5919d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
5923208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            rc = sTetherCtrl->startTethering(num_addrs, addrs);
5933208ea0b6cce28e7aef8459d548fd86df329e34fRobert Greenwalt            free(addrs);
5949d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else if (!strcmp(argv[1], "interface")) {
5959d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            if (!strcmp(argv[2], "add")) {
5969d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                rc = sTetherCtrl->tetherInterface(argv[3]);
5979d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else if (!strcmp(argv[2], "remove")) {
5989d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                rc = sTetherCtrl->untetherInterface(argv[3]);
59920f95ed9db048261c18bbeb152d3204d9cbb58f1JP Abgrall            /* else if (!strcmp(argv[2], "list")) handled above */
6009d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else {
6019d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                cli->sendMsg(ResponseCode::CommandParameterError,
6029d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                             "Unknown tether interface operation", false);
6039d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
6049d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
6059d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else if (!strcmp(argv[1], "dns")) {
6069d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            if (!strcmp(argv[2], "set")) {
607667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                if (argc < 5) {
608667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                    cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
609667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                    return 0;
610667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                }
611667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                unsigned netId = stringToNetId(argv[3]);
612667c477133318e4779819d34364194c8e5eaf19cLorenzo Colitti                rc = sTetherCtrl->setDnsForwarders(netId, &argv[4], argc - 4);
61336971a687bf3a6edc2bf5af8a8b2a3176e7d4691JP Abgrall            /* else if (!strcmp(argv[2], "list")) handled above */
6149d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            } else {
6159d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                cli->sendMsg(ResponseCode::CommandParameterError,
6169d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                             "Unknown tether interface operation", false);
6179d10b341a0ba46f108cb96e46691197d778cbc06San Mehat                return 0;
6189d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            }
6199d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        } else {
6209d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
6219d10b341a0ba46f108cb96e46691197d778cbc06San Mehat            return 0;
6229d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        }
6239d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6249d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
6259d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!rc) {
6269d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
6279d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6289d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
629d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
630d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
631d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
632d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
633d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
634d18304287dbabc7835be771400b85d4ae8b63de6San MehatCommandListener::NatCmd::NatCmd() :
635d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                 NetdCommand("nat") {
636d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
637d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
638d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint CommandListener::NatCmd::runCommand(SocketClient *cli,
639d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                                                      int argc, char **argv) {
6409d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    int rc = 0;
6419d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
642fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt    if (argc < 5) {
6439d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
6449d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
6459d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6469d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
64787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    //  0     1       2        3
64887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // nat  enable intiface extiface
64987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // nat disable intiface extiface
65087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(argv[1], "enable") && argc >= 4) {
65187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        rc = sNatCtrl->enableNat(argv[2], argv[3]);
652c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if(!rc) {
653c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            /* Ignore ifaces for now. */
654c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
655c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
65687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    } else if (!strcmp(argv[1], "disable") && argc >= 4) {
657f7bf29c8a37d65e132a4dceb7c5a4200ed5c3d79Robert Greenwalt        /* Ignore ifaces for now. */
658fc97b82e02979f246d56a4bfd60e4aab8686d3f6Robert Greenwalt        rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
65987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        rc |= sNatCtrl->disableNat(argv[2], argv[3]);
6609d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6619d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
6629d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        return 0;
6639d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
6649d10b341a0ba46f108cb96e46691197d778cbc06San Mehat
6659d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    if (!rc) {
6669d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
6679d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    } else {
6689d10b341a0ba46f108cb96e46691197d778cbc06San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
6699d10b341a0ba46f108cb96e46691197d778cbc06San Mehat    }
670d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
671d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
672d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
673d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
674d5573d34c8fac49e16b20cf144486125bf940086San MehatCommandListener::PppdCmd::PppdCmd() :
675d5573d34c8fac49e16b20cf144486125bf940086San Mehat                 NetdCommand("pppd") {
676d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
677d5573d34c8fac49e16b20cf144486125bf940086San Mehat
678d5573d34c8fac49e16b20cf144486125bf940086San Mehatint CommandListener::PppdCmd::runCommand(SocketClient *cli,
679d5573d34c8fac49e16b20cf144486125bf940086San Mehat                                                      int argc, char **argv) {
680d5573d34c8fac49e16b20cf144486125bf940086San Mehat    int rc = 0;
681d5573d34c8fac49e16b20cf144486125bf940086San Mehat
682d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (argc < 3) {
683d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
684d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
685d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
686d5573d34c8fac49e16b20cf144486125bf940086San Mehat
687d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!strcmp(argv[1], "attach")) {
68874d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        struct in_addr l, r, dns1, dns2;
68974d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt
6901c4a77955acdb730d017b15e9a92ca511e6ca106Wang Liyong        memset(&dns1, 0, sizeof(struct in_addr));
6911c4a77955acdb730d017b15e9a92ca511e6ca106Wang Liyong        memset(&dns2, 0, sizeof(struct in_addr));
692d5573d34c8fac49e16b20cf144486125bf940086San Mehat
693d5573d34c8fac49e16b20cf144486125bf940086San Mehat        if (!inet_aton(argv[3], &l)) {
694d5573d34c8fac49e16b20cf144486125bf940086San Mehat            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
695d5573d34c8fac49e16b20cf144486125bf940086San Mehat            return 0;
696d5573d34c8fac49e16b20cf144486125bf940086San Mehat        }
697d5573d34c8fac49e16b20cf144486125bf940086San Mehat        if (!inet_aton(argv[4], &r)) {
698d5573d34c8fac49e16b20cf144486125bf940086San Mehat            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
699d5573d34c8fac49e16b20cf144486125bf940086San Mehat            return 0;
700d5573d34c8fac49e16b20cf144486125bf940086San Mehat        }
70174d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        if ((argc > 3) && (!inet_aton(argv[5], &dns1))) {
70274d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns1 address", false);
70374d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            return 0;
70474d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        }
70574d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        if ((argc > 4) && (!inet_aton(argv[6], &dns2))) {
70674d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid dns2 address", false);
70774d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt            return 0;
70874d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        }
70974d8fdd307275bfdf95dcf61d9e6366e87da24ecRobert Greenwalt        rc = sPppCtrl->attachPppd(argv[2], l, r, dns1, dns2);
710d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else if (!strcmp(argv[1], "detach")) {
711d5573d34c8fac49e16b20cf144486125bf940086San Mehat        rc = sPppCtrl->detachPppd(argv[2]);
712d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else {
713d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
714d5573d34c8fac49e16b20cf144486125bf940086San Mehat        return 0;
715d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
716d5573d34c8fac49e16b20cf144486125bf940086San Mehat
717d5573d34c8fac49e16b20cf144486125bf940086San Mehat    if (!rc) {
718d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
719d5573d34c8fac49e16b20cf144486125bf940086San Mehat    } else {
720d5573d34c8fac49e16b20cf144486125bf940086San Mehat        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
721d5573d34c8fac49e16b20cf144486125bf940086San Mehat    }
722d5573d34c8fac49e16b20cf144486125bf940086San Mehat
723d5573d34c8fac49e16b20cf144486125bf940086San Mehat    return 0;
724d5573d34c8fac49e16b20cf144486125bf940086San Mehat}
7251bdac9e98c1ef37ba568b6cf23bfbc09cfe6bf15San Mehat
7265af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry ShmidtCommandListener::SoftapCmd::SoftapCmd() :
7275af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt                 NetdCommand("softap") {
7285af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt}
7295af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7305af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidtint CommandListener::SoftapCmd::runCommand(SocketClient *cli,
7315af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt                                        int argc, char **argv) {
73225753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    int rc = ResponseCode::SoftapStatusResult;
733666fe255fa581965d2835bd581cd5a8959411067Dmitry Shmidt    char *retbuf = NULL;
7345af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
73525753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    if (sSoftapCtrl == NULL) {
73625753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(ResponseCode::ServiceStartFailed, "SoftAP is not available", false);
73725753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      return -1;
73825753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    }
7395af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    if (argc < 2) {
74025753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(ResponseCode::CommandSyntaxError,
74125753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy                     "Missing argument in a SoftAP command", false);
7425af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7435af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    }
7445af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7457e9eb7b48345af69283afa7ca58d3be0a329931bIrfan Sheriff    if (!strcmp(argv[1], "startap")) {
746c3539e22bd7a59a12542b9ad961f7d7f0db9a8dfDmitry Shmidt        rc = sSoftapCtrl->startSoftap();
747c3539e22bd7a59a12542b9ad961f7d7f0db9a8dfDmitry Shmidt    } else if (!strcmp(argv[1], "stopap")) {
7485af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        rc = sSoftapCtrl->stopSoftap();
74931fd6c5f3e9c39a13b028718dba5921a4300988cDmitry Shmidt    } else if (!strcmp(argv[1], "fwreload")) {
75031fd6c5f3e9c39a13b028718dba5921a4300988cDmitry Shmidt        rc = sSoftapCtrl->fwReloadSoftap(argc, argv);
7515af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else if (!strcmp(argv[1], "status")) {
75225753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        asprintf(&retbuf, "Softap service %s running",
75325753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy                 (sSoftapCtrl->isSoftapStarted() ? "is" : "is not"));
75425753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(rc, retbuf, false);
755666fe255fa581965d2835bd581cd5a8959411067Dmitry Shmidt        free(retbuf);
7565af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7575af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else if (!strcmp(argv[1], "set")) {
7585af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        rc = sSoftapCtrl->setSoftap(argc, argv);
7595af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    } else {
76025753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unrecognized SoftAP command", false);
7615af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt        return 0;
7625af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    }
7635af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
76425753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    if (rc >= 400 && rc < 600)
76525753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(rc, "SoftAP command has failed", false);
76625753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy    else
76725753d500d9ef6ee04dad43ffa27287a6dc959acSasha Levitskiy      cli->sendMsg(rc, "Ok", false);
7685af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt
7695af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt    return 0;
7705af38c360587ca2eef0badf6137ccf018f8cd4aaDmitry Shmidt}
7713e6ba3ce1abda6071d5b01f53ca6039bb7b5e2d3Robert Greenwalt
77289c1e975f0c03997808d35c7be10b244c5309f9fMattias FalkCommandListener::ResolverCmd::ResolverCmd() :
77389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        NetdCommand("resolver") {
77489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk}
77589c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
776938ab2acc65ea12e84d66e5bc3f8166482d2165bSasha Levitskiyint CommandListener::ResolverCmd::runCommand(SocketClient *cli, int argc, char **margv) {
77789c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    int rc = 0;
778938ab2acc65ea12e84d66e5bc3f8166482d2165bSasha Levitskiy    const char **argv = const_cast<const char **>(margv);
77989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
78089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    if (argc < 2) {
78189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandSyntaxError, "Resolver missing arguments", false);
78289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        return 0;
78389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
78489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
78535c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen    if (!strcmp(argv[1], "setnetdns")) {
78635c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen        // "resolver setnetdns <netId> <domains> <dns1> <dns2> ..."
787dd3e46758b500d5e8c61ed30f7402e8538df7e06Robert Greenwalt        if (argc >= 5) {
78835c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen            rc = sResolverCtrl->setDnsServers(strtoul(argv[2], NULL, 0), argv[3], &argv[4], argc - 4);
78989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        } else {
79089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk            cli->sendMsg(ResponseCode::CommandSyntaxError,
79135c77e32b27694a138e9a7877b9a5b474441c58bPaul Jensen                    "Wrong number of arguments to resolver setnetdns", false);
79289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk            return 0;
79389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        }
7946a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen    } else if (!strcmp(argv[1], "flushnet")) { // "resolver flushnet <netId>"
7956a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen        if (argc == 3) {
7966a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen            rc = sResolverCtrl->flushDnsCache(strtoul(argv[2], NULL, 0));
7976a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen        } else {
7986a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen            cli->sendMsg(ResponseCode::CommandSyntaxError,
7996a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen                    "Wrong number of arguments to resolver flushnet", false);
8006a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen            return 0;
8016a46f3384b3f48e6ef77a83a5e058a47a2939a0dPaul Jensen        }
80289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    } else {
80389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandSyntaxError,"Resolver unknown command", false);
80489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        return 0;
80589c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
80689c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
80789c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    if (!rc) {
80889c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::CommandOkay, "Resolver command succeeded", false);
80989c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    } else {
81089c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk        cli->sendMsg(ResponseCode::OperationFailed, "Resolver command failed", true);
81189c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    }
81289c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
81389c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk    return 0;
81489c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk}
81589c1e975f0c03997808d35c7be10b244c5309f9fMattias Falk
8164a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP AbgrallCommandListener::BandwidthControlCmd::BandwidthControlCmd() :
8170dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall    NetdCommand("bandwidth") {
8184a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
8194a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
820db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericSyntaxError(SocketClient *cli, const char *usageMsg) {
821db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    char *msg;
822db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    asprintf(&msg, "Usage: bandwidth %s", usageMsg);
823db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, msg, false);
824db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    free(msg);
825db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
826db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
827db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericOkFail(SocketClient *cli, int cond) {
828db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!cond) {
829db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Bandwidth command succeeeded", false);
830db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    } else {
831db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        cli->sendMsg(ResponseCode::OperationFailed, "Bandwidth command failed", false);
832db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
833db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
834db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
835db7da58e8d2aa021060098057f944ef754be06e3JP Abgrallvoid CommandListener::BandwidthControlCmd::sendGenericOpFailed(SocketClient *cli, const char *errMsg) {
836db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::OperationFailed, errMsg, false);
837db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall}
838db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
839fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrallint CommandListener::BandwidthControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
8404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (argc < 2) {
841db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericSyntaxError(cli, "<cmds> <args...>");
8424a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall        return 0;
8434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
8444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
8453fb42e026ffebab2c8f282e42501040121e32d83Steve Block    ALOGV("bwctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
846db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
8474a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    if (!strcmp(argv[1], "enable")) {
8480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        int rc = sBandwidthCtrl->enableBandwidthControl(true);
849db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
850db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
851db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
852db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
853db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "disable")) {
854db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->disableBandwidthControl();
855db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
856db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
8570dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
858db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
859db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removequota") || !strcmp(argv[1], "rq")) {
860fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc != 3) {
861db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removequota <interface>");
862fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
863fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
864db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[2]);
865db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
866db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
867fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
868db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
869db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "getquota") || !strcmp(argv[1], "gq")) {
8708a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        int64_t bytes;
8718a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
872db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "getquota");
8738a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
8748a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
875db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->getInterfaceSharedQuota(&bytes);
8768a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (rc) {
877db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericOpFailed(cli, "Failed to get quota");
8788a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
8798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
880db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
8818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        char *msg;
8827776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev        asprintf(&msg, "%" PRId64, bytes);
8838a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
8848a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(msg);
885db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
8868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
887db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
888db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "getiquota") || !strcmp(argv[1], "giq")) {
8898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        int64_t bytes;
8908a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
891db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "getiquota <iface>");
8928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
8938a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
894db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
895db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->getInterfaceQuota(argv[2], &bytes);
8968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (rc) {
897db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericOpFailed(cli, "Failed to get quota");
8988a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
8998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
9008a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        char *msg;
9017776cea21f88c4c01eba509db09bc2ccaa28ed5dSynergyDev        asprintf(&msg, "%" PRId64, bytes);
9028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        cli->sendMsg(ResponseCode::QuotaCounterResult, msg, false);
9038a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        free(msg);
904db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9058a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
906db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
907db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setquota") || !strcmp(argv[1], "sq")) {
908fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc != 4) {
909db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setquota <interface> <bytes>");
910fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
911fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
912db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[2], atoll(argv[3]));
913db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
914db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
915db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
916db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setquotas") || !strcmp(argv[1], "sqs")) {
917db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc;
918fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 4) {
919db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setquotas <bytes> <interface> ...");
920fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
921fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
922db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9238a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        for (int q = 3; argc >= 4; q++, argc--) {
9240dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            rc = sBandwidthCtrl->setInterfaceSharedQuota(argv[q], atoll(argv[2]));
9250dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            if (rc) {
9260dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                char *msg;
9270dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                asprintf(&msg, "bandwidth setquotas %s %s failed", argv[2], argv[q]);
9280dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                cli->sendMsg(ResponseCode::OperationFailed,
9290dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                             msg, false);
9300dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                free(msg);
931db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                return 0;
9320dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            }
9330dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
934db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
935db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9360dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
937db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
938db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removequotas") || !strcmp(argv[1], "rqs")) {
939db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc;
9400dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc < 3) {
941db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removequotas <interface> ...");
9420dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
9430dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
944db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
9458a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        for (int q = 2; argc >= 3; q++, argc--) {
9460dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            rc = sBandwidthCtrl->removeInterfaceSharedQuota(argv[q]);
9470dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            if (rc) {
9480dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                char *msg;
9490dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                asprintf(&msg, "bandwidth removequotas %s failed", argv[q]);
9500dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                cli->sendMsg(ResponseCode::OperationFailed,
9510dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                             msg, false);
9520dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall                free(msg);
953db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall                return 0;
9540dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            }
9550dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
956db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
957db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9580dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
959db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
960db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeiquota") || !strcmp(argv[1], "riq")) {
9610dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc != 3) {
962db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeiquota <interface>");
9630dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
9640dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
965db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeInterfaceQuota(argv[2]);
966db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
967db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
9680dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall
969db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
970db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setiquota") || !strcmp(argv[1], "siq")) {
9710dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        if (argc != 4) {
972db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setiquota <interface> <bytes>");
9730dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall            return 0;
9740dad7c2f1f6994fbe5e85b9e1fc72d29d6453211JP Abgrall        }
975db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->setInterfaceQuota(argv[2], atoll(argv[3]));
976db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
977db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
978fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
979db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
980db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {
981fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 3) {
982db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");
9834a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall            return 0;
984fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
985db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
986db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
987db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
988db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
989fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
990db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
991db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removenaughtyapps") || !strcmp(argv[1], "rna")) {
992fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        if (argc < 3) {
993db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removenaughtyapps <appUid> ...");
994fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall            return 0;
995fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        }
996db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeNaughtyApps(argc - 2, argv + 2);
997db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
998db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
999e478873947f995e44e8c559342462c177a420ae0JP Abgrall    }
1000e478873947f995e44e8c559342462c177a420ae0JP Abgrall    if (!strcmp(argv[1], "happybox")) {
1001e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (argc < 3) {
1002e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericSyntaxError(cli, "happybox (enable | disable)");
1003e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1004e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
1005e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (!strcmp(argv[2], "enable")) {
1006e478873947f995e44e8c559342462c177a420ae0JP Abgrall            int rc = sBandwidthCtrl->enableHappyBox();
1007e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericOkFail(cli, rc);
1008e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1009fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall
1010e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
1011e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (!strcmp(argv[2], "disable")) {
1012e478873947f995e44e8c559342462c177a420ae0JP Abgrall            int rc = sBandwidthCtrl->disableHappyBox();
1013e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericOkFail(cli, rc);
1014e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1015e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
1016e478873947f995e44e8c559342462c177a420ae0JP Abgrall        sendGenericSyntaxError(cli, "happybox (enable | disable)");
1017e478873947f995e44e8c559342462c177a420ae0JP Abgrall        return 0;
1018e478873947f995e44e8c559342462c177a420ae0JP Abgrall    }
1019e478873947f995e44e8c559342462c177a420ae0JP Abgrall    if (!strcmp(argv[1], "addniceapps") || !strcmp(argv[1], "aha")) {
1020e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (argc < 3) {
1021e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericSyntaxError(cli, "addniceapps <appUid> ...");
1022e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1023e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
1024e478873947f995e44e8c559342462c177a420ae0JP Abgrall        int rc = sBandwidthCtrl->addNiceApps(argc - 2, argv + 2);
1025e478873947f995e44e8c559342462c177a420ae0JP Abgrall        sendGenericOkFail(cli, rc);
1026e478873947f995e44e8c559342462c177a420ae0JP Abgrall        return 0;
1027e478873947f995e44e8c559342462c177a420ae0JP Abgrall    }
1028e478873947f995e44e8c559342462c177a420ae0JP Abgrall    if (!strcmp(argv[1], "removeniceapps") || !strcmp(argv[1], "rha")) {
1029e478873947f995e44e8c559342462c177a420ae0JP Abgrall        if (argc < 3) {
1030e478873947f995e44e8c559342462c177a420ae0JP Abgrall            sendGenericSyntaxError(cli, "removeniceapps <appUid> ...");
1031e478873947f995e44e8c559342462c177a420ae0JP Abgrall            return 0;
1032e478873947f995e44e8c559342462c177a420ae0JP Abgrall        }
1033e478873947f995e44e8c559342462c177a420ae0JP Abgrall        int rc = sBandwidthCtrl->removeNiceApps(argc - 2, argv + 2);
1034e478873947f995e44e8c559342462c177a420ae0JP Abgrall        sendGenericOkFail(cli, rc);
1035e478873947f995e44e8c559342462c177a420ae0JP Abgrall        return 0;
1036db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1037db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setglobalalert") || !strcmp(argv[1], "sga")) {
10388a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1039db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setglobalalert <bytes>");
10408a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10418a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1042db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->setGlobalAlert(atoll(argv[2]));
1043db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1044db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
1045db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1046c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!strcmp(argv[1], "debugsettetherglobalalert") || !strcmp(argv[1], "dstga")) {
1047c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (argc != 4) {
1048c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            sendGenericSyntaxError(cli, "debugsettetherglobalalert <interface0> <interface1>");
1049c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            return 0;
1050c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
1051c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        /* We ignore the interfaces for now. */
1052c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        int rc = sBandwidthCtrl->setGlobalAlertInForwardChain();
1053c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        sendGenericOkFail(cli, rc);
1054c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
1055c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
1056c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
1057db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeglobalalert") || !strcmp(argv[1], "rga")) {
10588a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
1059db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeglobalalert");
10608a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10618a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1062db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeGlobalAlert();
1063db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1064db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10658a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1066db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1067c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    if (!strcmp(argv[1], "debugremovetetherglobalalert") || !strcmp(argv[1], "drtga")) {
1068c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        if (argc != 4) {
1069c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            sendGenericSyntaxError(cli, "debugremovetetherglobalalert <interface0> <interface1>");
1070c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall            return 0;
1071c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        }
1072c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        /* We ignore the interfaces for now. */
1073c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        int rc = sBandwidthCtrl->removeGlobalAlertInForwardChain();
1074c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        sendGenericOkFail(cli, rc);
1075c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall        return 0;
1076c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall
1077c6c673496184bed6d62cf92a6fc7ed43fd94acd5JP Abgrall    }
1078db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setsharedalert") || !strcmp(argv[1], "ssa")) {
10798a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1080db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setsharedalert <bytes>");
10818a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10828a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1083db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->setSharedAlert(atoll(argv[2]));
1084db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1085db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10868a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1087db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1088db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removesharedalert") || !strcmp(argv[1], "rsa")) {
10898a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 2) {
1090db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removesharedalert");
10918a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
10928a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1093db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeSharedAlert();
1094db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1095db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
10968a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1097db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1098db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "setinterfacealert") || !strcmp(argv[1], "sia")) {
10998a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 4) {
1100db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "setinterfacealert <interface> <bytes>");
11018a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11028a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1103db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->setInterfaceAlert(argv[2], atoll(argv[3]));
1104db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1105db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11068a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall
1107db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    }
1108db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "removeinterfacealert") || !strcmp(argv[1], "ria")) {
11098a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        if (argc != 3) {
1110db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            sendGenericSyntaxError(cli, "removeinterfacealert <interface>");
11118a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall            return 0;
11128a93272255f1b7e3083a97e1e28ddf675c0c7fb0JP Abgrall        }
1113db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        int rc = sBandwidthCtrl->removeInterfaceAlert(argv[2]);
1114db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        sendGenericOkFail(cli, rc);
1115fa6f46d3370ae5475fc3bc8273bbe04ee7348d60JP Abgrall        return 0;
1116db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
11174a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
1118db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    if (!strcmp(argv[1], "gettetherstats") || !strcmp(argv[1], "gts")) {
1119db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        BandwidthController::TetherStats tetherStats;
1120a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall        std::string extraProcessingInfo = "";
1121baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        if (argc < 2 || argc > 4) {
1122baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall            sendGenericSyntaxError(cli, "gettetherstats [<intInterface> <extInterface>]");
1123db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall            return 0;
1124db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1125baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        tetherStats.intIface = argc > 2 ? argv[2] : "";
1126baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        tetherStats.extIface = argc > 3 ? argv[3] : "";
1127f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        // No filtering requested and there are no interface pairs to lookup.
1128f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        if (argc <= 2 && sNatCtrl->ifacePairList.empty()) {
1129f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            cli->sendMsg(ResponseCode::CommandOkay, "Tethering stats list completed", false);
1130f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall            return 0;
1131f3cc83fa5b14455589af83b20998885452cdc46dJP Abgrall        }
1132baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall        int rc = sBandwidthCtrl->getTetherStats(cli, tetherStats, extraProcessingInfo);
1133db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        if (rc) {
1134a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                extraProcessingInfo.insert(0, "Failed to get tethering stats.\n");
1135a2a64f004f1677daf16b0b03d589d6572ec547c2JP Abgrall                sendGenericOpFailed(cli, extraProcessingInfo.c_str());
1136baeccc455b293c2c83dbe6463f56b741177bd612JP Abgrall                return 0;
1137db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        }
1138db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall        return 0;
11394a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall
11404a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    }
1141db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall
1142db7da58e8d2aa021060098057f944ef754be06e3JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown bandwidth cmd", false);
11434a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall    return 0;
11444a5f5ca3c9e07fc3e6feca2afde07f41a8a64f11JP Abgrall}
11450031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11460031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP AbgrallCommandListener::IdletimerControlCmd::IdletimerControlCmd() :
11470031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    NetdCommand("idletimer") {
11480031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
11490031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11500031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrallint CommandListener::IdletimerControlCmd::runCommand(SocketClient *cli, int argc, char **argv) {
11510031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall  // TODO(ashish): Change the error statements
11520031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (argc < 2) {
11530031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11540031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
11550031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11560031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11570031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    ALOGV("idletimerctrlcmd: argc=%d %s %s ...", argc, argv[0], argv[1]);
11580031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11590031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "enable")) {
11600031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      if (0 != sIdletimerCtrl->enableIdletimerControl()) {
11610031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11620031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      } else {
11630031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Enable success", false);
11640031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      }
11650031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      return 0;
11660031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
11670031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11680031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "disable")) {
11690031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      if (0 != sIdletimerCtrl->disableIdletimerControl()) {
11700031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11710031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      } else {
11720031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        cli->sendMsg(ResponseCode::CommandOkay, "Disable success", false);
11730031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      }
11740031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall      return 0;
11750031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11760031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "add")) {
117798f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if (argc != 5) {
11780031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11790031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            return 0;
11800031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
118198f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if(0 != sIdletimerCtrl->addInterfaceIdletimer(
118298f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                        argv[2], atoi(argv[3]), argv[4])) {
11830031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::OperationFailed, "Failed to add interface", false);
11840031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        } else {
11850031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::CommandOkay,  "Add success", false);
11860031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
11870031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
11880031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
11890031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    if (!strcmp(argv[1], "remove")) {
119098f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if (argc != 5) {
11910031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
11920031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall            return 0;
11930031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
11940031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        // ashish: fixme timeout
119598f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai        if (0 != sIdletimerCtrl->removeInterfaceIdletimer(
119698f65d32b1530b4da6050e38d52f955710577efbHaoyu Bai                                        argv[2], atoi(argv[3]), argv[4])) {
11970031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::OperationFailed, "Failed to remove interface", false);
11980031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        } else {
11990031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall          cli->sendMsg(ResponseCode::CommandOkay, "Remove success", false);
12000031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        }
12010031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall        return 0;
12020031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    }
12030031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall
12040031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown idletimer cmd", false);
12050031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall    return 0;
12060031cead820149e2fe3ccb3cc2fe05758a3cb5c2JP Abgrall}
1207d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1208d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyCommandListener::FirewallCmd::FirewallCmd() :
1209d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    NetdCommand("firewall") {
1210d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1211d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1212d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint CommandListener::FirewallCmd::sendGenericOkFail(SocketClient *cli, int cond) {
1213d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!cond) {
1214d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::CommandOkay, "Firewall command succeeded", false);
1215d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    } else {
1216d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::OperationFailed, "Firewall command failed", false);
1217d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1218d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    return 0;
1219d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1220d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1221d8c64026aaae5a9987151b719bd840ec7d68747aJeff SharkeyFirewallRule CommandListener::FirewallCmd::parseRule(const char* arg) {
1222d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(arg, "allow")) {
1223d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return ALLOW;
1224d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    } else {
1225d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return DENY;
1226d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1227d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
1228d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1229d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkeyint CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc,
1230d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        char **argv) {
1231d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (argc < 2) {
1232d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing command", false);
1233d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return 0;
1234d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1235d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1236d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "enable")) {
1237d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->enableFirewall();
1238d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1239d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1240d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "disable")) {
1241d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->disableFirewall();
1242d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1243d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1244d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "is_enabled")) {
1245d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->isFirewallEnabled();
1246d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1247d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1248d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1249d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_interface_rule")) {
1250d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 4) {
1251d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1252d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_interface_rule <rmnet0> <allow|deny>", false);
1253d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1254d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1255d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1256d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* iface = argv[2];
1257d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[3]);
1258d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1259d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->setInterfaceRule(iface, rule);
1260d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1261d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1262d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1263d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_egress_source_rule")) {
1264d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 4) {
1265d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1266d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_egress_source_rule <192.168.0.1> <allow|deny>",
1267d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1268d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1269d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1270d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1271d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* addr = argv[2];
1272d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[3]);
1273d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1274d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->setEgressSourceRule(addr, rule);
1275d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1276d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1277d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1278d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_egress_dest_rule")) {
1279d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 5) {
1280d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1281d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_egress_dest_rule <192.168.0.1> <80> <allow|deny>",
1282d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1283d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1284d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1285d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1286d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        const char* addr = argv[2];
1287d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int port = atoi(argv[3]);
1288d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[4]);
1289d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1290d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = 0;
1291d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_TCP, port, rule);
1292d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        res |= sFirewallCtrl->setEgressDestRule(addr, PROTOCOL_UDP, port, rule);
1293d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1294d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1295d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1296d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    if (!strcmp(argv[1], "set_uid_rule")) {
1297d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        if (argc != 4) {
1298d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            cli->sendMsg(ResponseCode::CommandSyntaxError,
1299d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         "Usage: firewall set_uid_rule <1000> <allow|deny>",
1300d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey                         false);
1301d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey            return 0;
1302d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        }
1303d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1304d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int uid = atoi(argv[2]);
1305d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        FirewallRule rule = parseRule(argv[3]);
1306d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1307d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        int res = sFirewallCtrl->setUidRule(uid, rule);
1308d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey        return sendGenericOkFail(cli, res);
1309d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    }
1310d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey
1311d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown command", false);
1312d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey    return 0;
1313d8c64026aaae5a9987151b719bd840ec7d68747aJeff Sharkey}
13140da73fcecc30140439f856118056df8908609627Daniel Drown
13150da73fcecc30140439f856118056df8908609627Daniel DrownCommandListener::ClatdCmd::ClatdCmd() : NetdCommand("clatd") {
13160da73fcecc30140439f856118056df8908609627Daniel Drown}
13170da73fcecc30140439f856118056df8908609627Daniel Drown
13180da73fcecc30140439f856118056df8908609627Daniel Drownint CommandListener::ClatdCmd::runCommand(SocketClient *cli, int argc,
13190da73fcecc30140439f856118056df8908609627Daniel Drown                                                            char **argv) {
13200da73fcecc30140439f856118056df8908609627Daniel Drown    int rc = 0;
13210da73fcecc30140439f856118056df8908609627Daniel Drown    if (argc < 2) {
13220da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
13230da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
13240da73fcecc30140439f856118056df8908609627Daniel Drown    }
13250da73fcecc30140439f856118056df8908609627Daniel Drown
13260da73fcecc30140439f856118056df8908609627Daniel Drown    if(!strcmp(argv[1], "stop")) {
13270da73fcecc30140439f856118056df8908609627Daniel Drown        rc = sClatdCtrl->stopClatd();
13280da73fcecc30140439f856118056df8908609627Daniel Drown    } else if (!strcmp(argv[1], "status")) {
13290da73fcecc30140439f856118056df8908609627Daniel Drown        char *tmp = NULL;
13300da73fcecc30140439f856118056df8908609627Daniel Drown
13310da73fcecc30140439f856118056df8908609627Daniel Drown        asprintf(&tmp, "Clatd status: %s", (sClatdCtrl->isClatdStarted() ?
13320da73fcecc30140439f856118056df8908609627Daniel Drown                                                        "started" : "stopped"));
13330da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::ClatdStatusResult, tmp, false);
13340da73fcecc30140439f856118056df8908609627Daniel Drown        free(tmp);
13350da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
13360da73fcecc30140439f856118056df8908609627Daniel Drown    } else if(!strcmp(argv[1], "start")) {
13370da73fcecc30140439f856118056df8908609627Daniel Drown        if (argc < 3) {
13380da73fcecc30140439f856118056df8908609627Daniel Drown            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
13390da73fcecc30140439f856118056df8908609627Daniel Drown            return 0;
13400da73fcecc30140439f856118056df8908609627Daniel Drown        }
13410da73fcecc30140439f856118056df8908609627Daniel Drown        rc = sClatdCtrl->startClatd(argv[2]);
13420da73fcecc30140439f856118056df8908609627Daniel Drown    } else {
13430da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown clatd cmd", false);
13440da73fcecc30140439f856118056df8908609627Daniel Drown        return 0;
13450da73fcecc30140439f856118056df8908609627Daniel Drown    }
13460da73fcecc30140439f856118056df8908609627Daniel Drown
13470da73fcecc30140439f856118056df8908609627Daniel Drown    if (!rc) {
13480da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::CommandOkay, "Clatd operation succeeded", false);
13490da73fcecc30140439f856118056df8908609627Daniel Drown    } else {
13500da73fcecc30140439f856118056df8908609627Daniel Drown        cli->sendMsg(ResponseCode::OperationFailed, "Clatd operation failed", false);
13510da73fcecc30140439f856118056df8908609627Daniel Drown    }
13520da73fcecc30140439f856118056df8908609627Daniel Drown
13530da73fcecc30140439f856118056df8908609627Daniel Drown    return 0;
13540da73fcecc30140439f856118056df8908609627Daniel Drown}
1355d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
13565c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram RamachandranCommandListener::NetworkCommand::NetworkCommand() : NetdCommand("network") {
13575c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
13585c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
13595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::syntaxError(SocketClient* client, const char* message) {
13605c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::CommandSyntaxError, message, false);
13615c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return 0;
13625c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran}
13635c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1364f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandranint CommandListener::NetworkCommand::operationError(SocketClient* client, const char* message,
1365f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                                                    int ret) {
1366f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    errno = -ret;
13675c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::OperationFailed, message, true);
1368d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    return 0;
1369d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1370d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
13715c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::success(SocketClient* client) {
13725c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    client->sendMsg(ResponseCode::CommandOkay, "success", false);
1373d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    return 0;
1374d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1375d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran
13765c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandranint CommandListener::NetworkCommand::runCommand(SocketClient* client, int argc, char** argv) {
1377d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (argc < 2) {
13785c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return syntaxError(client, "Missing argument");
1379d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
13805c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
13814c95a125e0930c112555437589f7620575482095Lorenzo Colitti    //    0      1      2      3      4       5         6            7           8
13824c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // network route [legacy <uid>]  add   <netId> <interface> <destination> [nexthop]
13834c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // network route [legacy <uid>] remove <netId> <interface> <destination> [nexthop]
13844c95a125e0930c112555437589f7620575482095Lorenzo Colitti    //
13854c95a125e0930c112555437589f7620575482095Lorenzo Colitti    // nexthop may be either an IPv4/IPv6 address or one of "unreachable" or "throw".
1386f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (!strcmp(argv[1], "route")) {
1387f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (argc < 6 || argc > 9) {
1388f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
1389f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1390f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1391f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        int nextArg = 2;
1392f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        bool legacy = false;
1393f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        uid_t uid = 0;
1394f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[nextArg], "legacy")) {
1395f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ++nextArg;
1396f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            legacy = true;
1397f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            uid = strtoul(argv[nextArg++], NULL, 0);
1398f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1399f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1400f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        bool add = false;
1401f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[nextArg], "add")) {
1402f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            add = true;
1403f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else if (strcmp(argv[nextArg], "remove")) {
1404f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1405f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1406f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        ++nextArg;
1407f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1408de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran        if (argc < nextArg + 3 || argc > nextArg + 4) {
1409de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
1410de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran        }
1411de5d5df753dd35d852ac47a6174b06eacd0d5523Sreeram Ramachandran
141287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[nextArg++]);
1413f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* interface = argv[nextArg++];
1414f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* destination = argv[nextArg++];
1415f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        const char* nexthop = argc > nextArg ? argv[nextArg] : NULL;
1416f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1417f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        int ret;
1418f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (add) {
1419f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ret = sNetCtrl->addRoute(netId, interface, destination, nexthop, legacy, uid);
1420f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else {
1421f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            ret = sNetCtrl->removeRoute(netId, interface, destination, nexthop, legacy, uid);
1422f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1423f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (ret) {
1424f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, add ? "addRoute() failed" : "removeRoute() failed", ret);
1425f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1426f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1427f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return success(client);
1428f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
1429f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
143087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    //    0        1       2       3         4
143187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // network interface  add   <netId> <interface>
143287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    // network interface remove <netId> <interface>
143387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran    if (!strcmp(argv[1], "interface")) {
143487475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        if (argc != 5) {
1435f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Missing argument");
1436f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
143787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[3]);
143887475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        if (!strcmp(argv[2], "add")) {
143987475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            if (int ret = sNetCtrl->addInterfaceToNetwork(netId, argv[4])) {
1440f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "addInterfaceToNetwork() failed", ret);
1441f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            }
144287475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        } else if (!strcmp(argv[2], "remove")) {
144387475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            if (int ret = sNetCtrl->removeInterfaceFromNetwork(netId, argv[4])) {
1444f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "removeInterfaceFromNetwork() failed", ret);
1445f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            }
144687475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        } else {
144787475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1448f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1449f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        return success(client);
1450f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    }
1451f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran
1452ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    //    0      1       2         3
1453ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network create <netId> [permission]
14544043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran    //
145595684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    //    0      1       2     3     4        5
145695684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran    // network create <netId> vpn <hasDns> <secure>
1457d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (!strcmp(argv[1], "create")) {
1458ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        if (argc < 3) {
14595c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran            return syntaxError(client, "Missing argument");
14605c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
146187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[2]);
146295684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran        if (argc == 6 && !strcmp(argv[3], "vpn")) {
1463e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            bool hasDns = atoi(argv[4]);
146495684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran            bool secure = atoi(argv[5]);
146595684ba176a9fe5ea59207d7202e47fa12bbfdbeSreeram Ramachandran            if (int ret = sNetCtrl->createVirtualNetwork(netId, hasDns, secure)) {
1466e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                return operationError(client, "createVirtualNetwork() failed", ret);
14674043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
1468ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        } else if (argc > 4) {
1469ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            return syntaxError(client, "Unknown trailing argument(s)");
14704043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran        } else {
1471ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            Permission permission = PERMISSION_NONE;
1472ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            if (argc == 4) {
1473ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                permission = stringToPermission(argv[3]);
1474ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                if (permission == PERMISSION_NONE) {
1475ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                    return syntaxError(client, "Unknown permission");
1476ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                }
14774043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
1478e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran            if (int ret = sNetCtrl->createPhysicalNetwork(netId, permission)) {
1479e09b20aee85f1dfd8c18c3d8581ac875d939ba70Sreeram Ramachandran                return operationError(client, "createPhysicalNetwork() failed", ret);
14804043f01f8e25f24246efadc710ad7440aab75529Sreeram Ramachandran            }
14815c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
14825c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return success(client);
1483d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
14845c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1485d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    //    0       1       2
1486d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    // network destroy <netId>
1487d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    if (!strcmp(argv[1], "destroy")) {
1488379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (argc != 3) {
1489379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Incorrect number of arguments");
14905c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
149187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[2]);
1492f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (int ret = sNetCtrl->destroyNetwork(netId)) {
1493f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, "destroyNetwork() failed", ret);
14945c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        }
14955c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran        return success(client);
1496d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran    }
14975c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran
1498f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    //    0       1      2      3
1499f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    // network default  set  <netId>
1500f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    // network default clear
1501f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran    if (!strcmp(argv[1], "default")) {
1502f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (argc < 3) {
1503ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen            return syntaxError(client, "Missing argument");
1504ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        }
1505f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        unsigned netId = NETID_UNSET;
1506f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (!strcmp(argv[2], "set")) {
1507f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            if (argc < 4) {
1508f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return syntaxError(client, "Missing netId");
1509ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen            }
151087475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran            netId = stringToNetId(argv[3]);
1511f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        } else if (strcmp(argv[2], "clear")) {
1512f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
1513f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        }
1514f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran        if (int ret = sNetCtrl->setDefaultNetwork(netId)) {
1515f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            return operationError(client, "setDefaultNetwork() failed", ret);
1516ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        }
1517ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen        return success(client);
1518ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen    }
1519ae37e8a4f42b658d5aaf43f312f063944b4aeecbPaul Jensen
1520ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    //    0        1         2      3        4          5
1521ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission   user   set  <permission>  <uid> ...
1522ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission   user  clear    <uid> ...
1523ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission network  set  <permission> <netId> ...
1524ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran    // network permission network clear   <netId> ...
1525379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    if (!strcmp(argv[1], "permission")) {
1526379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (argc < 5) {
1527379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Missing argument");
1528379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1529379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        int nextArg = 4;
1530379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        Permission permission = PERMISSION_NONE;
1531379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (!strcmp(argv[3], "set")) {
1532ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            permission = stringToPermission(argv[4]);
1533ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            if (permission == PERMISSION_NONE) {
1534ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran                return syntaxError(client, "Unknown permission");
1535ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            }
1536ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            nextArg = 5;
1537379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        } else if (strcmp(argv[3], "clear")) {
1538379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Unknown argument");
1539379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1540ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        if (nextArg == argc) {
1541ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran            return syntaxError(client, "Missing id");
1542ed4bd1f7d219f9f5f56763ea02cf4947e78397f6Sreeram Ramachandran        }
1543379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        std::vector<unsigned> ids;
1544379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        for (; nextArg < argc; ++nextArg) {
1545379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            char* endPtr;
1546379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            unsigned id = strtoul(argv[nextArg], &endPtr, 0);
1547379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            if (!*argv[nextArg] || *endPtr) {
1548379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran                return syntaxError(client, "Invalid id");
1549379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            }
1550379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            ids.push_back(id);
1551379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1552379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        if (!strcmp(argv[2], "user")) {
1553f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            sNetCtrl->setPermissionForUsers(permission, ids);
1554379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        } else if (!strcmp(argv[2], "network")) {
1555f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran            if (int ret = sNetCtrl->setPermissionForNetworks(permission, ids)) {
1556f4f6c8de3f091be4b91a5a9d7f14e8882ec6d502Sreeram Ramachandran                return operationError(client, "setPermissionForNetworks() failed", ret);
1557379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            }
1558379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        } else {
1559379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran            return syntaxError(client, "Unknown argument");
1560379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        }
1561379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran        return success(client);
1562379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran    }
1563379bd33f7640e2c4bef902be0ed6cb96378c8c2eSreeram Ramachandran
1564b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    //    0      1     2       3           4
1565b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    // network users  add   <netId> [<uid>[-<uid>]] ...
1566b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    // network users remove <netId> [<uid>[-<uid>]] ...
1567b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    if (!strcmp(argv[1], "users")) {
1568b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (argc < 4) {
1569b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Missing argument");
1570b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
157187475a1471373b72ffc9f81f17dfd7884723fa86Sreeram Ramachandran        unsigned netId = stringToNetId(argv[3]);
1572b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        UidRanges uidRanges;
1573b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!uidRanges.parseFrom(argc - 4, argv + 4)) {
1574b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Invalid UIDs");
1575b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
1576b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        if (!strcmp(argv[2], "add")) {
1577b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            if (int ret = sNetCtrl->addUsersToNetwork(netId, uidRanges)) {
1578b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return operationError(client, "addUsersToNetwork() failed", ret);
1579b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
1580b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else if (!strcmp(argv[2], "remove")) {
1581b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            if (int ret = sNetCtrl->removeUsersFromNetwork(netId, uidRanges)) {
1582b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran                return operationError(client, "removeUsersFromNetwork() failed", ret);
1583b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            }
1584b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        } else {
1585b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran            return syntaxError(client, "Unknown argument");
1586b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        }
1587b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran        return success(client);
1588b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran    }
1589b1425cc09f8a29350520db0d4f489331df5a689bSreeram Ramachandran
159089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    //    0       1      2     3
159189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    // network protect allow <uid> ...
159289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    // network protect  deny <uid> ...
159389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    if (!strcmp(argv[1], "protect")) {
159489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        if (argc < 4) {
159589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            return syntaxError(client, "Missing argument");
159689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
159789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        std::vector<uid_t> uids;
159889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        for (int i = 3; i < argc; ++i) {
159989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            uids.push_back(strtoul(argv[i], NULL, 0));
160089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
160189dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        if (!strcmp(argv[2], "allow")) {
160289dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            sNetCtrl->allowProtect(uids);
160389dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        } else if (!strcmp(argv[2], "deny")) {
160489dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            sNetCtrl->denyProtect(uids);
160589dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        } else {
160689dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran            return syntaxError(client, "Unknown argument");
160789dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        }
160889dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran        return success(client);
160989dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran    }
161089dad013e4dd98434b0409a84567f38782894029Sreeram Ramachandran
16115c181bf8ca0c89bd9e3e6d8e40bac53d0ee7082fSreeram Ramachandran    return syntaxError(client, "Unknown argument");
1612d736d4b327bf35afc59b5cec110491fcdb9e2cbbSreeram Ramachandran}
1613