CommandListener.cpp revision 9d10b341a0ba46f108cb96e46691197d778cbc06
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;
34
35CommandListener::CommandListener() :
36                 FrameworkListener("netd") {
37    registerCmd(new ListInterfacesCmd());
38    registerCmd(new IpFwdCmd());
39    registerCmd(new TetherCmd());
40    registerCmd(new NatCmd());
41
42    if (!sTetherCtrl)
43        sTetherCtrl = new TetherController();
44}
45
46CommandListener::ListInterfacesCmd::ListInterfacesCmd() :
47                 NetdCommand("list_interfaces") {
48}
49
50int CommandListener::ListInterfacesCmd::runCommand(SocketClient *cli,
51                                                      int argc, char **argv) {
52    // XXX: Send a series of InterfaceListResults
53    cli->sendMsg(ResponseCode::CommandOkay, "Interfaces listed.", false);
54    return 0;
55}
56
57CommandListener::IpFwdCmd::IpFwdCmd() :
58                 NetdCommand("ipfwd") {
59}
60
61int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
62                                                      int argc, char **argv) {
63    int rc = 0;
64
65    if (argc < 2) {
66        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
67        return 0;
68    }
69
70    if (!strcmp(argv[1], "status")) {
71        char *tmp = NULL;
72
73        asprintf(&tmp, "Forwarding %s", (sTetherCtrl->getIpFwdEnabled() ? "enabled" : "disabled"));
74        cli->sendMsg(ResponseCode::IpFwdStatusResult, tmp, false);
75        free(tmp);
76        return 0;
77    } else if (!strcmp(argv[1], "enable")) {
78        rc = sTetherCtrl->setIpFwdEnabled(true);
79    } else if (!strcmp(argv[1], "disable")) {
80        rc = sTetherCtrl->setIpFwdEnabled(false);
81    } else {
82        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown ipfwd cmd", false);
83        return 0;
84    }
85
86    if (!rc) {
87        cli->sendMsg(ResponseCode::CommandOkay, "ipfwd operation succeeded", false);
88    } else {
89        cli->sendMsg(ResponseCode::OperationFailed, "ipfwd operation failed", true);
90    }
91
92    return 0;
93}
94
95CommandListener::TetherCmd::TetherCmd() :
96                 NetdCommand("tether") {
97}
98
99int CommandListener::TetherCmd::runCommand(SocketClient *cli,
100                                                      int argc, char **argv) {
101    int rc = 0;
102
103    if (argc < 2) {
104        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
105        return 0;
106    }
107
108    if (!strcmp(argv[1], "stop")) {
109        rc = sTetherCtrl->stopTethering();
110    } else if (!strcmp(argv[1], "status")) {
111        char *tmp = NULL;
112
113        asprintf(&tmp, "Tethering services %s",
114                 (sTetherCtrl->isTetheringStarted() ? "started" : "stopped"));
115        cli->sendMsg(ResponseCode::TetherStatusResult, tmp, false);
116        free(tmp);
117        return 0;
118    } else {
119        /*
120         * These commands take a minimum of 4 arguments
121         */
122        if (argc < 4) {
123            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
124            return 0;
125        }
126
127        if (!strcmp(argv[1], "start")) {
128            struct in_addr s, e;
129
130            if (!inet_aton(argv[2], &s)) {
131                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid start address", false);
132                return 0;
133            }
134            if (!inet_aton(argv[3], &e)) {
135                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid end address", false);
136                return 0;
137            }
138            rc = sTetherCtrl->startTethering(s, e);
139        } else if (!strcmp(argv[1], "interface")) {
140            if (!strcmp(argv[2], "add")) {
141                rc = sTetherCtrl->tetherInterface(argv[3]);
142            } else if (!strcmp(argv[2], "remove")) {
143                rc = sTetherCtrl->untetherInterface(argv[3]);
144            } else if (!strcmp(argv[2], "list")) {
145                InterfaceCollection *ilist = sTetherCtrl->getTetheredInterfaceList();
146                InterfaceCollection::iterator it;
147
148                for (it = ilist->begin(); it != ilist->end(); ++it) {
149                    cli->sendMsg(ResponseCode::TetherInterfaceListResult, *it, false);
150                }
151            } else {
152                cli->sendMsg(ResponseCode::CommandParameterError,
153                             "Unknown tether interface operation", false);
154                return 0;
155            }
156        } else if (!strcmp(argv[1], "dns")) {
157            if (!strcmp(argv[2], "set")) {
158                rc = sTetherCtrl->setDnsForwarders(&argv[3], argc - 3);
159            } else if (!strcmp(argv[2], "list")) {
160                NetAddressCollection *dlist = sTetherCtrl->getDnsForwarders();
161                NetAddressCollection::iterator it;
162
163                for (it = dlist->begin(); it != dlist->end(); ++it) {
164                    cli->sendMsg(ResponseCode::TetherDnsFwdTgtListResult, inet_ntoa(*it), false);
165                }
166            } else {
167                cli->sendMsg(ResponseCode::CommandParameterError,
168                             "Unknown tether interface operation", false);
169                return 0;
170            }
171        } else {
172            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
173            return 0;
174        }
175    }
176
177    if (!rc) {
178        cli->sendMsg(ResponseCode::CommandOkay, "Tether operation succeeded", false);
179    } else {
180        cli->sendMsg(ResponseCode::OperationFailed, "Tether operation failed", true);
181    }
182
183    return 0;
184}
185
186CommandListener::NatCmd::NatCmd() :
187                 NetdCommand("nat") {
188}
189
190int CommandListener::NatCmd::runCommand(SocketClient *cli,
191                                                      int argc, char **argv) {
192    int rc = 0;
193
194    if (argc < 3) {
195        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
196        return 0;
197    }
198
199    if (!strcmp(argv[1], "binding")) {
200        if (!strcmp(argv[2], "add")) {
201            rc = 0;
202        } else if (!strcmp(argv[2], "remove")) {
203            rc = 0;
204        } else {
205            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat binding cmd", false);
206            return 0;
207        }
208    } else {
209        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown nat cmd", false);
210        return 0;
211    }
212
213    if (!rc) {
214        cli->sendMsg(ResponseCode::CommandOkay, "Nat operation succeeded", false);
215    } else {
216        cli->sendMsg(ResponseCode::OperationFailed, "Nat operation failed", true);
217    }
218
219    return 0;
220}
221
222