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 }