socket是网络编程的基础,Android中socket接口定义在bionic里面,Android5.0后,为了更好使用fwmark,用netd中的函数实现部分代替了bionic的socket实现。
上代码
bionic/libc/bionic/libc_init_dynamic.cpp
// We flag the __libc_preinit function as a constructor to ensure 64 // that its address is listed in libc.so's .init_array section. 65 // This ensures that the function is called by the dynamic linker 66 // as soon as the shared library is loaded. 67 __attribute__((constructor)) static void __libc_preinit() { 68 // Read the kernel argument block pointer from TLS. 69 void** tls = __get_tls(); 70 KernelArgumentBlock** args_slot = &reinterpret_cast<KernelArgumentBlock**>(tls)[TLS_SLOT_BIONIC_PREINIT]; 71 KernelArgumentBlock* args = *args_slot; 72 73 // Clear the slot so no other initializer sees its value. 74 // __libc_init_common() will change the TLS area so the old one won't be accessible anyway. 75 *args_slot = NULL; 76 77 __libc_init_common(*args); 78 79 // Hooks for various libraries to let them know that we're starting up. 80 malloc_debug_init(); 81 <span style="background-color: rgb(255, 255, 102);">netdClientInit();</span> 82 }上面的代码在libc动态库加载的时候回执行
bionic/libc/bionic/NetdClient.cpp
template <typename FunctionType> 28 static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) { 29 typedef void (*InitFunctionType)(FunctionType*); 30 InitFunctionType initFunction = reinterpret_cast<InitFunctionType>(dlsym(handle, symbol)); 31 if (initFunction != NULL) { 32 initFunction(function); 33 } 34 } 35 36 static void netdClientInitImpl() { 37 void* netdClientHandle = dlopen("libnetd_client.so", RTLD_LAZY); 38 if (netdClientHandle == NULL) { 39 // If the library is not available, it's not an error. We'll just use 40 // default implementations of functions that it would've overridden. 41 return; 42 } 43 netdClientInitFunction(netdClientHandle, "netdClientInitAccept4", 44 &__netdClientDispatch.accept4); 45 netdClientInitFunction(netdClientHandle, "netdClientInitConnect", 46 &__netdClientDispatch.connect); 47 netdClientInitFunction(netdClientHandle, "netdClientInitNetIdForResolv", 48 &__netdClientDispatch.netIdForResolv); 49 netdClientInitFunction(netdClientHandle, "netdClientInitSocket", &__netdClientDispatch.socket); 50 } 51 52 static pthread_once_t netdClientInitOnce = PTHREAD_ONCE_INIT; 53 54 extern "C" __LIBC_HIDDEN__ void <span style="background-color: rgb(255, 255, 102);">netdClientInit</span>() { 55 if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) { 56 __libc_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client"); 57 } 58 }上面代码中,netdClientInitFunction最终完成了bionic到netd的映射
下面这段代码就是bionic中提供给上层的接口
bionic/libc/bionic/accept4.cpp
int accept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) { 22 return __netdClientDispatch.accept4(sockfd, addr, addrlen, flags); 23 }
// This structure is modified only at startup (when libc.so is loaded) and never 34 // afterwards, so it's okay that it's read later at runtime without a lock. 35 __LIBC_HIDDEN__ NetdClientDispatch __netdClientDispatch __attribute__((aligned(32))) = { 36 __accept4, 37 __connect, 38 __socket, 39 fallBackNetIdForResolv, 40 };__accept4等函数是汇编实现,完成到kernel的调用
system/netd/client/NetdClient.cpp
下面代码中netdClientInitAccept4就是bionic/libc/bionic/NetdClient.cpp中netdClientInitFunction中的参数netdClientInitAccept4,这样就完成了bionic到netd的映射
// accept() just calls accept4(..., 0), so there's no need to handle accept() separately. 139 extern "C" void netdClientInitAccept4(Accept4FunctionType* function) { 140 if (function && *function) { 141 libcAccept4 = *function; 142 *function = netdClientAccept4; 143 } 144 } 145 146 extern "C" void netdClientInitConnect(ConnectFunctionType* function) { 147 if (function && *function) { 148 libcConnect = *function; 149 *function = netdClientConnect; 150 } 151 } 152 153 extern "C" void netdClientInitSocket(SocketFunctionType* function) { 154 if (function && *function) { 155 libcSocket = *function; 156 *function = netdClientSocket; 157 } 158 } 159 160 extern "C" void netdClientInitNetIdForResolv(NetIdForResolvFunctionType* function) { 161 if (function) { 162 *function = getNetworkForResolv; 163 } 164 }
system/netd/client/NetdClient.cpp
下面是netd中accept4的实现,可以看到最终通过FwmarkServer对socket做mark
int netdClientAccept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) { 52 int acceptedSocket = libcAccept4(sockfd, addr, addrlen, flags); 53 if (acceptedSocket == -1) { 54 return -1; 55 } 56 int family; 57 if (addr) { 58 family = addr->sa_family; 59 } else { 60 socklen_t familyLen = sizeof(family); 61 if (getsockopt(acceptedSocket, SOL_SOCKET, SO_DOMAIN, &family, &familyLen) == -1) { 62 return closeFdAndSetErrno(acceptedSocket, -errno); 63 } 64 } 65 if (FwmarkClient::shouldSetFwmark(family)) { 66 FwmarkCommand command = {FwmarkCommand::ON_ACCEPT, 0, 0}; 67 if (int error = FwmarkClient().send(&command, sizeof(command), acceptedSocket)) { 68 return closeFdAndSetErrno(acceptedSocket, error); 69 } 70 } 71 return acceptedSocket; 72 }