Introduce netd_client, a dynamic library that talks to netd.
The library exists outside bionic. It is dynamically loaded, to replace selected standard socket syscalls with versions that talk to netd. Change connect() to use the library if available. (cherry picked from commit 3a6b627a14df8111b03e452f2df4b5f4938e0e49) Change-Id: Ib6198e19dbc306521a26fcecfdf6e8424d163fc9
This commit is contained in:
parent
0ccef7ec52
commit
ceb5bd787c
@ -110,6 +110,7 @@ libc_bionic_src_files := \
|
||||
bionic/clock.cpp \
|
||||
bionic/clone.cpp \
|
||||
bionic/cmsg_nxthdr.cpp \
|
||||
bionic/connect.cpp \
|
||||
bionic/dirent.cpp \
|
||||
bionic/dup2.cpp \
|
||||
bionic/epoll_create.cpp \
|
||||
@ -141,6 +142,7 @@ libc_bionic_src_files := \
|
||||
bionic/mkfifo.cpp \
|
||||
bionic/mknod.cpp \
|
||||
bionic/mntent.cpp \
|
||||
bionic/NetdClient.cpp \
|
||||
bionic/open.cpp \
|
||||
bionic/pause.cpp \
|
||||
bionic/pipe.cpp \
|
||||
|
@ -234,7 +234,7 @@ int signalfd4(int, const sigset_t*, size_t, int) all
|
||||
int socket(int, int, int) arm,arm64,mips,mips64,x86_64
|
||||
int socketpair(int, int, int, int*) arm,arm64,mips,mips64,x86_64
|
||||
int bind(int, struct sockaddr*, int) arm,arm64,mips,mips64,x86_64
|
||||
int connect(int, struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
|
||||
int __connect:connect(int, struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
|
||||
int listen(int, int) arm,arm64,mips,mips64,x86_64
|
||||
int accept(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
|
||||
int accept4(int, struct sockaddr*, socklen_t*, int) arm,arm64,mips,mips64,x86_64
|
||||
@ -253,7 +253,7 @@ int sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips
|
||||
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
|
||||
int socket:socketcall:1(int, int, int) x86
|
||||
int bind:socketcall:2(int, struct sockaddr*, int) x86
|
||||
int connect:socketcall:3(int, struct sockaddr*, socklen_t) x86
|
||||
int __connect:socketcall:3(int, struct sockaddr*, socklen_t) x86
|
||||
int listen:socketcall:4(int, int) x86
|
||||
int accept:socketcall:5(int, struct sockaddr*, socklen_t*) x86
|
||||
int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_connect
|
||||
swi #0
|
||||
@ -11,4 +11,4 @@ ENTRY(connect)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno
|
||||
END(connect)
|
||||
END(__connect)
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
stp x29, x30, [sp, #-16]!
|
||||
mov x29, sp
|
||||
str x8, [sp, #-16]!
|
||||
@ -18,4 +18,5 @@ ENTRY(connect)
|
||||
b.hi __set_errno
|
||||
|
||||
ret
|
||||
END(connect)
|
||||
END(__connect)
|
||||
.hidden __connect
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_connect
|
||||
@ -16,4 +16,4 @@ ENTRY(connect)
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(connect)
|
||||
END(__connect)
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_connect
|
||||
@ -22,4 +22,5 @@ ENTRY(connect)
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(connect)
|
||||
END(__connect)
|
||||
.hidden __connect
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
.cfi_def_cfa_offset 8
|
||||
@ -24,4 +24,4 @@ ENTRY(connect)
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(connect)
|
||||
END(__connect)
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(connect)
|
||||
ENTRY(__connect)
|
||||
movl $__NR_connect, %eax
|
||||
syscall
|
||||
cmpq $-MAX_ERRNO, %rax
|
||||
@ -13,4 +13,5 @@ ENTRY(connect)
|
||||
orq $-1, %rax
|
||||
1:
|
||||
ret
|
||||
END(connect)
|
||||
END(__connect)
|
||||
.hidden __connect
|
68
libc/bionic/NetdClient.cpp
Normal file
68
libc/bionic/NetdClient.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <private/NetdClient.h>
|
||||
#include <private/libc_logging.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __i386__
|
||||
#define __socketcall __attribute__((__cdecl__))
|
||||
#else
|
||||
#define __socketcall
|
||||
#endif
|
||||
|
||||
extern "C" __socketcall int __connect(int, const sockaddr*, socklen_t);
|
||||
|
||||
NetdClientDispatch __netdClientDispatch __attribute__((aligned(32))) = {
|
||||
__connect
|
||||
};
|
||||
|
||||
#ifndef LIBC_STATIC
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
template <typename FunctionType>
|
||||
static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
|
||||
typedef void (*InitFunctionType)(FunctionType*);
|
||||
InitFunctionType initFunction = reinterpret_cast<InitFunctionType>(dlsym(handle, symbol));
|
||||
if (initFunction != NULL) {
|
||||
initFunction(function);
|
||||
}
|
||||
}
|
||||
|
||||
static void netdClientInitImpl() {
|
||||
void* netdClientHandle = dlopen("libnetd_client.so", RTLD_LAZY);
|
||||
if (netdClientHandle == NULL) {
|
||||
// If the library is not available, it's not an error. We'll just use
|
||||
// default implementations of functions that it would've overridden.
|
||||
return;
|
||||
}
|
||||
netdClientInitFunction(netdClientHandle, "netdClientInitConnect",
|
||||
&__netdClientDispatch.connect);
|
||||
}
|
||||
|
||||
static pthread_once_t netdClientInitOnce = PTHREAD_ONCE_INIT;
|
||||
|
||||
#endif // LIBC_STATIC
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void netdClientInit() {
|
||||
#ifndef LIBC_STATIC
|
||||
if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "netdClient",
|
||||
"Unable to initialize netd_client component.");
|
||||
}
|
||||
#endif // LIBC_STATIC
|
||||
}
|
22
libc/bionic/connect.cpp
Normal file
22
libc/bionic/connect.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <private/NetdClient.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int connect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
|
||||
return __netdClientDispatch.connect(sockfd, addr, addrlen);
|
||||
}
|
@ -58,6 +58,7 @@ extern "C" {
|
||||
extern void pthread_debug_init(void);
|
||||
extern void malloc_debug_init(void);
|
||||
extern void malloc_debug_fini(void);
|
||||
extern void netdClientInit(void);
|
||||
};
|
||||
|
||||
// We flag the __libc_preinit function as a constructor to ensure
|
||||
@ -79,6 +80,9 @@ __attribute__((constructor)) static void __libc_preinit() {
|
||||
// Hooks for the debug malloc and pthread libraries to let them know that we're starting up.
|
||||
pthread_debug_init();
|
||||
malloc_debug_init();
|
||||
|
||||
// Hook for the netd client library to let it know that we're starting up.
|
||||
netdClientInit();
|
||||
}
|
||||
|
||||
__LIBC_HIDDEN__ void __libc_postfini() {
|
||||
|
28
libc/private/NetdClient.h
Normal file
28
libc/private/NetdClient.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef PRIVATE_NETD_CLIENT_H
|
||||
#define PRIVATE_NETD_CLIENT_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
struct NetdClientDispatch {
|
||||
int (*connect)(int, const sockaddr*, socklen_t);
|
||||
};
|
||||
|
||||
extern NetdClientDispatch __netdClientDispatch;
|
||||
|
||||
#endif // PRIVATE_NETD_CLIENT_H
|
Loading…
Reference in New Issue
Block a user