blob: a5a91b4c1a15b0ef4cfd8adb9ea720e8ec400469 [file] [log] [blame]
San Mehat9d10b342010-01-18 09:51:02 -08001/*
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>
San Mehat18737842010-01-21 09:22:43 -080019#include <fcntl.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080020#include <string.h>
San Mehat18737842010-01-21 09:22:43 -080021
San Mehat9d10b342010-01-18 09:51:02 -080022#include <sys/socket.h>
23#include <sys/stat.h>
San Mehat18737842010-01-21 09:22:43 -080024#include <sys/types.h>
25#include <sys/wait.h>
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060026#include <linux/capability.h>
San Mehat18737842010-01-21 09:22:43 -080027
San Mehat9d10b342010-01-18 09:51:02 -080028#include <netinet/in.h>
29#include <arpa/inet.h>
30
31#define LOG_TAG "TetherController"
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060032#define LOG_NDEBUG 0
33#define LOG_NDDEBUG 0
34#define LOG_NIDEBUG 0
San Mehat9d10b342010-01-18 09:51:02 -080035#include <cutils/log.h>
Kazuhiro Ondo6b858eb2011-06-24 20:31:03 -050036#include <cutils/properties.h>
San Mehat9d10b342010-01-18 09:51:02 -080037
Lorenzo Colitti667c4772014-08-26 14:13:07 -070038#include "Fwmark.h"
JP Abgrall69261cb2014-06-19 18:35:24 -070039#include "NetdConstants.h"
Lorenzo Colitti667c4772014-08-26 14:13:07 -070040#include "Permission.h"
San Mehat9d10b342010-01-18 09:51:02 -080041#include "TetherController.h"
42
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060043#include <private/android_filesystem_config.h>
44#include <unistd.h>
45
46#define RTRADVDAEMON "/system/bin/radish"
47#define IP4_CFG_IP_FORWARD "/proc/sys/net/ipv4/ip_forward"
48#define IP6_CFG_ALL_PROXY_NDP "/proc/sys/net/ipv6/conf/all/proxy_ndp"
49#define IP6_CFG_ALL_FORWARDING "/proc/sys/net/ipv6/conf/all/forwarding"
50#define IP6_IFACE_CFG_ACCEPT_RA "/proc/sys/net/ipv6/conf/%s/accept_ra"
51#define PROC_PATH_SIZE 255
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -060052#define RTRADVDAEMON_MIN_IFACES 2
53#define MAX_TABLE_LEN 11
54#define MIN_TABLE_NUMBER 0
55#define IP_ADDR "ip addr"
56#define BASE_TABLE_NUMBER 1000
57#define IF_INDEX_PATH "/sys/class/net/%s/ifindex"
58#define SYS_PATH_SIZE PROC_PATH_SIZE
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060059
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -060060/* This is the number of arguments for RTRADVDAEMON which accounts for the
61 * location of the daemon, the table name option, the name of the table
62 * and a final empty string
63 */
64#define RTRADVDAEMON_ARGS_COUNT 4
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060065
Sreeram Ramachandran87475a12014-07-15 16:20:28 -070066TetherController::TetherController() {
San Mehat9d10b342010-01-18 09:51:02 -080067 mInterfaces = new InterfaceCollection();
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060068 mUpstreamInterfaces = new InterfaceCollection();
San Mehat9d10b342010-01-18 09:51:02 -080069 mDnsForwarders = new NetAddressCollection();
70 mDaemonFd = -1;
71 mDaemonPid = 0;
72}
73
74TetherController::~TetherController() {
75 InterfaceCollection::iterator it;
76
77 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
78 free(*it);
79 }
80 mInterfaces->clear();
81
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060082 for (it = mUpstreamInterfaces->begin(); it != mUpstreamInterfaces->end(); ++it) {
83 free(*it);
84 }
85 mUpstreamInterfaces->clear();
86
San Mehat9d10b342010-01-18 09:51:02 -080087 mDnsForwarders->clear();
88}
89
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -060090static int config_write_setting(const char *path, const char *value)
91{
92 int fd = open(path, O_WRONLY);
93
94 ALOGD("config_write_setting(%s, %s)", path, value);
95 if (fd < 0) {
96 ALOGE("Failed to open %s (%s)", path, strerror(errno));
97 return -1;
98 }
99 if (write(fd, value, strlen(value)) != (int)strlen(value)) {
100 ALOGE("Failed to write to %s (%s)", path, strerror(errno));
101 close(fd);
102 return -1;
103 }
104 close(fd);
105 return 0;
106}
107
San Mehat9d10b342010-01-18 09:51:02 -0800108int TetherController::setIpFwdEnabled(bool enable) {
109
Steve Block7b984e32011-12-20 16:22:42 +0000110 ALOGD("Setting IP forward enable = %d", enable);
Kazuhiro Ondo6b858eb2011-06-24 20:31:03 -0500111
112 // In BP tools mode, do not disable IP forwarding
113 char bootmode[PROPERTY_VALUE_MAX] = {0};
114 property_get("ro.bootmode", bootmode, "unknown");
115 if ((enable == false) && (0 == strcmp("bp-tools", bootmode))) {
116 return 0;
117 }
118
San Mehat9d10b342010-01-18 09:51:02 -0800119 int fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY);
120 if (fd < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000121 ALOGE("Failed to open ip_forward (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800122 return -1;
123 }
124
125 if (write(fd, (enable ? "1" : "0"), 1) != 1) {
Steve Block5ea0c052012-01-06 19:18:11 +0000126 ALOGE("Failed to write ip_forward (%s)", strerror(errno));
Robert Greenwalt37dc4a52010-04-28 16:05:04 -0700127 close(fd);
San Mehat9d10b342010-01-18 09:51:02 -0800128 return -1;
129 }
130 close(fd);
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600131 if (config_write_setting(
132 IP6_CFG_ALL_PROXY_NDP, enable ? "2" : "0")) {
133 ALOGE("Failed to write proxy_ndp (%s)", strerror(errno));
134 return -1;
135 }
136 if (config_write_setting(
137 IP6_CFG_ALL_FORWARDING, enable ? "2" : "0")) {
138 ALOGE("Failed to write ip6 forwarding (%s)", strerror(errno));
139 return -1;
140 }
141
San Mehat9d10b342010-01-18 09:51:02 -0800142 return 0;
143}
144
145bool TetherController::getIpFwdEnabled() {
146 int fd = open("/proc/sys/net/ipv4/ip_forward", O_RDONLY);
147
148 if (fd < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000149 ALOGE("Failed to open ip_forward (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800150 return false;
151 }
152
153 char enabled;
154 if (read(fd, &enabled, 1) != 1) {
Steve Block5ea0c052012-01-06 19:18:11 +0000155 ALOGE("Failed to read ip_forward (%s)", strerror(errno));
Robert Greenwalt37dc4a52010-04-28 16:05:04 -0700156 close(fd);
San Mehat9d10b342010-01-18 09:51:02 -0800157 return -1;
158 }
159
160 close(fd);
San Mehat9d10b342010-01-18 09:51:02 -0800161 return (enabled == '1' ? true : false);
162}
163
Dmitry Shmidtbc775ed2013-12-12 16:41:16 -0800164#define TETHER_START_CONST_ARG 8
165
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700166int TetherController::startTethering(int num_addrs, struct in_addr* addrs) {
San Mehat9d10b342010-01-18 09:51:02 -0800167 if (mDaemonPid != 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000168 ALOGE("Tethering already started");
San Mehat9d10b342010-01-18 09:51:02 -0800169 errno = EBUSY;
170 return -1;
171 }
172
Steve Block7b984e32011-12-20 16:22:42 +0000173 ALOGD("Starting tethering services");
San Mehat9d10b342010-01-18 09:51:02 -0800174
175 pid_t pid;
176 int pipefd[2];
177
178 if (pipe(pipefd) < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000179 ALOGE("pipe failed (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800180 return -1;
181 }
182
183 /*
184 * TODO: Create a monitoring thread to handle and restart
185 * the daemon if it exits prematurely
186 */
187 if ((pid = fork()) < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000188 ALOGE("fork failed (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800189 close(pipefd[0]);
190 close(pipefd[1]);
191 return -1;
192 }
193
194 if (!pid) {
195 close(pipefd[1]);
196 if (pipefd[0] != STDIN_FILENO) {
197 if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
Steve Block5ea0c052012-01-06 19:18:11 +0000198 ALOGE("dup2 failed (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800199 return -1;
200 }
201 close(pipefd[0]);
202 }
San Mehat9d10b342010-01-18 09:51:02 -0800203
Dmitry Shmidtbc775ed2013-12-12 16:41:16 -0800204 int num_processed_args = TETHER_START_CONST_ARG + (num_addrs/2) + 1;
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700205 char **args = (char **)malloc(sizeof(char *) * num_processed_args);
206 args[num_processed_args - 1] = NULL;
207 args[0] = (char *)"/system/bin/dnsmasq";
Peter Nilssonb756f692011-09-08 09:48:31 -0700208 args[1] = (char *)"--keep-in-foreground";
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700209 args[2] = (char *)"--no-resolv";
210 args[3] = (char *)"--no-poll";
Dmitry Shmidtbc775ed2013-12-12 16:41:16 -0800211 args[4] = (char *)"--dhcp-authoritative";
Jeff Sharkey6df79da2012-04-18 21:53:35 -0700212 // TODO: pipe through metered status from ConnService
Dmitry Shmidtbc775ed2013-12-12 16:41:16 -0800213 args[5] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
214 args[6] = (char *)"--pid-file";
215 args[7] = (char *)"";
San Mehat9d10b342010-01-18 09:51:02 -0800216
Dmitry Shmidtbc775ed2013-12-12 16:41:16 -0800217 int nextArg = TETHER_START_CONST_ARG;
Robert Greenwalt3208ea02010-03-24 16:32:55 -0700218 for (int addrIndex=0; addrIndex < num_addrs;) {
219 char *start = strdup(inet_ntoa(addrs[addrIndex++]));
220 char *end = strdup(inet_ntoa(addrs[addrIndex++]));
221 asprintf(&(args[nextArg++]),"--dhcp-range=%s,%s,1h", start, end);
222 }
223
224 if (execv(args[0], args)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000225 ALOGE("execl failed (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800226 }
Steve Block5ea0c052012-01-06 19:18:11 +0000227 ALOGE("Should never get here!");
JP Abgrallce4f3792012-08-06 13:44:44 -0700228 _exit(-1);
San Mehat9d10b342010-01-18 09:51:02 -0800229 } else {
230 close(pipefd[0]);
231 mDaemonPid = pid;
232 mDaemonFd = pipefd[1];
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800233 applyDnsInterfaces();
Steve Block7b984e32011-12-20 16:22:42 +0000234 ALOGD("Tethering services running");
San Mehat9d10b342010-01-18 09:51:02 -0800235 }
236
237 return 0;
238}
239
240int TetherController::stopTethering() {
241
242 if (mDaemonPid == 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000243 ALOGE("Tethering already stopped");
San Mehat9d10b342010-01-18 09:51:02 -0800244 return 0;
245 }
246
Steve Block7b984e32011-12-20 16:22:42 +0000247 ALOGD("Stopping tethering services");
San Mehat9d10b342010-01-18 09:51:02 -0800248
249 kill(mDaemonPid, SIGTERM);
San Mehat18737842010-01-21 09:22:43 -0800250 waitpid(mDaemonPid, NULL, 0);
San Mehat9d10b342010-01-18 09:51:02 -0800251 mDaemonPid = 0;
252 close(mDaemonFd);
253 mDaemonFd = -1;
Steve Block7b984e32011-12-20 16:22:42 +0000254 ALOGD("Tethering services stopped");
San Mehat9d10b342010-01-18 09:51:02 -0800255 return 0;
256}
Matthew Xie19944102012-07-12 16:42:07 -0700257
San Mehat9d10b342010-01-18 09:51:02 -0800258bool TetherController::isTetheringStarted() {
259 return (mDaemonPid == 0 ? false : true);
260}
261
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600262int TetherController::startV6RtrAdv(int num_ifaces, char **ifaces, int table_number) {
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600263 int pid;
264 int num_processed_args = 1;
265 gid_t groups [] = { AID_NET_ADMIN, AID_NET_RAW, AID_INET };
266
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600267 if (num_ifaces < RTRADVDAEMON_MIN_IFACES) {
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600268 ALOGD("Need atleast two interfaces to start Router advertisement daemon");
269 return 0;
270 }
271
272 if ((pid = fork()) < 0) {
273 ALOGE("%s: fork failed (%s)", __func__, strerror(errno));
274 return -1;
275 }
276 if (!pid) {
277 char **args;
278 const char *cmd = RTRADVDAEMON;
279
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600280 args = (char **)calloc(num_ifaces * 3 + RTRADVDAEMON_ARGS_COUNT, sizeof(char *));
281 if (!args) {
282 ALOGE("%s: failed to allocate memory", __func__);
283 return -1;
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600284 }
285
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600286 args[0] = strdup(RTRADVDAEMON);
287 int aidx = 0;
288 for (int i=0; i < num_ifaces; i++) {
289 aidx = 3 * i + num_processed_args;
290 args[aidx++] = (char *)"-i";
291 args[aidx++] = ifaces[i];
292 args[aidx++] = (char *)"-x";
293 }
294 if (table_number > MIN_TABLE_NUMBER) {
295 char table_name[MAX_TABLE_LEN];
296 unsigned int retval = 0;
297 table_number += BASE_TABLE_NUMBER;
298 retval = snprintf(table_name, sizeof(table_name), "%d", table_number);
299 if (retval >= sizeof(table_name)) {
300 ALOGE("%s: String truncation occured", __func__);
301 } else {
302 args[aidx++] = (char *)"-t";
303 args[aidx] = table_name;
304 }
305 }
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600306
307 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
308 setresgid(AID_RADIO, AID_RADIO, AID_RADIO);
309 setresuid(AID_RADIO, AID_RADIO, AID_RADIO);
310
311 if (execv(cmd, args)) {
312 ALOGE("Unable to exec %s: (%s)" , cmd, strerror(errno));
313 }
314 free(args[0]);
315 free(args);
316 exit(0);
317 } else {
318 mRtrAdvPid = pid;
319 ALOGD("Router advertisement daemon running");
320 }
321 return 0;
322}
323
324int TetherController::stopV6RtrAdv() {
325 if (!mRtrAdvPid) {
326 ALOGD("Router advertisement daemon already stopped");
327 return 0;
328 }
329
330 kill(mRtrAdvPid, SIGTERM);
331 waitpid(mRtrAdvPid, NULL, 0);
332 mRtrAdvPid = 0;
333 ALOGD("Router advertisement daemon stopped");
334 return 0;
335}
336
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600337int TetherController::getIfaceIndexForIface(const char *iface)
338{
339 FILE *fp = NULL;
340 char res[MAX_TABLE_LEN];
341 int iface_num = -1;
342 char if_index[SYS_PATH_SIZE];
343 unsigned int retval = 0;
344 if (iface == NULL)
345 {
346 ALOGE("%s() Interface is NULL", __func__);
347 return iface_num;
348 }
349
350 memset(if_index, 0, sizeof(if_index));
351 retval = snprintf(if_index, sizeof(if_index), IF_INDEX_PATH, iface);
352 if (retval >= sizeof(if_index)) {
353 ALOGE("%s() String truncation occurred", __func__);
354 return iface_num;
355 }
356
357 ALOGD("%s() File path is %s", __func__, if_index);
358 fp = fopen(if_index, "r");
359 if (fp == NULL)
360 {
361 ALOGE("%s() Cannot read file : path %s, error %s", __func__, if_index, strerror(errno));
362 return iface_num;
363 }
364
365 memset(res, 0, sizeof(res));
366 while (fgets(res, sizeof(res)-1, fp) != NULL)
367 {
368 ALOGD("%s() %s", __func__, res);
369 iface_num = atoi(res);
370 ALOGD("%s() Interface index for interface %s is %d", __func__, iface, iface_num);
371 }
372
373 fclose(fp);
374 return iface_num;
375}
376
377/* Stop and start the ipv6 router advertisement daemon with the updated
378 * interfaces. Pass the table number as a command line argument when
379 * tethering is enabled.
380 */
381int TetherController::configureV6RtrAdv() {
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600382 char **args;
383 int i;
384 int len;
385 InterfaceCollection::iterator it;
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600386 int iface_index = -1;
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600387 /* For now, just stop and start the daemon with the new interface list */
388
389 len = mInterfaces->size() + mUpstreamInterfaces->size();
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600390 args = (char **)calloc(len, sizeof(char *));
391
392 if (!args) {
393 errno = ENOMEM;
394 return -1;
395 }
396
397 for (i = 0, it = mInterfaces->begin(); it != mInterfaces->end(); it++, i++) {
398 args[i] = *it;
399 }
400
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600401 for (it = mUpstreamInterfaces->begin(); i < len && it != mUpstreamInterfaces->end(); it++, i++)
402 {
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600403 args[i] = *it;
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600404 iface_index = getIfaceIndexForIface(args[i]);
405 ALOGD("%s: Upstream Iface: %s iface index: %d", __func__, args[i], iface_index);
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600406 }
407
408 stopV6RtrAdv();
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600409 startV6RtrAdv(i, args, iface_index);
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600410
411 free(args);
412
413 return 0;
414}
415
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600416bool TetherController::isV6RtrAdvStarted() {
417 return (mRtrAdvPid == 0 ? false : true);
418}
419
Kenny Rootcf52faf2010-02-18 09:59:55 -0800420#define MAX_CMD_SIZE 1024
421
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700422int TetherController::setDnsForwarders(unsigned netId, char **servers, int numServers) {
San Mehat9d10b342010-01-18 09:51:02 -0800423 int i;
Kenny Rootcf52faf2010-02-18 09:59:55 -0800424 char daemonCmd[MAX_CMD_SIZE];
San Mehat9d10b342010-01-18 09:51:02 -0800425
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700426 Fwmark fwmark;
427 fwmark.netId = netId;
428 fwmark.explicitlySelected = true;
429 fwmark.protectedFromVpn = true;
430 fwmark.permission = PERMISSION_SYSTEM;
431
432 snprintf(daemonCmd, sizeof(daemonCmd), "update_dns:0x%x", fwmark.intValue);
Kenny Rootcf52faf2010-02-18 09:59:55 -0800433 int cmdLen = strlen(daemonCmd);
San Mehat9d10b342010-01-18 09:51:02 -0800434
435 mDnsForwarders->clear();
436 for (i = 0; i < numServers; i++) {
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700437 ALOGD("setDnsForwarders(0x%x %d = '%s')", fwmark.intValue, i, servers[i]);
San Mehat9d10b342010-01-18 09:51:02 -0800438
439 struct in_addr a;
440
441 if (!inet_aton(servers[i], &a)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000442 ALOGE("Failed to parse DNS server '%s'", servers[i]);
San Mehat9d10b342010-01-18 09:51:02 -0800443 mDnsForwarders->clear();
444 return -1;
445 }
Kenny Rootcf52faf2010-02-18 09:59:55 -0800446
Nick Kralevichad5b41f2012-07-19 18:48:05 -0700447 cmdLen += (strlen(servers[i]) + 1);
448 if (cmdLen + 1 >= MAX_CMD_SIZE) {
Steve Block7b984e32011-12-20 16:22:42 +0000449 ALOGD("Too many DNS servers listed");
Kenny Rootcf52faf2010-02-18 09:59:55 -0800450 break;
451 }
452
San Mehat9d10b342010-01-18 09:51:02 -0800453 strcat(daemonCmd, ":");
454 strcat(daemonCmd, servers[i]);
455 mDnsForwarders->push_back(a);
456 }
457
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700458 mDnsNetId = netId;
San Mehat9d10b342010-01-18 09:51:02 -0800459 if (mDaemonFd != -1) {
Steve Block7b984e32011-12-20 16:22:42 +0000460 ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
San Mehat9d10b342010-01-18 09:51:02 -0800461 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000462 ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
San Mehat9d10b342010-01-18 09:51:02 -0800463 mDnsForwarders->clear();
464 return -1;
465 }
466 }
467 return 0;
468}
469
Lorenzo Colitti667c4772014-08-26 14:13:07 -0700470unsigned TetherController::getDnsNetId() {
471 return mDnsNetId;
472}
473
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600474int TetherController::addUpstreamInterface(char *iface)
475{
476 InterfaceCollection::iterator it;
477
478 ALOGD("addUpstreamInterface(%s)\n", iface);
479
480 if (!iface) {
481 ALOGE("addUpstreamInterface: received null interface");
482 return 0;
483 }
484 for (it = mUpstreamInterfaces->begin(); it != mUpstreamInterfaces->end(); ++it) {
485 ALOGD(".");
486 if (*it && !strcmp(iface, *it)) {
487 ALOGD("addUpstreamInterface: interface %s already present", iface);
488 return 0;
489 }
490 }
491 mUpstreamInterfaces->push_back(strdup(iface));
492
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600493 return configureV6RtrAdv();
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600494}
495
496int TetherController::removeUpstreamInterface(char *iface)
497{
498 InterfaceCollection::iterator it;
499
500 if (!iface) {
501 ALOGE("removeUpstreamInterface: Null interface name received");
502 return 0;
503 }
504 for (it = mUpstreamInterfaces->begin(); it != mUpstreamInterfaces->end(); ++it) {
505 if (*it && !strcmp(iface, *it)) {
506 free(*it);
507 mUpstreamInterfaces->erase(it);
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600508 return configureV6RtrAdv();
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600509 }
510 }
511
512 ALOGW("Couldn't find interface %s to remove", iface);
513 return 0;
514}
515
San Mehat9d10b342010-01-18 09:51:02 -0800516NetAddressCollection *TetherController::getDnsForwarders() {
517 return mDnsForwarders;
518}
519
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800520int TetherController::applyDnsInterfaces() {
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800521 char daemonCmd[MAX_CMD_SIZE];
522
523 strcpy(daemonCmd, "update_ifaces");
524 int cmdLen = strlen(daemonCmd);
525 InterfaceCollection::iterator it;
526 bool haveInterfaces = false;
527
528 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
529 cmdLen += (strlen(*it) + 1);
530 if (cmdLen + 1 >= MAX_CMD_SIZE) {
531 ALOGD("Too many DNS ifaces listed");
532 break;
533 }
534
535 strcat(daemonCmd, ":");
536 strcat(daemonCmd, *it);
537 haveInterfaces = true;
538 }
539
540 if ((mDaemonFd != -1) && haveInterfaces) {
541 ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
542 if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
543 ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
544 return -1;
545 }
546 }
San Mehat9d10b342010-01-18 09:51:02 -0800547 return 0;
548}
549
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800550int TetherController::tetherInterface(const char *interface) {
551 ALOGD("tetherInterface(%s)", interface);
JP Abgrall69261cb2014-06-19 18:35:24 -0700552 if (!isIfaceName(interface)) {
553 errno = ENOENT;
554 return -1;
555 }
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800556 mInterfaces->push_back(strdup(interface));
557
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600558 configureV6RtrAdv();
Subash Abhinov Kasiviswanathan0e217b52014-07-15 00:08:40 -0600559
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800560 if (applyDnsInterfaces()) {
561 InterfaceCollection::iterator it;
562 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
563 if (!strcmp(interface, *it)) {
564 free(*it);
565 mInterfaces->erase(it);
566 break;
567 }
568 }
569 return -1;
570 } else {
571 return 0;
572 }
573}
574
San Mehat9d10b342010-01-18 09:51:02 -0800575int TetherController::untetherInterface(const char *interface) {
576 InterfaceCollection::iterator it;
577
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800578 ALOGD("untetherInterface(%s)", interface);
579
San Mehat9d10b342010-01-18 09:51:02 -0800580 for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
581 if (!strcmp(interface, *it)) {
582 free(*it);
583 mInterfaces->erase(it);
Subash Abhinov Kasiviswanathan2f1cf8a2014-10-20 13:04:32 -0600584 configureV6RtrAdv();
Robert Greenwalt3d4c7582012-12-11 12:33:37 -0800585 return applyDnsInterfaces();
San Mehat9d10b342010-01-18 09:51:02 -0800586 }
587 }
588 errno = ENOENT;
589 return -1;
590}
591
592InterfaceCollection *TetherController::getTetheredInterfaceList() {
593 return mInterfaces;
594}