CommandListener.cpp revision d5573d34c8fac49e16b20cf144486125bf940086
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;
35PppController *CommandListener::sPppCtrl = NULL;
36
37CommandListener::CommandListener() :
38                 FrameworkListener("netd") {
39    registerCmd(new ListInterfacesCmd());
40    registerCmd(new IpFwdCmd());
41    registerCmd(new TetherCmd());
42    registerCmd(new NatCmd());
43    registerCmd(new ListTtysCmd());
44    registerCmd(new PppdCmd());
45
46    if (!sTetherCtrl)
47        sTetherCtrl = new TetherController();
48    if (!sNatCtrl)
49        sNatCtrl = new NatController();
50    if (!sPppCtrl)
51        sPppCtrl = new PppController();
52}
53
54CommandListener::ListInterfacesCmd::ListInterfacesCmd() :
55                 NetdCommand("list_interfaces") {
56}
57
58int CommandListener::ListInterfacesCmd::runCommand(SocketClient *cli,
59                                                      int argc, char **argv) {
60    // XXX: Send a series of InterfaceListResults
61    cli->sendMsg(ResponseCode::CommandOkay, "Interfaces listed.", false);
62    return 0;
63}
64
65CommandListener::ListTtysCmd::ListTtysCmd() :
66                 NetdCommand("list_ttys") {
67}
68
69int CommandListener::ListTtysCmd::runCommand(SocketClient *cli,
70                                             int argc, char **argv) {
71    TtyCollection *tlist = sPppCtrl->getTtyList();
72    TtyCollection::iterator it;
73
74    for (it = tlist->begin(); it != tlist->end(); ++it) {
75        cli->sendMsg(ResponseCode::TtyListResult, *it, false);
76    }
77
78    cli->sendMsg(ResponseCode::CommandOkay, "Ttys listed.", false);
79    return 0;
80}
81
82CommandListener::IpFwdCmd::IpFwdCmd() :
83                 NetdCommand("ipfwd") {
84}
85
86int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
87                                                      int argc, char **argv) {
88    int rc = 0;
89
90    if (argc < 2) {
91        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
92        return 0;
93    }
94
95    if (!strcmp(argv[1], "status")) {
96        char *tmp = NULL;
97
98        asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
99        cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
100        free(tmp);
101        return 0;
102    } else if (!strcmp(argv[1], "enable")) {
103        rc = sTetherCtrl->setIpFwdEnabled(true);
104    } else if (!strcmp(argv[1], "disable")) {
105        rc = sTetherCtrl->setIpFwdEnabled(false);
106    } else {
107        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
108        return 0;
109    }
110
111    if (!rc) {
112        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
113    } else {
114        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
115    }
116
117    return 0;
118}
119
120CommandListener::TetherCmd::TetherCmd() :
121                 NetdCommand("tether") {
122}
123
124int CommandListener::TetherCmd::runCommand(SocketClient *cli,
125                                                      int argc, char **argv) {
126    int rc = 0;
127
128    if (argc < 2) {
129        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
130        return 0;
131    }
132
133    if (!strcmp(argv[1], "stop")) {
134        rc = sTetherCtrl->stopTethering();
135    } else if (!strcmp(argv[1], "status")) {
136        char *tmp = NULL;
137
138        asprintf(&tmp, "Tethering services %s",
139                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
140        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
141        free(tmp);
142        return 0;
143    } else {
144        /*
145         * These commands take a minimum of 4 arguments
146         */
147        if (argc < 4) {
148            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
149            return 0;
150        }
151
152        if (!strcmp(argv[1], "start")) {
153            struct in_addr s, e;
154
155            if (!inet_aton(argv[2], &s)) {
156                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid start address", false);
157                return 0;
158            }
159            if (!inet_aton(argv[3], &e)) {
160                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid end address", false);
161                return 0;
162            }
163            rc = sTetherCtrl->startTethering(s, e);
164        } else if (!strcmp(argv[1], "interface")) {
165            if (!strcmp(argv[2], "add")) {
166                rc = sTetherCtrl->tetherInterface(argv[3]);
167            } else if (!strcmp(argv[2], "remove")) {
168                rc = sTetherCtrl->untetherInterface(argv[3]);
169            } else if (!strcmp(argv[2], "list")) {
170                InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
171                InterfaceCollection::iterator it;
172
173                for (it = ilist->begin(); it != ilist->end(); ++it) {
174                    cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
175                }
176            } else {
177                cli->sendMsg(ResponseCode::CommandParameterError,
178                             "Unknown tether interface operation", false);
179                return 0;
180            }
181        } else if (!strcmp(argv[1], "dns")) {
182            if (!strcmp(argv[2], "set")) {
183                rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
184            } else if (!strcmp(argv[2], "list")) {
185                NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
186                NetAddressCollection::iterator it;
187
188                for (it = dlist->begin(); it != dlist->end(); ++it) {
189                    cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
190                }
191            } else {
192                cli->sendMsg(ResponseCode::CommandParameterError,
193                             "Unknown tether interface operation", false);
194                return 0;
195            }
196        } else {
197            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
198            return 0;
199        }
200    }
201
202    if (!rc) {
203        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
204    } else {
205        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
206    }
207
208    return 0;
209}
210
211CommandListener::NatCmd::NatCmd() :
212                 NetdCommand("nat") {
213}
214
215int CommandListener::NatCmd::runCommand(SocketClient *cli,
216                                                      int argc, char **argv) {
217    int rc = 0;
218
219    if (argc < 3) {
220        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
221        return 0;
222    }
223
224    if (!strcmp(argv[1], "enable")) {
225        rc = sNatCtrl->enableNat(argv[2], argv[3]);
226    } else if (!strcmp(argv[1], "disable")) {
227        rc = sNatCtrl->disableNat(argv[2], argv[3]);
228    } else {
229        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
230        return 0;
231    }
232
233    if (!rc) {
234        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
235    } else {
236        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
237    }
238
239    return 0;
240}
241
242CommandListener::PppdCmd::PppdCmd() :
243                 NetdCommand("pppd") {
244}
245
246int CommandListener::PppdCmd::runCommand(SocketClient *cli,
247                                                      int argc, char **argv) {
248    int rc = 0;
249
250    if (argc < 3) {
251        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
252        return 0;
253    }
254
255    if (!strcmp(argv[1], "attach")) {
256        struct in_addr l, r;
257
258        if (!inet_aton(argv[3], &l)) {
259            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid local address", false);
260            return 0;
261        }
262        if (!inet_aton(argv[4], &r)) {
263            cli->sendMsg(ResponseCode::CommandParameterError, "Invalid remote address", false);
264            return 0;
265        }
266        rc = sPppCtrl->attachPppd(argv[2], l, r);
267    } else if (!strcmp(argv[1], "detach")) {
268        rc = sPppCtrl->detachPppd(argv[2]);
269    } else {
270        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown pppd cmd", false);
271        return 0;
272    }
273
274    if (!rc) {
275        cli->sendMsg(ResponseCode::CommandOkay, "Pppd operation succeeded", false);
276    } else {
277        cli->sendMsg(ResponseCode::OperationFailed, "Pppd operation failed", true);
278    }
279
280    return 0;
281}
282