InterfaceController.cpp revision 70afde6ad9b5fce63cca594ac9b230d2fc9b21ee
12eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt/* 22eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Copyright (C) 2012 The Android Open Source Project 32eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * 42eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Licensed under the Apache License, Version 2.0 (the "License"); 52eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * you may not use this file except in compliance with the License. 62eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * You may obtain a copy of the License at 72eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * 8329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy * http://www.apache.org/licenses/LICENSE-2.0 92eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * 102eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Unless required by applicable law or agreed to in writing, software 112eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * distributed under the License is distributed on an "AS IS" BASIS, 122eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * See the License for the specific language governing permissions and 142eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * limitations under the License. 152eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt */ 162eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 172eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <stdlib.h> 182eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <errno.h> 192eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <fcntl.h> 202eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <string.h> 212eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 22329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy#include <dlfcn.h> 23329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy 242eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <sys/socket.h> 252eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <sys/stat.h> 262eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <sys/ioctl.h> 272eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <sys/types.h> 282eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 292eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <netinet/in.h> 302eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <arpa/inet.h> 312eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 322eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#define LOG_TAG "InterfaceController" 332eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <cutils/log.h> 342eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <netutils/ifc.h> 352eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include <private/android_filesystem_config.h> 362eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 3770afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti#include "NetdConstants.h" 3870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti 392eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt#include "InterfaceController.h" 402eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 41329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiychar if_cmd_lib_file_name[] = "/system/lib/libnetcmdiface.so"; 42329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiychar set_cmd_func_name[] = "net_iface_send_command"; 43329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiychar set_cmd_init_func_name[] = "net_iface_send_command_init"; 44329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiychar set_cmd_fini_func_name[] = "net_iface_send_command_fini"; 452eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 46329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha LevitskiyInterfaceController::InterfaceController() 47329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy : sendCommand_(NULL) { 48329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy libh_ = dlopen(if_cmd_lib_file_name, RTLD_NOW | RTLD_LOCAL); 49329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (libh_ == NULL) { 50329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy const char *err_str = dlerror(); 5187482aa6d64b835ce8f6485fd5b0953d939ed94fSasha Levitskiy ALOGW("Warning (%s) while opening the net interface command library", err_str ? err_str : "unknown"); 52329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } else { 53329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy sendCommandInit_ = (int (*)(void))dlsym(libh_, set_cmd_init_func_name); 54329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommandInit_ == NULL) { 55329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy const char *err_str = dlerror(); 56329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGW("Error (%s) while searching for the interface command init function", err_str ? err_str : "unknown"); 57329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } else if (sendCommandInit_()) { 58329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGE("Can't init the interface command API"); 59329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy return; 60329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 61329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy sendCommandFini_ = (int (*)(void))dlsym(libh_, set_cmd_fini_func_name); 62329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommandFini_ == NULL) { 63329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy const char *err_str = dlerror(); 64329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGW("Error (%s) while searching for the interface command fini function", err_str ? err_str : "unknown"); 65329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 66329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy sendCommand_ = (int (*)(int, char **, char **))dlsym(libh_, set_cmd_func_name); 67329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommand_ == NULL) { 68329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy const char *err_str = dlerror(); 69329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGE("Error (%s) while searching for the interface command function", err_str ? err_str : "unknown"); 70329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy return; 71329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 72329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 732eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt} 742eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 75329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha LevitskiyInterfaceController::~InterfaceController() { 76329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommandFini_) { 77329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommandFini_()) { 78329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGE("Can't shutdown the interface command API"); 79329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 80329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 81329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (libh_) { 82329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy int err = dlclose(libh_); 83329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (err) { 84329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy const char *err_str = dlerror(); 85329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ALOGE("Error (%s) while closing the net interface command library", err_str ? err_str : "unknown"); 86329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 87329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy } 882eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt} 892eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 902eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt/* 912eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt * Arguments: 92329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy * argv[2] - wlan interface 93329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy * argv[3] - command 94329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy * argv[4] - argument 95329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy * rbuf - returned buffer 962eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt */ 972eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidtint InterfaceController::interfaceCommand(int argc, char *argv[], char **rbuf) { 98329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy int ret = -ENOSYS; 99329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy if (sendCommand_) 100329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy ret = sendCommand_(argc, argv, rbuf); 1012eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt 102329c3b4681e2ca4831adc7c8cf257e9e32971710Sasha Levitskiy return ret; 1032eab1f762badb7ba46b95716e62ea4548a979903Dmitry Shmidt} 10470afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti 10570afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::writeIPv6ProcPath(const char *interface, const char *setting, const char *value) { 10670afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti char *path; 10770afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti asprintf(&path, "/proc/sys/net/ipv6/conf/%s/%s", interface, setting); 10870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti int success = writeFile(path, value, strlen(value)); 10970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti free(path); 11070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti return success; 11170afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti} 11270afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti 11370afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setEnableIPv6(const char *interface, const int on) { 11470afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti // When disable_ipv6 changes from 1 to 0, the kernel starts autoconf. 11570afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti // When disable_ipv6 changes from 0 to 1, the kernel clears all autoconf 11670afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti // addresses and routes and disables IPv6 on the interface. 11770afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti const char *disable_ipv6 = on ? "0" : "1"; 11870afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti return writeIPv6ProcPath(interface, "disable_ipv6", disable_ipv6); 11970afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti} 12070afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti 12170afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colittiint InterfaceController::setIPv6PrivacyExtensions(const char *interface, const int on) { 12270afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti // 0: disable IPv6 privacy addresses 12370afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti // 0: enable IPv6 privacy addresses and prefer them over non-privacy ones. 12470afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti return writeIPv6ProcPath(interface, "use_tempaddr", on ? "2" : "0"); 12570afde6ad9b5fce63cca594ac9b230d2fc9b21eeLorenzo Colitti} 126