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