Merge "We don't need two copies of <nsswitch.h>."
diff --git a/libc/Android.mk b/libc/Android.mk
index 5befacf..9eacb54 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -110,6 +110,7 @@
     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 @@
     bionic/mkfifo.cpp \
     bionic/mknod.cpp \
     bionic/mntent.cpp \
+    bionic/NetdClientDispatch.cpp \
     bionic/open.cpp \
     bionic/pause.cpp \
     bionic/pipe.cpp \
@@ -881,6 +883,7 @@
     bionic/debug_stacktrace.cpp \
     bionic/pthread_debug.cpp \
     bionic/libc_init_dynamic.cpp \
+    bionic/NetdClient.cpp \
 
 LOCAL_MODULE := libc
 LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 93ed85c..e9fb575 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -234,7 +234,7 @@
 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 @@
 # 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
diff --git a/libc/arch-arm/syscalls/connect.S b/libc/arch-arm/syscalls/__connect.S
similarity index 88%
rename from libc/arch-arm/syscalls/connect.S
rename to libc/arch-arm/syscalls/__connect.S
index f7a5188..8cb026c 100644
--- a/libc/arch-arm/syscalls/connect.S
+++ b/libc/arch-arm/syscalls/__connect.S
@@ -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 @@
     bxls    lr
     neg     r0, r0
     b       __set_errno
-END(connect)
+END(__connect)
diff --git a/libc/arch-arm64/syscalls/connect.S b/libc/arch-arm64/syscalls/__connect.S
similarity index 88%
rename from libc/arch-arm64/syscalls/connect.S
rename to libc/arch-arm64/syscalls/__connect.S
index d3cd43d..c46f418 100644
--- a/libc/arch-arm64/syscalls/connect.S
+++ b/libc/arch-arm64/syscalls/__connect.S
@@ -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 @@
     b.hi    __set_errno
 
     ret
-END(connect)
+END(__connect)
+.hidden __connect
diff --git a/libc/arch-mips/syscalls/connect.S b/libc/arch-mips/syscalls/__connect.S
similarity index 89%
rename from libc/arch-mips/syscalls/connect.S
rename to libc/arch-mips/syscalls/__connect.S
index 6f10652..f7ac916 100644
--- a/libc/arch-mips/syscalls/connect.S
+++ b/libc/arch-mips/syscalls/__connect.S
@@ -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 @@
     j t9
     nop
     .set reorder
-END(connect)
+END(__connect)
diff --git a/libc/arch-mips64/syscalls/connect.S b/libc/arch-mips64/syscalls/__connect.S
similarity index 87%
rename from libc/arch-mips64/syscalls/connect.S
rename to libc/arch-mips64/syscalls/__connect.S
index 8fe2d56..b1475fb 100644
--- a/libc/arch-mips64/syscalls/connect.S
+++ b/libc/arch-mips64/syscalls/__connect.S
@@ -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 @@
     j t9
     move ra, t0
     .set pop
-END(connect)
+END(__connect)
+.hidden __connect
diff --git a/libc/arch-x86/syscalls/connect.S b/libc/arch-x86/syscalls/__connect.S
similarity index 94%
rename from libc/arch-x86/syscalls/connect.S
rename to libc/arch-x86/syscalls/__connect.S
index c0d73ca..2f53b33 100644
--- a/libc/arch-x86/syscalls/connect.S
+++ b/libc/arch-x86/syscalls/__connect.S
@@ -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 @@
     popl    %ecx
     popl    %ebx
     ret
-END(connect)
+END(__connect)
diff --git a/libc/arch-x86_64/syscalls/connect.S b/libc/arch-x86_64/syscalls/__connect.S
similarity index 84%
rename from libc/arch-x86_64/syscalls/connect.S
rename to libc/arch-x86_64/syscalls/__connect.S
index 23cdbae..288484e 100644
--- a/libc/arch-x86_64/syscalls/connect.S
+++ b/libc/arch-x86_64/syscalls/__connect.S
@@ -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 @@
     orq     $-1, %rax
 1:
     ret
-END(connect)
+END(__connect)
+.hidden __connect
diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
new file mode 100644
index 0000000..6826ee8
--- /dev/null
+++ b/libc/bionic/NetdClient.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifdef LIBC_STATIC
+#error NetdClient.cpp should NOT be included in static libc builds.
+#endif
+
+#include <private/NetdClient.h>
+#include <private/libc_logging.h>
+#include <pthread.h>
+
+#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;
+
+extern "C" __LIBC_HIDDEN__ void netdClientInit() {
+    if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
+        __libc_format_log(ANDROID_LOG_ERROR, "netdClient",
+                          "Unable to initialize netd_client component.");
+    }
+}
diff --git a/libc/bionic/NetdClientDispatch.cpp b/libc/bionic/NetdClientDispatch.cpp
new file mode 100644
index 0000000..31728d2
--- /dev/null
+++ b/libc/bionic/NetdClientDispatch.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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>
+
+#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
+};
diff --git a/libc/bionic/connect.cpp b/libc/bionic/connect.cpp
new file mode 100644
index 0000000..c5db46b
--- /dev/null
+++ b/libc/bionic/connect.cpp
@@ -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);
+}
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 61fb887..3d98861 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -58,6 +58,7 @@
   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 @@
   // 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() {
diff --git a/libc/private/NetdClient.h b/libc/private/NetdClient.h
new file mode 100644
index 0000000..48c05cb
--- /dev/null
+++ b/libc/private/NetdClient.h
@@ -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