Bug 812700 - Fix SCTP code to build on Android, r=dmose,ted
authorGian-Carlo Pascutto <gpascutto@mozilla.com>
Mon, 10 Dec 2012 15:53:22 -0800
changeset 121150 226ffef01c8471a8bea80df488257fe73a284f4f
parent 121149 8d00a8bf150863be5f89576f6cb3dc5a27349902
child 121151 4528be937f5c42db7173132d00055525de17ef87
push idunknown
push userunknown
push dateunknown
reviewersdmose, ted
bugs812700
milestone20.0a1
Bug 812700 - Fix SCTP code to build on Android, r=dmose,ted
netwerk/sctp/datachannel/DataChannel.cpp
netwerk/sctp/datachannel/Makefile.in
netwerk/sctp/src/LocalArray.h
netwerk/sctp/src/Makefile.in
netwerk/sctp/src/ScopedFd.h
netwerk/sctp/src/ifaddrs-android-ext.h
netwerk/sctp/src/ifaddrs_android.cpp
netwerk/sctp/src/netinet/sctp_bsd_addr.c
netwerk/sctp/src/netinet/sctp_os_userspace.h
netwerk/sctp/src/netinet/sctp_pcb.c
netwerk/sctp/src/user_environment.c
netwerk/sctp/src/user_inpcb.h
netwerk/sctp/src/user_recv_thread.c
netwerk/sctp/src/user_socketvar.h
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -370,17 +370,17 @@ DataChannelConnection::ConnectDTLS(Trans
 void
 DataChannelConnection::DTLSConnectThread(void *data)
 {
   DataChannelConnection *_this = static_cast<DataChannelConnection*>(data);
   struct sockaddr_conn addr;
 
   memset(&addr, 0, sizeof(addr));
   addr.sconn_family = AF_CONN;
-#if !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
+#if defined(__Userspace_os_Darwin)
   addr.sconn_len = sizeof(addr);
 #endif
   addr.sconn_port = htons(_this->mLocalPort);
 
   int r = usrsctp_bind(_this->mMasterSocket, reinterpret_cast<struct sockaddr *>(&addr),
                        sizeof(addr));
   if (r < 0) {
     LOG(("usrsctp_bind failed: %d", r));
--- a/netwerk/sctp/datachannel/Makefile.in
+++ b/netwerk/sctp/datachannel/Makefile.in
@@ -40,30 +40,17 @@ DEFINES = \
   -DINET=1 \
   -DINET6=1 \
   -DSCTP_DEBUG=1 \
   $(NULL)
 
 ifeq ($(OS_TARGET),WINNT)
 DEFINES += -D__Userspace_os_Windows=1
 else
-ifeq ($(OS_TARGET),Darwin)
-DEFINES += -D__Userspace_os_Darwin=1
-else
-ifeq ($(OS_TARGET),Linux)
-DEFINES += -D__Userspace_os_Linux=1
-else
-ifeq ($(OS_TARGET),FreeBSD)
-DEFINES += -D__Userspace_os_FreeBSD=1
-else
-#default_fallback; probably doesn't work
 DEFINES += -D__Userspace_os_$(OS_TARGET)=1
 endif
-endif
-endif
-endif
 
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DIMPL_NS_NET
new file mode 100644
--- /dev/null
+++ b/netwerk/sctp/src/LocalArray.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 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 LOCAL_ARRAY_H_included
+#define LOCAL_ARRAY_H_included
+
+#include <cstddef>
+#include <new>
+
+/**
+ * A fixed-size array with a size hint. That number of bytes will be allocated
+ * on the stack, and used if possible, but if more bytes are requested at
+ * construction time, a buffer will be allocated on the heap (and deallocated
+ * by the destructor).
+ *
+ * The API is intended to be a compatible subset of C++0x's std::array.
+ */
+template <size_t STACK_BYTE_COUNT>
+class LocalArray {
+public:
+    /**
+     * Allocates a new fixed-size array of the given size. If this size is
+     * less than or equal to the template parameter STACK_BYTE_COUNT, an
+     * internal on-stack buffer will be used. Otherwise a heap buffer will
+     * be allocated.
+     */
+    LocalArray(size_t desiredByteCount) : mSize(desiredByteCount) {
+        if (desiredByteCount > STACK_BYTE_COUNT) {
+            mPtr = new char[mSize];
+        } else {
+            mPtr = &mOnStackBuffer[0];
+        }
+    }
+
+    /**
+     * Frees the heap-allocated buffer, if there was one.
+     */
+    ~LocalArray() {
+        if (mPtr != &mOnStackBuffer[0]) {
+            delete[] mPtr;
+        }
+    }
+
+    // Capacity.
+    size_t size() { return mSize; }
+    bool empty() { return mSize == 0; }
+
+    // Element access.
+    char& operator[](size_t n) { return mPtr[n]; }
+    const char& operator[](size_t n) const { return mPtr[n]; }
+
+private:
+    char mOnStackBuffer[STACK_BYTE_COUNT];
+    char* mPtr;
+    size_t mSize;
+
+    // Disallow copy and assignment.
+    LocalArray(const LocalArray&);
+    void operator=(const LocalArray&);
+};
+
+#endif // LOCAL_ARRAY_H_included
--- a/netwerk/sctp/src/Makefile.in
+++ b/netwerk/sctp/src/Makefile.in
@@ -21,16 +21,22 @@ XPIDL_MODULE   = necko_sctp
 GRE_MODULE     = 1
 FORCE_STATIC_LIB = 1
 
 EXPORTS_NAMESPACES = mozilla/net
 
 XPIDLSRCS = \
   $(NULL)
 
+ifeq ($(OS_TARGET),Android)
+CPPSRCS = \
+  ifaddrs_android.cpp \
+  $(NULL)
+endif
+
 CSRCS = \
   user_environment.c \
   user_mbuf.c \
   user_recv_thread.c \
   user_sctp_timer_iterate.c \
   user_socket.c \
   sctp_asconf.c \
   sctp_auth.c \
@@ -60,23 +66,31 @@ EXPORTS_mozilla/net = \
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../../base/src \
   -I$(topsrcdir)/content/base/src \
   -I$(topsrcdir)/content/events/src \
   -I$(topsrcdir)/xpcom/ds \
   $(NULL)
 
+# Android NDK r5c, used on the builders at the time of this writing, doesn't
+# have the headers we need for IPv6
+ifeq ($(OS_TARGET),Android)
+  IPV6_DEFINE=
+else
+  IPV6_DEFINE=-DINET6=1
+endif
+
 DEFINES = \
   -DSCTP_SIMPLE_ALLOCATOR=1 \
   -DUSE_SCTP_SHA1=1 \
   -DSCTP_PROCESS_LEVEL_LOCKS=1 \
   -D__Userspace__=1 \
   -DINET=1 \
-  -DINET6=1 \
+  $(IPV6_DEFINE) \
   -DCALLBACK_API=1 \
   -DSCTP_DEBUG=1 \
   $(NULL)
 
 ifeq ($(OS_TARGET),WINNT)
 DEFINES += \
   -D__Userspace_os_Windows=1 \
   -D_LIB=1 \
@@ -84,17 +98,17 @@ DEFINES += \
 else
 ifeq ($(OS_TARGET),Darwin)
 DEFINES += \
   -D__Userspace_os_Darwin=1 \
   -D__APPLE_USE_RFC_2292=1 \
   -U__APPLE__ \
   $(NULL)
 else
-ifeq ($(OS_TARGET),Linux)
+ifeq (,$(filter-out Linux Android,$(OS_TARGET)))
 DEFINES += -D__Userspace_os_Linux=1
 else
 ifeq ($(OS_TARGET),FreeBSD)
 DEFINES += \
   -D__Userspace_os_FreeBSD=1 \
   -U__FreeBSD__ \
   $(NULL)
 else
new file mode 100644
--- /dev/null
+++ b/netwerk/sctp/src/ScopedFd.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 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 SCOPED_FD_H_included
+#define SCOPED_FD_H_included
+
+#include <unistd.h>
+
+// A smart pointer that closes the given fd on going out of scope.
+// Use this when the fd is incidental to the purpose of your function,
+// but needs to be cleaned up on exit.
+class ScopedFd {
+public:
+    explicit ScopedFd(int fd) : fd(fd) {
+    }
+
+    ~ScopedFd() {
+        close(fd);
+    }
+
+    int get() const {
+        return fd;
+    }
+
+private:
+    int fd;
+
+    // Disallow copy and assignment.
+    ScopedFd(const ScopedFd&);
+    void operator=(const ScopedFd&);
+};
+
+#endif  // SCOPED_FD_H_included
new file mode 100644
--- /dev/null
+++ b/netwerk/sctp/src/ifaddrs-android-ext.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 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 IFADDRS_ANDROID_EXT_H_included
+#define IFADDRS_ANDROID_EXT_H_included
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+// Android (bionic) doesn't have getifaddrs(3)/freeifaddrs(3).
+// We fake it here, so java_net_NetworkInterface.cpp can use that API
+// with all the non-portable code being in this file.
+
+// Source-compatible subset of the BSD struct.
+typedef struct ifaddrs {
+    // Pointer to next struct in list, or NULL at end.
+    struct ifaddrs* ifa_next;
+
+    // Interface name.
+    char* ifa_name;
+
+    // Interface flags.
+    unsigned int ifa_flags;
+
+    // Interface network address.
+    struct sockaddr* ifa_addr;
+
+    // Interface netmask.
+    struct sockaddr* ifa_netmask;
+} ifaddrs;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    int getifaddrs(ifaddrs** result);
+    void freeifaddrs(ifaddrs* addresses);
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // IFADDRS_ANDROID_H_included
new file mode 100644
--- /dev/null
+++ b/netwerk/sctp/src/ifaddrs_android.cpp
@@ -0,0 +1,186 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/*
+ * Copyright (C) 2009 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 "ifaddrs-android-ext.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "ScopedFd.h"
+#include "LocalArray.h"
+
+// Returns a pointer to the first byte in the address data (which is
+// stored in network byte order).
+uint8_t* sockaddrBytes(int family, sockaddr_storage* ss) {
+    if (family == AF_INET) {
+        sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
+        return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
+    } else if (family == AF_INET6) {
+        sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
+        return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
+    }
+    return NULL;
+}
+
+// Sadly, we can't keep the interface index for portability with BSD.
+// We'll have to keep the name instead, and re-query the index when
+// we need it later.
+bool ifa_setNameAndFlagsByIndex(ifaddrs *self, int interfaceIndex) {
+    // Get the name.
+    char buf[IFNAMSIZ];
+    char* name = if_indextoname(interfaceIndex, buf);
+    if (name == NULL) {
+        return false;
+    }
+    self->ifa_name = new char[strlen(name) + 1];
+    strcpy(self->ifa_name, name);
+
+    // Get the flags.
+    ScopedFd fd(socket(AF_INET, SOCK_DGRAM, 0));
+    if (fd.get() == -1) {
+        return false;
+    }
+    ifreq ifr;
+    memset(&ifr, 0, sizeof(ifr));
+    strcpy(ifr.ifr_name, name);
+    int rc = ioctl(fd.get(), SIOCGIFFLAGS, &ifr);
+    if (rc == -1) {
+        return false;
+    }
+    self->ifa_flags = ifr.ifr_flags;
+    return true;
+}
+
+// Netlink gives us the address family in the header, and the
+// sockaddr_in or sockaddr_in6 bytes as the payload. We need to
+// stitch the two bits together into the sockaddr that's part of
+// our portable interface.
+void ifa_setAddress(ifaddrs *self, int family, void* data, size_t byteCount) {
+    // Set the address proper...
+    sockaddr_storage* ss = new sockaddr_storage;
+    memset(ss, 0, sizeof(*ss));
+    self->ifa_addr = reinterpret_cast<sockaddr*>(ss);
+    ss->ss_family = family;
+    uint8_t* dst = sockaddrBytes(family, ss);
+    memcpy(dst, data, byteCount);
+}
+
+// Netlink gives us the prefix length as a bit count. We need to turn
+// that into a BSD-compatible netmask represented by a sockaddr*.
+void ifa_setNetmask(ifaddrs *self, int family, size_t prefixLength) {
+    // ...and work out the netmask from the prefix length.
+    sockaddr_storage* ss = new sockaddr_storage;
+    memset(ss, 0, sizeof(*ss));
+    self->ifa_netmask = reinterpret_cast<sockaddr*>(ss);
+    ss->ss_family = family;
+    uint8_t* dst = sockaddrBytes(family, ss);
+    memset(dst, 0xff, prefixLength / 8);
+    if ((prefixLength % 8) != 0) {
+        dst[prefixLength/8] = (0xff << (8 - (prefixLength % 8)));
+    }
+}
+
+// FIXME: use iovec instead.
+struct addrReq_struct {
+    nlmsghdr netlinkHeader;
+    ifaddrmsg msg;
+};
+
+inline bool sendNetlinkMessage(int fd, const void* data, size_t byteCount) {
+    ssize_t sentByteCount = TEMP_FAILURE_RETRY(send(fd, data, byteCount, 0));
+    return (sentByteCount == static_cast<ssize_t>(byteCount));
+}
+
+inline ssize_t recvNetlinkMessage(int fd, char* buf, size_t byteCount) {
+    return TEMP_FAILURE_RETRY(recv(fd, buf, byteCount, 0));
+}
+
+// Source-compatible with the BSD function.
+int getifaddrs(ifaddrs** result)
+{
+    // Simplify cleanup for callers.
+    *result = NULL;
+
+    // Create a netlink socket.
+    ScopedFd fd(socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE));
+    if (fd.get() < 0) {
+        return -1;
+    }
+
+    // Ask for the address information.
+    addrReq_struct addrRequest;
+    memset(&addrRequest, 0, sizeof(addrRequest));
+    addrRequest.netlinkHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
+    addrRequest.netlinkHeader.nlmsg_type = RTM_GETADDR;
+    addrRequest.netlinkHeader.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(addrRequest)));
+    addrRequest.msg.ifa_family = AF_UNSPEC; // All families.
+    addrRequest.msg.ifa_index = 0; // All interfaces.
+    if (!sendNetlinkMessage(fd.get(), &addrRequest, addrRequest.netlinkHeader.nlmsg_len)) {
+        return -1;
+    }
+
+    // Read the responses.
+    LocalArray<0> buf(65536); // We don't necessarily have std::vector.
+    ssize_t bytesRead;
+    while ((bytesRead  = recvNetlinkMessage(fd.get(), &buf[0], buf.size())) > 0) {
+        nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(&buf[0]);
+        for (; NLMSG_OK(hdr, (size_t)bytesRead); hdr = NLMSG_NEXT(hdr, bytesRead)) {
+            switch (hdr->nlmsg_type) {
+            case NLMSG_DONE:
+                return 0;
+            case NLMSG_ERROR:
+                return -1;
+            case RTM_NEWADDR:
+                {
+                    ifaddrmsg* address = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
+                    rtattr* rta = IFA_RTA(address);
+                    size_t ifaPayloadLength = IFA_PAYLOAD(hdr);
+                    while (RTA_OK(rta, ifaPayloadLength)) {
+                        if (rta->rta_type == IFA_LOCAL) {
+                            int family = address->ifa_family;
+                            if (family == AF_INET || family == AF_INET6) {
+                                ifaddrs *next = *result;
+                                *result = new ifaddrs;
+                                (*result)->ifa_next = next;
+                                if (!ifa_setNameAndFlagsByIndex(*result, address->ifa_index)) {
+                                    return -1;
+                                }
+                                ifa_setAddress(*result, family, RTA_DATA(rta), RTA_PAYLOAD(rta));
+                                ifa_setNetmask(*result, family, address->ifa_prefixlen);
+                            }
+                        }
+                        rta = RTA_NEXT(rta, ifaPayloadLength);
+                    }
+                }
+                break;
+            }
+        }
+    }
+    // We only get here if recv fails before we see a NLMSG_DONE.
+    return -1;
+}
+
+// Source-compatible with the BSD function.
+void freeifaddrs(ifaddrs* addresses) {
+    ifaddrs* next = addresses;
+    while (next != NULL) {
+        delete[] next->ifa_name;
+        delete next->ifa_addr;
+        delete next->ifa_netmask;
+        next = addresses->ifa_next;
+    }
+}
--- a/netwerk/sctp/src/netinet/sctp_bsd_addr.c
+++ b/netwerk/sctp/src/netinet/sctp_bsd_addr.c
@@ -44,18 +44,23 @@
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_uio.h>
 #include <netinet/sctputil.h>
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_asconf.h>
 #include <netinet/sctp_sysctl.h>
 #include <netinet/sctp_indata.h>
 #if !defined(__Userspace_os_Windows)
+#if defined(ANDROID)
+#include <unistd.h>
+#include <ifaddrs-android-ext.h>
+#else
 #include <sys/unistd.h>
 #endif
+#endif
 
 /* Declare all of our malloc named types */
 #ifndef __Panda__
 MALLOC_DEFINE(SCTP_M_MAP, "sctp_map", "sctp asoc map descriptor");
 MALLOC_DEFINE(SCTP_M_STRMI, "sctp_stri", "sctp stream in array");
 MALLOC_DEFINE(SCTP_M_STRMO, "sctp_stro", "sctp stream out array");
 MALLOC_DEFINE(SCTP_M_ASC_ADDR, "sctp_aadr", "sctp asconf address");
 MALLOC_DEFINE(SCTP_M_ASC_IT, "sctp_a_it", "sctp asconf iterator");
--- a/netwerk/sctp/src/netinet/sctp_os_userspace.h
+++ b/netwerk/sctp/src/netinet/sctp_os_userspace.h
@@ -376,17 +376,17 @@ struct udphdr {
 	unsigned __int16 uh_dport;
 	unsigned __int16 uh_ulen;
 	unsigned __int16 uh_sum;
 };
 
 #else /* !defined(Userspace_os_Windows) */
 #include <sys/cdefs.h> /* needed? added from old __FreeBSD__ */
 #include <sys/socket.h>
-#if defined(__Userspace_os_FreeBSD)
+#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Linux) || defined(__Userspace_os_Android)
 #include <pthread.h>
 #endif
 typedef pthread_mutex_t userland_mutex_t;
 typedef pthread_cond_t userland_cond_t;
 typedef pthread_t userland_thread_t;
 #endif
 
 #define mtx_lock(arg1)
@@ -456,17 +456,19 @@ struct sx {int dummy;};
 #include <user_ip_icmp.h>
 #endif
 /* #include <netinet/in_pcb.h> ported to userspace */
 #include <user_inpcb.h>
 
 /* for getifaddrs */
 #include <sys/types.h>
 #if !defined(__Userspace_os_Windows)
+#if !defined(ANDROID)
 #include <ifaddrs.h>
+#endif
 
 /* for ioctl */
 #include <sys/ioctl.h>
 
 /* for close, etc. */
 #include <unistd.h>
 #endif
 
--- a/netwerk/sctp/src/netinet/sctp_pcb.c
+++ b/netwerk/sctp/src/netinet/sctp_pcb.c
@@ -64,18 +64,23 @@
 #endif
 #if defined(__FreeBSD__)
 #include <sys/sched.h>
 #include <sys/smp.h>
 #include <sys/unistd.h>
 #endif
 #if defined(__Userspace__)
 #if !defined(__Userspace_os_Windows)
+#if defined(ANDROID)
+#include <unistd.h>
+#include <ifaddrs-android-ext.h>
+#else
 #include <sys/unistd.h>
 #endif
+#endif
 #include <user_socketvar.h>
 #endif
 
 #if defined(__APPLE__)
 #define APPLE_FILE_NO 4
 #endif
 
 #if defined(__FreeBSD__) && __FreeBSD_version >= 801000
--- a/netwerk/sctp/src/user_environment.c
+++ b/netwerk/sctp/src/user_environment.c
@@ -29,18 +29,20 @@
  */
 
 /* __Userspace__ */
 
 #include <stdlib.h>
 #if !defined (__Userspace_os_Windows)
 #include <stdint.h>
 #if !defined(__Userspace_os_FreeBSD)
+#if !defined(ANDROID)
 #include <sys/sysctl.h>
 #endif
+#endif
 #include <netinet/sctp_os_userspace.h>
 #endif
 #include <user_environment.h>
 #include <sys/types.h>
 /* #include <sys/param.h> defines MIN */
 #if !defined(MIN)
 #define MIN(arg1,arg2) ((arg1) < (arg2) ? (arg1) : (arg2))
 #endif
--- a/netwerk/sctp/src/user_inpcb.h
+++ b/netwerk/sctp/src/user_inpcb.h
@@ -30,16 +30,23 @@
  * $FreeBSD: src/sys/netinet/in_pcb.h,v 1.100.2.1 2007/12/07 05:46:08 kmacy Exp $
  */
 
 #ifndef _USER_INPCB_H_
 #define _USER_INPCB_H_
 
 #include <user_route.h> /* was <net/route.h> */
 
+#if defined(ANDROID)
+#include <arpa/inet.h>
+#include <netinet/in.h>
+/* missing defines in Android bionic libc/NDK */
+typedef uint16_t                in_port_t;
+#endif
+
 #define	in6pcb		inpcb	/* for KAME src sync over BSD*'s */
 #define	in6p_sp		inp_sp	/* for KAME src sync over BSD*'s */
 struct inpcbpolicy;
 
 /*
  * Struct inpcb is the ommon structure pcb for the Internet Protocol
  * implementation.
  *
--- a/netwerk/sctp/src/user_recv_thread.c
+++ b/netwerk/sctp/src/user_recv_thread.c
@@ -440,16 +440,17 @@ recv_function_raw(void *arg)
 	}
 	/* free the array itself */
 	free(recvmbuf);
 #if defined (__Userspace_os_Windows)
 	ExitThread(0);
 #else
 	pthread_exit(NULL);
 #endif
+	return NULL;
 }
 #endif
 
 #if defined(INET6)
 static void *
 recv_function_raw6(void *arg)
 {
 	struct mbuf **recvmbuf6;
@@ -623,16 +624,17 @@ recv_function_raw6(void *arg)
 	}
 	/* free the array itself */
 	free(recvmbuf6);
 #if defined (__Userspace_os_Windows)
 	ExitThread(0);
 #else
 	pthread_exit(NULL);
 #endif
+	return NULL;
 }
 #endif
 
 #ifdef INET
 static void *
 recv_function_udp(void *arg)
 {
 	struct mbuf **udprecvmbuf;
@@ -827,16 +829,17 @@ recv_function_udp(void *arg)
 	}
 	/* free the array itself */
 	free(udprecvmbuf);
 #if defined (__Userspace_os_Windows)
 	ExitThread(0);
 #else
 	pthread_exit(NULL);
 #endif
+	return NULL;
 }
 #endif
 
 #if defined(INET6)
 static void *
 recv_function_udp6(void *arg)
 {
 	struct mbuf **udprecvmbuf6;
@@ -1013,16 +1016,17 @@ recv_function_udp6(void *arg)
 	}
 	/* free the array itself */
 	free(udprecvmbuf6);
 #if defined (__Userspace_os_Windows)
 	ExitThread(0);
 #else
 	pthread_exit(NULL);
 #endif
+	return NULL;
 }
 #endif
 
 static void
 setReceiveBufferSize(int sfd, int new_size)
 {
 	int ch = new_size;
 
--- a/netwerk/sctp/src/user_socketvar.h
+++ b/netwerk/sctp/src/user_socketvar.h
@@ -32,16 +32,21 @@
 
 #ifndef _USER_SOCKETVAR_H_
 #define _USER_SOCKETVAR_H_
 
 #if defined(__Userspace_os_Darwin)
 #include <sys/types.h>
 #include <unistd.h>
 #endif
+#if defined(ANDROID)
+/* Android bionic libc is missing some defines in sys/types.h. Pick them
+ * up elsewhere */
+#include <linux/coda.h>
+#endif
 
 /* #include <sys/selinfo.h> */ /*__Userspace__ alternative?*/	/* for struct selinfo */
 /* #include <sys/_lock.h>  was 0 byte file */
 /* #include <sys/_mutex.h> was 0 byte file */
 /* #include <sys/_sx.h> */ /*__Userspace__ alternative?*/
 #if !defined(__Userspace_os_Windows) && !defined(__Userspace_os_FreeBSD)
 #include <sys/uio.h>
 #endif