OSDN Git Service

am 41efab55: Merge "Fix DNS proxy."
[android-x86/system-netd.git] / TetherController.cpp
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 <errno.h>
19 #include <fcntl.h>
20 #include <string.h>
21
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29
30 #define LOG_TAG "TetherController"
31 #include <cutils/log.h>
32
33
34 #include "TetherController.h"
35
36 TetherController::TetherController() {
37     mInterfaces = new InterfaceCollection();
38     mDnsForwarders = new NetAddressCollection();
39     mDaemonFd = -1;
40     mDaemonPid = 0;
41 }
42
43 TetherController::~TetherController() {
44     InterfaceCollection::iterator it;
45
46     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
47         free(*it);
48     }
49     mInterfaces->clear();
50
51     mDnsForwarders->clear();
52 }
53
54 int TetherController::setIpFwdEnabled(bool enable) {
55
56     LOGD("Setting IP forward enable = %d", enable);
57     int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY);
58     if (fd < 0) {
59         LOGE("Failed to open ip_forward (%s)", strerror(errno));
60         return -1;
61     }
62
63     if (write(fd, (enable ? "1" : "0"), 1) != 1) {
64         LOGE("Failed to write ip_forward (%s)", strerror(errno));
65         close(fd);
66         return -1;
67     }
68     close(fd);
69     return 0;
70 }
71
72 bool TetherController::getIpFwdEnabled() {
73     int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY);
74
75     if (fd < 0) {
76         LOGE("Failed to open ip_forward (%s)", strerror(errno));
77         return false;
78     }
79
80     char enabled;
81     if (read(fd, &enabled, 1) != 1) {
82         LOGE("Failed to read ip_forward (%s)", strerror(errno));
83         close(fd);
84         return -1;
85     }
86
87     close(fd);
88     return (enabled  == '1' ? true : false);
89 }
90
91 int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
92     if (mDaemonPid != 0) {
93         LOGE("Tethering already started");
94         errno = EBUSY;
95         return -1;
96     }
97
98     LOGD("Starting tethering services");
99
100     pid_t pid;
101     int pipefd[2];
102
103     if (pipe(pipefd) < 0) {
104         LOGE("pipe failed (%s)", strerror(errno));
105         return -1;
106     }
107
108     /*
109      * TODO: Create a monitoring thread to handle and restart
110      * the daemon if it exits prematurely
111      */
112     if ((pid = fork()) < 0) {
113         LOGE("fork failed (%s)", strerror(errno));
114         close(pipefd[0]);
115         close(pipefd[1]);
116         return -1;
117     }
118
119     if (!pid) {
120         close(pipefd[1]);
121         if (pipefd[0] != STDIN_FILENO) {
122             if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
123                 LOGE("dup2 failed (%s)", strerror(errno));
124                 return -1;
125             }
126             close(pipefd[0]);
127         }
128
129         int num_processed_args = 4 + (num_addrs/2) + 1; // 1 null for termination
130         char **args = (char **)malloc(sizeof(char *) * num_processed_args);
131         args[num_processed_args - 1] = NULL;
132         args[0] = (char *)"/system/bin/dnsmasq";
133         args[1] = (char *)"--no-daemon";
134         args[2] = (char *)"--no-resolv";
135         args[3] = (char *)"--no-poll";
136
137         int nextArg = 4;
138         for (int addrIndex=0; addrIndex < num_addrs;) {
139             char *start = strdup(inet_ntoa(addrs[addrIndex++]));
140             char *end = strdup(inet_ntoa(addrs[addrIndex++]));
141             asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
142         }
143
144         if (execv(args[0], args)) {
145             LOGE("execl failed (%s)", strerror(errno));
146         }
147         LOGE("Should never get here!");
148         free(args);
149         return 0;
150     } else {
151         close(pipefd[0]);
152         mDaemonPid = pid;
153         mDaemonFd = pipefd[1];
154         LOGD("Tethering services running");
155     }
156
157     return 0;
158 }
159
160 int TetherController::stopTethering() {
161
162     if (mDaemonPid == 0) {
163         LOGE("Tethering already stopped");
164         return 0;
165     }
166
167     LOGD("Stopping tethering services");
168
169     kill(mDaemonPid, SIGTERM);
170     waitpid(mDaemonPid, NULL, 0);
171     mDaemonPid = 0;
172     close(mDaemonFd);
173     mDaemonFd = -1;
174     LOGD("Tethering services stopped");
175     return 0;
176 }
177
178 bool TetherController::isTetheringStarted() {
179     return (mDaemonPid == 0 ? false : true);
180 }
181
182 #define MAX_CMD_SIZE 1024
183
184 int TetherController::setDnsForwarders(char **servers, int numServers) {
185     int i;
186     char daemonCmd[MAX_CMD_SIZE];
187
188     strcpy(daemonCmd, "update_dns");
189     int cmdLen = strlen(daemonCmd);
190
191     mDnsForwarders->clear();
192     for (i = 0; i < numServers; i++) {
193         LOGD("setDnsForwarders(%d = '%s')", i, servers[i]);
194
195         struct in_addr a;
196
197         if (!inet_aton(servers[i], &a)) {
198             LOGE("Failed to parse DNS server '%s'", servers[i]);
199             mDnsForwarders->clear();
200             return -1;
201         }
202
203         cmdLen += strlen(servers[i]);
204         if (cmdLen + 2 >= MAX_CMD_SIZE) {
205             LOGD("Too many DNS servers listed");
206             break;
207         }
208
209         strcat(daemonCmd, ":");
210         strcat(daemonCmd, servers[i]);
211         mDnsForwarders->push_back(a);
212     }
213
214     if (mDaemonFd != -1) {
215         LOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
216         if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
217             LOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
218             mDnsForwarders->clear();
219             return -1;
220         }
221     }
222     return 0;
223 }
224
225 NetAddressCollection *TetherController::getDnsForwarders() {
226     return mDnsForwarders;
227 }
228
229 int TetherController::tetherInterface(const char *interface) {
230     mInterfaces->push_back(strdup(interface));
231     return 0;
232 }
233
234 int TetherController::untetherInterface(const char *interface) {
235     InterfaceCollection::iterator it;
236
237     for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
238         if (!strcmp(interface, *it)) {
239             free(*it);
240             mInterfaces->erase(it);
241             return 0;
242         }
243     }
244     errno = ENOENT;
245     return -1;
246 }
247
248 InterfaceCollection *TetherController::getTetheredInterfaceList() {
249     return mInterfaces;
250 }