18
18
#include < errno.h>
19
19
#include < fcntl.h>
20
20
#include < string.h>
21
+ #include < dirent.h>
21
22
22
23
#include < dlfcn.h>
23
24
@@ -43,8 +44,17 @@ char set_cmd_func_name[] = "net_iface_send_command";
43
44
char set_cmd_init_func_name[] = " net_iface_send_command_init" ;
44
45
char set_cmd_fini_func_name[] = " net_iface_send_command_fini" ;
45
46
47
+ const char ipv6_proc_path[] = " /proc/sys/net/ipv6/conf" ;
48
+
46
49
InterfaceController::InterfaceController ()
47
50
: 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
+
48
58
libh_ = dlopen (if_cmd_lib_file_name, RTLD_NOW | RTLD_LOCAL);
49
59
if (libh_ == NULL ) {
50
60
const char *err_str = dlerror ();
@@ -104,20 +114,13 @@ int InterfaceController::interfaceCommand(int argc, char *argv[], char **rbuf) {
104
114
105
115
int InterfaceController::writeIPv6ProcPath (const char *interface, const char *setting, const char *value) {
106
116
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);
108
118
int success = writeFile (path, value, strlen (value));
109
119
free (path);
110
120
return success;
111
121
}
112
122
113
123
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
-
121
124
// When disable_ipv6 changes from 1 to 0, the kernel starts autoconf.
122
125
// When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf
123
126
// addresses and routes and disables IPv6 on the interface.
@@ -130,3 +133,33 @@ int InterfaceController::setIPv6PrivacyExtensions(const char *interface, const i
130
133
// 0: enable IPv6 privacy addresses and prefer them over non-privacy ones.
131
134
return writeIPv6ProcPath (interface, " use_tempaddr" , on ? " 2" : " 0" );
132
135
}
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
+ }
0 commit comments