Skip to content

Commit 37f2e37

Browse files
committed
Set accept_ra to 2 on all interfaces
Currently, we set accept_ra to 2 (accept RAs even if forwarding is on) only on wifi and ethernet, but not on other interfaces like mobile. This breaks IPv6 over mobile on Nexus 7 3G and all other devices where the IPv6 default route is configured via RA, because as soon as we start 464xlat (which enables forwarding) their default route goes away. Rather than require all manufacturers to update their RILs to set the flag themselves, set it ourselves at netd startup time. Bug: 8276725 Change-Id: If066bb1aa3ff211da0a0bbe8d58d5a7f35298580
1 parent 1d18162 commit 37f2e37

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

InterfaceController.cpp

+41-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <errno.h>
1919
#include <fcntl.h>
2020
#include <string.h>
21+
#include <dirent.h>
2122

2223
#include <dlfcn.h>
2324

@@ -43,8 +44,17 @@ char set_cmd_func_name[] = "net_iface_send_command";
4344
char set_cmd_init_func_name[] = "net_iface_send_command_init";
4445
char set_cmd_fini_func_name[] = "net_iface_send_command_fini";
4546

47+
const char ipv6_proc_path[] = "/proc/sys/net/ipv6/conf";
48+
4649
InterfaceController::InterfaceController()
4750
: sendCommand_(NULL) {
51+
// Initial IPv6 settings.
52+
// By default, accept_ra is set to 1 (accept RAs unless forwarding is on) on all interfaces.
53+
// This causes RAs to work or not work based on whether forwarding is on, and causes routes
54+
// learned from RAs to go away when forwarding is turned on. Make this behaviour predictable
55+
// by always setting accept_ra to 2.
56+
setAcceptRA("2");
57+
4858
libh_ = dlopen(if_cmd_lib_file_name, RTLD_NOW | RTLD_LOCAL);
4959
if (libh_ == NULL) {
5060
const char *err_str = dlerror();
@@ -104,20 +114,13 @@ int InterfaceController::interfaceCommand(int argc, char *argv[], char **rbuf) {
104114

105115
int InterfaceController::writeIPv6ProcPath(const char *interface, const char *setting, const char *value) {
106116
char *path;
107-
asprintf(&path, "/proc/sys/net/ipv6/conf/%s/%s", interface, setting);
117+
asprintf(&path, "%s/%s/%s", ipv6_proc_path, interface, setting);
108118
int success = writeFile(path, value, strlen(value));
109119
free(path);
110120
return success;
111121
}
112122

113123
int InterfaceController::setEnableIPv6(const char *interface, const int on) {
114-
// When IPv6 is on, accept RAs regardless of forwarding state.
115-
// When IPv6 is off, accept RAs only if forwarding is off (the default).
116-
const char *accept_ra = on ? "2" : "1";
117-
if (writeIPv6ProcPath(interface, "accept_ra", accept_ra)) {
118-
return -1;
119-
}
120-
121124
// When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
122125
// When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
123126
// addresses and routes and disables IPv6 on the interface.
@@ -130,3 +133,33 @@ int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const i
130133
// 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
131134
return writeIPv6ProcPath(interface, "use_tempaddr", on ? "2" : "0");
132135
}
136+
137+
int InterfaceController::isInterfaceName(const char *name) {
138+
return strcmp(name, ".") &&
139+
strcmp(name, "..") &&
140+
strcmp(name, "default") &&
141+
strcmp(name, "all");
142+
}
143+
144+
int InterfaceController::setAcceptRA(const char *value) {
145+
// Set the default value, which is used by any interfaces that are created in the future.
146+
writeIPv6ProcPath("default", "accept_ra", value);
147+
148+
// Set the value on all the interfaces.
149+
DIR *dir = opendir(ipv6_proc_path);
150+
if (!dir) {
151+
ALOGE("Can't list %s: %s", ipv6_proc_path, strerror(errno));
152+
return -errno;
153+
}
154+
struct dirent *d;
155+
while((d = readdir(dir)) != NULL) {
156+
if (d->d_type == DT_DIR && isInterfaceName(d->d_name)) {
157+
if (writeIPv6ProcPath(d->d_name, "accept_ra", value) < 0) {
158+
ALOGE("Can't write to %s/%s/accept_ra: %s", ipv6_proc_path,
159+
d->d_name, strerror(errno));
160+
}
161+
}
162+
}
163+
closedir(dir);
164+
return 0;
165+
}

InterfaceController.h

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class InterfaceController {
4343
int (*sendCommandFini_)(void);
4444
int writeIPv6ProcPath(const char *interface, const char *setting,
4545
const char *value);
46+
int isInterfaceName(const char *name);
47+
int setAcceptRA(const char *value);
4648
};
4749

4850
#endif

0 commit comments

Comments
 (0)