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:
Sreeram Ramachandran 2014-05-12 11:19:16 -07:00
parent 0ccef7ec52
commit ceb5bd787c
12 changed files with 141 additions and 14 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View 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
View 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);
}

View File

@ -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
View 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