CommandListener.cpp revision 9ff78fb7da7158f5bd7c86d89a842691820259cf
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <sys/socket.h>
19#include <sys/types.h>
20#include <netinet/in.h>
21#include <arpa/inet.h>
22#include <dirent.h>
23#include <errno.h>
24
25#define LOG_TAG "CommandListener"
26#include <cutils/log.h>
27
28#include <sysutils/SocketClient.h>
29
30#include "CommandListener.h"
31#include "ResponseCode.h"
32
33TetherController *CommandListener::sTetherCtrl = NULL;
34NatController *CommandListener::sNatCtrl = NULL;
35
36CommandListener::CommandListener() :
37                 FrameworkListener("netd") {
38    registerCmd(new ListInterfacesCmd());
39    registerCmd(new IpFwdCmd());
40    registerCmd(new TetherCmd());
41    registerCmd(new NatCmd());
42
43    if (!sTetherCtrl)
44        sTetherCtrl = new TetherController();
45    if (!sNatCtrl)
46        sNatCtrl = new NatController();
47}
48
49CommandListener::ListInterfacesCmd::ListInterfacesCmd() :
50                 NetdCommand("list_interfaces") {
51}
52
53int CommandListener::ListInterfacesCmd::runCommand(SocketClient *cli,
54                                                      int argc, char **argv) {
55    // XXX: Send a series of InterfaceListResults
56    cli->sendMsg(ResponseCode::CommandOkay, "Interfaces listed.", false);
57    return 0;
58}
59
60CommandListener::IpFwdCmd::IpFwdCmd() :
61                 NetdCommand("ipfwd") {
62}
63
64int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
65                                                      int argc, char **argv) {
66    int rc = 0;
67
68    if (argc < 2) {
69        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
70        return 0;
71    }
72
73    if (!strcmp(argv[1], "status")) {
74        char *tmp = NULL;
75
76        asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
77        cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
78        free(tmp);
79        return 0;
80    } else if (!strcmp(argv[1], "enable")) {
81        rc = sTetherCtrl->setIpFwdEnabled(true);
82    } else if (!strcmp(argv[1], "disable")) {
83        rc = sTetherCtrl->setIpFwdEnabled(false);
84    } else {
85        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
86        return 0;
87    }
88
89    if (!rc) {
90        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
91    } else {
92        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
93    }
94
95    return 0;
96}
97
98CommandListener::TetherCmd::TetherCmd() :
99                 NetdCommand("tether") {
100}
101
102int CommandListener::TetherCmd::runCommand(SocketClient *cli,
103                                                      int argc, char **argv) {
104    int rc = 0;
105
106    if (argc < 2) {
107        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
108        return 0;
109    }
110
111    if (!strcmp(argv[1], "stop")) {
112        rc = sTetherCtrl->stopTethering();
113    } else if (!strcmp(argv[1], "status")) {
114        char *tmp = NULL;
115
116        asprintf(&tmp, "Tethering services %s",
117                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
118        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
119        free(tmp);
120        return 0;
121    } else {
122        /*
123         * These commands take a minimum of 4 arguments
124         */
125        if (argc < 4) {
126            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
127            return 0;
128        }
129
130        if (!strcmp(argv[1], "start")) {
131            struct in_addr s, e;
132
133            if (!inet_aton(argv[2], &s)) {
134                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid start address", false);
135                return 0;
136            }
137            if (!inet_aton(argv[3], &e)) {
138                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid end address", false);
139                return 0;
140            }
141            rc = sTetherCtrl->startTethering(s, e);
142        } else if (!strcmp(argv[1], "interface")) {
143            if (!strcmp(argv[2], "add")) {
144                rc = sTetherCtrl->tetherInterface(argv[3]);
145            } else if (!strcmp(argv[2], "remove")) {
146                rc = sTetherCtrl->untetherInterface(argv[3]);
147            } else if (!strcmp(argv[2], "list")) {
148                InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
149                InterfaceCollection::iterator it;
150
151                for (it = ilist->begin(); it != ilist->end(); ++it) {
152                    cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
153                }
154            } else {
155                cli->sendMsg(ResponseCode::CommandParameterError,
156                             "Unknown tether interface operation", false);
157                return 0;
158            }
159        } else if (!strcmp(argv[1], "dns")) {
160            if (!strcmp(argv[2], "set")) {
161                rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
162            } else if (!strcmp(argv[2], "list")) {
163                NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
164                NetAddressCollection::iterator it;
165
166                for (it = dlist->begin(); it != dlist->end(); ++it) {
167                    cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
168                }
169            } else {
170                cli->sendMsg(ResponseCode::CommandParameterError,
171                             "Unknown tether interface operation", false);
172                return 0;
173            }
174        } else {
175            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
176            return 0;
177        }
178    }
179
180    if (!rc) {
181        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
182    } else {
183        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
184    }
185
186    return 0;
187}
188
189CommandListener::NatCmd::NatCmd() :
190                 NetdCommand("nat") {
191}
192
193int CommandListener::NatCmd::runCommand(SocketClient *cli,
194                                                      int argc, char **argv) {
195    int rc = 0;
196
197    if (argc < 3) {
198        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
199        return 0;
200    }
201
202    if (!strcmp(argv[1], "enable")) {
203        rc = sNatCtrl->enableNat(argv[2], argv[3]);
204    } else if (!strcmp(argv[1], "disable")) {
205        rc = sNatCtrl->disableNat(argv[2], argv[3]);
206    } else {
207        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
208        return 0;
209    }
210
211    if (!rc) {
212        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
213    } else {
214        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
215    }
216
217    return 0;
218}
219
220