18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
124e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#ifdef __linux__ /* Recent versions of glibc only define EAI_NODATA, which is an
134e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                    extension to the POSIX standard, if _GNU_SOURCE is defined. */
144e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#  define _GNU_SOURCE 1
154e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
164e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner
17cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h"
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stddef.h>
20e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "android/qemu-debug.h"
21e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/path.h"
253e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner#include "android/utils/debug.h"
26af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner#include "android/utils/eintr_wrapper.h"
27ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner#include "android/utils/misc.h"
2818fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner#include "android/utils/system.h"
293e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
303e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner#define  D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define xxWIN32_LEAN_AND_MEAN
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <windows.h>
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <winsock2.h>
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <ws2tcpip.h>
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <sys/ioctl.h>
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <sys/socket.h>
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <netinet/in.h>
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <netinet/tcp.h>
424e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#  include <netdb.h>
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if HAVE_UNIX_SOCKETS
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    include <sys/un.h>
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    ifndef UNIX_PATH_MAX
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#      define  UNIX_PATH_MAX  (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    endif
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * easily in QEMU since we use SIGALRM to implement periodic timers
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  QSOCKET_CALL(_ret,_cmd)   \
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  QSOCKET_CALL(_ret,_cmd)   \
617410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner    do { \
627410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner        errno = 0; \
63af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        _ret = HANDLE_EINTR(_cmd); \
647410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner    } while (0);
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h>
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int  winsock_error;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  WINSOCK_ERRORS_LIST \
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEINTR,EINTR,"interrupted function call") \
78ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEALREADY,EALREADY,"operation already in progress") \
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEBADF,EBADF,"bad file descriptor") \
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEACCES,EACCES,"permission denied") \
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEFAULT,EFAULT,"bad address") \
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEINVAL,EINVAL,"invalid argument") \
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEMFILE,EMFILE,"too many opened files") \
84ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
85ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEALREADY,EAGAIN,"operation already in progress") \
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETDOWN,ENETDOWN,"network is down") \
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEISCONN,EISCONN,"socket is already connected") \
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAELOOP,ELOOP,"cannot translate name") \
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          winsock;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          unix;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  string;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} WinsockError;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const WinsockError  _winsock_errors[] = {
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  EE(w,u,s)   { w, u, s },
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WINSOCK_ERRORS_LIST
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef   EE
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { -1, -1, NULL }
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function reads the latest winsock error code and updates
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * errno to a matching value. It also returns the new value of
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * errno.
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1297f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehfix_errno( void )
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const WinsockError*  werr = _winsock_errors;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                  unix = EINVAL;  /* generic error code */
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13426722dde31c3467cd31a078662810927eec05de5David 'Digit' Turner    winsock_error = WSAGetLastError();
1354e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; werr->string != NULL; werr++ ) {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (werr->winsock == winsock_error) {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unix = werr->unix;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1413e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    }
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = unix;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1477f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehset_errno( int  code )
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    winsock_error = -1;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno         = code;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function returns a string describing the latest Winsock error */
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_errno_str(void)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const WinsockError*  werr   = _winsock_errors;
159ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    const char*          result = NULL;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; werr->string; werr++ ) {
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (werr->winsock == winsock_error) {
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result = werr->string;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
168ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    if (result == NULL) {
169ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner        result = tempstr_format(
170ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner                    "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
171ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner                    winsock_error, errno, strerror(errno));
172ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    }
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1777f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehfix_errno( void )
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1837f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehset_errno( int  code )
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = code;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* socket types */
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_family_to_bsd( SocketFamily  family )
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (family) {
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET: return AF_INET;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:  return AF_INET6;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX: return AF_LOCAL;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return -1;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_to_bsd( SocketType  type )
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (type) {
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCKET_DGRAM:  return SOCK_DGRAM;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCKET_STREAM: return SOCK_STREAM;
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default: return 0;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SocketType
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_from_bsd( int  type )
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (type) {
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCK_DGRAM:  return SOCKET_DGRAM;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCK_STREAM: return SOCKET_STREAM;
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:          return (SocketType) SOCKET_UNSPEC;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_check( SocketType  type )
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
233b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnertypedef union {
234b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr     sa[1];
235b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_in  in[1];
236b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#if HAVE_IN6_SOCKETS
237b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_in6 in6[1];
238b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#endif
239b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#if HAVE_UNIX_SOCKETS
240b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_un  un[1];
241b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#endif
242b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner} sockaddr_storage;
243b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* socket addresses */
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_inet( SockAddress*  a, uint32_t  ip, uint16_t  port )
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family         = SOCKET_INET;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.inet.port    = port;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.inet.address = ip;
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_in6 ( SockAddress*  a, const uint8_t*  ip6[16], uint16_t  port )
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family = SOCKET_IN6;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.in6.port = port;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_unix( SockAddress*  a, const char*  path )
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family       = SOCKET_UNIX;
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u._unix.path  = strdup(path ? path : "");
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u._unix.owner = 1;
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid  sock_address_done( SockAddress*  a )
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_UNIX && a->u._unix.owner) {
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u._unix.owner = 0;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free((char*)a->u._unix.path);
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_char( char*  buf, char*  end, int  c )
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2810b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    if (buf < end) {
2820b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        if (buf+1 == end) {
2830b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf++ = 0;
2840b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        } else {
2850b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf++ = (char) c;
2860b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf    = 0;
2870b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        }
2880b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    }
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_str( char*  buf, char*  end, const char*  str )
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = strlen(str);
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  avail = end - buf;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > avail)
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = avail;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( buf, str, len );
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf += len;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (buf == end)
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[-1] = 0;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[0] = 0;
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_unsigned( char*  buf, char*  end, unsigned  val )
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  temp[16];
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; val != 0; nn++ ) {
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  rem = val % 10;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = '0'+rem;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val /= 10;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn++] = '0';
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (nn > 0)
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char(buf, end, temp[--nn]);
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_hex( char*  buf, char*  end, unsigned  val, int  ndigits )
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   shift = 4*ndigits;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char   hex[16] = "0123456789abcdef";
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (shift >= 0) {
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char(buf, end, hex[(val >> shift) & 15]);
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift -= 4;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_ip4( char*  buf, char*  end, uint32_t  ip )
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)(ip & 255));
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_ip6( char*  buf, char*  end, const uint8_t*  ip6 )
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < 8; nn++) {
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  val = (ip6[0] << 16) | ip6[1];
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ip6 += 2;
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn > 0)
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buf = format_char(buf, end, ':');
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val == 0)
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf  = format_hex(buf, end, val, 4);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_to_string( const SockAddress*  a )
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char buf0[MAX_PATH];
3790b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    char *buf = buf0, *end = buf + sizeof(buf0);
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_ip4( buf, end, a->u.inet.address );
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char( buf, end, ':' );
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_ip6( buf, end, a->u.in6.address );
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char( buf, end, ':' );
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_str( buf, end, a->u._unix.path );
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf0;
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_equal( const SockAddress*  a, const SockAddress*  b )
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family != b->family)
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (a->u.inet.address == b->u.inet.address &&
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                a->u.inet.port    == b->u.inet.port);
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                a->u.in6.port == b->u.in6.port);
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (!strcmp(a->u._unix.path, b->u._unix.path));
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_port( const SockAddress*  a )
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.inet.port;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.in6.port;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_set_port( SockAddress*  a, uint16_t  port )
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u.inet.port = port;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u.in6.port = port;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ;
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_path( const SockAddress*  a )
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_UNIX)
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u._unix.path;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_ip( const SockAddress*  a )
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_INET)
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.inet.address;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar*
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbufprint_sock_address( char*  p, char*  end, const SockAddress*  a )
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t  ip = a->u.inet.address;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint( p, end, "%d.%d.%d.%d:%d",
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (ip >> 24) & 255, (ip >> 16) & 255,
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (ip >> 8) & 255, ip & 255,
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         a->u.inet.port );
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int             nn     = 0;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char*     column = "";
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const uint8_t*  tab    = a->u.in6.address;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (nn = 0; nn < 16; nn += 2) {
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                column = ":";
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint(p, end, ":%d", a->u.in6.port);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint(p, end, "%s", a->u._unix.path);
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return p;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
509b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnerstatic int
5104e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turnersock_address_to_bsd( const SockAddress*  a, sockaddr_storage*  paddress, socklen_t  *psize )
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
515b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_in*  dst = paddress->in;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = sizeof(*dst);
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memset( paddress, 0, *psize );
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_family      = AF_INET;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_port        = htons(a->u.inet.port);
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_addr.s_addr = htonl(a->u.inet.address);
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_IN6_SOCKETS
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
530b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_in6*  dst = paddress->in6;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = sizeof(*dst);
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memset( paddress, 0, *psize );
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin6_family = AF_INET6;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin6_port   = htons(a->u.in6.port);
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_IN6_SOCKETS */
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int                  slen = strlen(a->u._unix.path);
547b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_un*  dst = paddress->un;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (slen >= UNIX_PATH_MAX)
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
552b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            memset( dst, 0, sizeof(*dst) );
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sun_family = AF_LOCAL;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy( dst->sun_path, a->u._unix.path, slen );
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sun_path[slen] = 0;
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_UNIX_SOCKETS */
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
5647f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
570b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnerstatic int
5714e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turnersock_address_from_bsd( SockAddress*  a, const void*  from, size_t  fromlen )
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5734e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner    switch (((struct sockaddr *)from)->sa_family) {
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_INET:
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5764e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner           const struct sockaddr_in*  src = from;
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
5797f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family         = SOCKET_INET;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.inet.port    = ntohs(src->sin_port);
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.inet.address = ntohl(src->sin_addr.s_addr);
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_IN6_SOCKETS
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_INET6:
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5904e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner            const struct sockaddr_in6*  src = from;
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
5937f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family     = SOCKET_IN6;
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.in6.port = ntohs(src->sin6_port);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_UNIX_SOCKETS
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_LOCAL:
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
6054e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner            const struct sockaddr_un*  src = from;
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char*                end;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
6097f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check that the path is zero-terminated */
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (end == NULL)
6147f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family = SOCKET_UNIX;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u._unix.owner = 1;
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u._unix.path  = strdup(src->sun_path);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
6247f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_resolve( SockAddress*  a, const char*  hostname, uint16_t  port, int  preferIn6 )
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct addrinfo   hints[1];
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct addrinfo*  res;
6354e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner    int                ret;
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(hints, 0, sizeof(hints));
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hints->ai_family   = preferIn6 ? AF_INET6 : AF_UNSPEC;
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
640669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner    ret = getaddrinfo(hostname, NULL, hints, &res);
641669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner    if (ret != 0) {
642669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        int  err;
643669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
644669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        switch (ret) {
645669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_AGAIN:  /* server is down */
646669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_FAIL:   /* server is sick */
647669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = EHOSTDOWN;
648669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
649669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
6507f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh/* NOTE that in x86_64-w64-mingw32 both EAI_NODATA and EAI_NONAME are the same */
6517f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
652669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_NODATA:
653f5be61d70b1f548e180ba11ab87c54c03704e819Nick Pelly#endif
654669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_NONAME:
655669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = ENOENT;
656669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
657669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
658669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_MEMORY:
659669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = ENOMEM;
660669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
661669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
662669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        default:
663669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = EINVAL;
664669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        }
6657f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(err);
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6683e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    /* Parse the returned list of addresses. */
6693e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    {
6703e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  res_ipv4 = NULL;
6713e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  res_ipv6 = NULL;
6723e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  r;
6733e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
6743e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner       /* If preferIn6 is false, we stop on the first IPv4 address,
6753e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        * otherwise, we stop on the first IPv6 one
6763e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        */
6773e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        for (r = res; r != NULL; r = r->ai_next) {
6783e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r->ai_family == AF_INET && res_ipv4 == NULL) {
6793e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                res_ipv4 = r;
6803e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                if (!preferIn6)
6813e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                    break;
6823e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            }
6833e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            else if (r->ai_family == AF_INET6 && res_ipv6 == NULL) {
6843e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                res_ipv6 = r;
6853e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                if (preferIn6)
6863e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                    break;
6873e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            }
6883e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
6893e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
6903e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        /* Select the best address in 'r', which will be NULL
6913e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner         * if there is no corresponding address.
6923e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner         */
6933e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (preferIn6) {
6943e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            r = res_ipv6;
6953e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r == NULL)
6963e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                r = res_ipv4;
6973e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        } else {
6983e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            r = res_ipv4;
6993e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r == NULL)
7003e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                r = res_ipv6;
7013e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
7023e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
7033e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (r == NULL) {
7047f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            ret = set_errno(ENOENT);
7053e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            goto Exit;
7063e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
7073e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
7083e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        /* Convert to a SockAddress */
7093e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        ret = sock_address_from_bsd( a, r->ai_addr, r->ai_addrlen );
7103e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (ret < 0)
7113e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            goto Exit;
7123e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    }
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* need to set the port */
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET: a->u.inet.port = port; break;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:  a->u.in6.port  = port; break;
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: ;
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7213e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' TurnerExit:
7223e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    freeaddrinfo(res);
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* The Winsock headers for mingw lack some definitions */
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef AI_ADDRCONFIG
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#  define  AI_ADDRCONFIG  0
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerSockAddress**
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_list_create( const char*  hostname,
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          const char*  port,
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          unsigned     flags )
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress**    list = NULL;
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress*     addr;
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int              nn, count, ret;
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct addrinfo  ai, *res, *e;
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(&ai, 0, sizeof(ai));
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ai.ai_flags   |= AI_ADDRCONFIG;
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ai.ai_family   = PF_UNSPEC;
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (flags & SOCKET_LIST_FORCE_INET)
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_family = PF_INET;
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (flags & SOCKET_LIST_FORCE_IN6)
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_family = PF_INET6;
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (flags & SOCKET_LIST_PASSIVE)
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_flags |= AI_PASSIVE;
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_flags |= AI_CANONNAME;
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
755c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner    if (flags & SOCKET_LIST_DGRAM)
756c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner        ai.ai_socktype = SOCK_DGRAM;
757c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (1) {
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        struct addrinfo  hints = ai;
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = getaddrinfo(hostname, port, &hints, &res);
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret == 0)
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (ret) {
7664e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#ifdef EAI_ADDRFAMILY
7674e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner        case EAI_ADDRFAMILY:
7684e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_NODATA:
7707f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(ENOENT);
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_FAMILY:
7737f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EAFNOSUPPORT);
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_AGAIN:
7767f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EAGAIN);
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7784e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#ifdef EAI_SYSTEM
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_SYSTEM:
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (errno == EINTR)
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7834e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:
7857f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EINVAL);
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* allocate result list */
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (count = 0, e = res; e != NULL; e = e->ai_next)
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        count += 1;
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
79418fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AARRAY_NEW(list, count+1);
79518fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AARRAY_NEW(addr, count);
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (nn = 0, e = res; e != NULL; e = e->ai_next) {
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0)
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list[nn++] = addr++;
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    list[nn] = NULL;
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    freeaddrinfo(res);
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return list;
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
81050eef01259415a59067de542a21f30f6f4b829d0Vladimir ChtchetkineSockAddress**
81150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkinesock_address_list_create2(const char* host_and_port, unsigned flags )
81250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine{
81350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    char host_name[512];
81450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    const char* actual_host_name = "localhost";
81550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    // Parse host and port name.
81650eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    const char* port_name = strchr(host_and_port, ':');
81750eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    if (port_name != NULL) {
81850eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        int to_copy = MIN(sizeof(host_name)-1, port_name - host_and_port);
81950eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        if (to_copy != 0) {
82050eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            memcpy(host_name, host_and_port, to_copy);
82150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            host_name[to_copy] = '\0';
82250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            actual_host_name = host_name;
82350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            port_name++;
82450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        } else {
82550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            return NULL;
82650eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        }
82750eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    } else {
82850eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        port_name = host_and_port;
82950eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    }
83050eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    // Make sure that port_name is not empty.
83150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    if (port_name[0] == '\0') {
83250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        return NULL;
83350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    }
83450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    return sock_address_list_create(actual_host_name, port_name, flags);
83550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine}
83650eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_list_free( SockAddress**  list )
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int  nn;
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress*  addr;
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (list == NULL)
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = list[0];
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (nn = 0; list[nn] != NULL; nn++) {
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sock_address_done(list[nn]);
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list[nn] = NULL;
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
85118fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AFREE(addr);
85218fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AFREE(list);
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_get_numeric_info( SockAddress*  a,
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               char*         host,
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               size_t        hostlen,
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               char*         serv,
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               size_t        servlen )
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr*  saddr;
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socklen_t         slen;
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int               ret;
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (a->family) {
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case SOCKET_INET:
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        saddr = (struct sockaddr*) &a->u.inet.address;
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        slen  = sizeof(a->u.inet.address);
8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if HAVE_IN6_SOCKET
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case SOCKET_IN6:
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        saddr = (struct sockaddr*) &a->u.in6.address;
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        slen  = sizeof(a->u.in6.address);
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
8797f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       NI_NUMERICHOST | NI_NUMERICSERV );
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (ret) {
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0:
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case EAI_AGAIN:
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = EAGAIN;
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = EINVAL;
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create( SocketFamily  family, SocketType  type )
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret;
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   sfamily = socket_family_to_bsd(family);
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   stype   = socket_type_to_bsd(type);
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sfamily < 0 || stype < 0) {
9057f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, socket(sfamily, stype, 0));
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
9107f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_inet( SocketType  type )
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_INET, type );
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_IN6_SOCKETS
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_in6 ( SocketType  type )
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_IN6, type );
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_unix( SocketType  type )
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_UNIX, type );
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  socket_can_read(int  fd)
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long  opt;
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctlsocket(fd, FIONREAD, &opt) < 0)
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return opt;
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  opt;
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl(fd, FIONREAD, &opt) < 0)
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return opt;
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define   SOCKET_CALL(cmd)  \
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  ret; \
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, (cmd)); \
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) \
9617f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno(); \
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret; \
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_send(int  fd, const void*  buf, int  buflen)
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(send(fd, buf, buflen, 0))
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_send_oob( int  fd, const void*  buf, int  buflen )
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_sendto(int  fd, const void*  buf, int  buflen, const SockAddress*  to)
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
979b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  sa;
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         salen;
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(to, &sa, &salen) < 0)
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
985b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(sendto(fd, buf, buflen, 0, sa.sa, salen));
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_recv(int  fd, void*  buf, int  len)
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(recv(fd, buf, len, 0));
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_recvfrom(int  fd, void*  buf, int  len, SockAddress*  from)
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
997b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  sa;
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         salen = sizeof(sa);
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1001b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,sa.sa,&salen));
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10037f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_from_bsd(from, &sa, salen) < 0)
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_connect( int  fd, const SockAddress*  address )
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1014b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1020b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(connect(fd,addr.sa,addrlen));
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_bind( int  fd, const SockAddress*  address )
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1026b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
1027b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    socklen_t         addrlen;
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1032b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(bind(fd, addr.sa, addrlen));
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_get_address( int  fd, SockAddress*  address )
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1038b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen = sizeof(addr);
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1042b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, getsockname(fd, addr.sa, &addrlen));
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10447f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sock_address_from_bsd(address, &addr, addrlen);
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocket_get_peer_address( int  fd, SockAddress*  address )
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1052b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socklen_t         addrlen = sizeof(addr);
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int               ret;
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1056b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, getpeername(fd, addr.sa, &addrlen));
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
10587f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return sock_address_from_bsd(address, &addr, addrlen);
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_listen( int  fd, int  backlog )
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(listen(fd, backlog));
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_accept( int  fd, SockAddress*  address )
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1072b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen = sizeof(addr);
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1076b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, accept(fd, addr.sa, &addrlen));
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10787f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (address) {
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            socket_close(ret);
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int
10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocket_getoption(int  fd, int  domain, int  option, int  defaut)
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int  ret;
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (1) {
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        DWORD opt = (DWORD)-1;
10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int  opt  = -1;
10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
10994e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner        socklen_t  optlen = sizeof(opt);
1100af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        ret = HANDLE_EINTR(
1101af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner                getsockopt(fd, domain, option, (char*)&opt, &optlen));
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret == 0)
11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return (int)opt;
1104af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        else
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return defaut;
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11074e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#undef OPT_CAST
11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerSocketType socket_get_type(int fd)
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int   so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_type_from_bsd(so_type);
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_nonblock(int fd)
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long opt = 1;
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ioctlsocket(fd, FIONBIO, &opt);
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   flags = fcntl(fd, F_GETFL);
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_blocking(int fd)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long opt = 0;
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ioctlsocket(fd, FIONBIO, &opt);
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   flags = fcntl(fd, F_GETFL);
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_setoption(int  fd, int  domain, int  option, int  _flag)
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD  flag = (DWORD) _flag;
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    flag = _flag;
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_xreuseaddr(int  fd)
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* on Windows, SO_REUSEADDR is used to indicate that several programs can
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * bind to the same port. this is completely different from the Unix
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * this.
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_oobinline(int  fd)
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
117094cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turnerint socket_set_cork(int fd, int v)
117194cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner{
117294cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner#if defined(SOL_TCP) && defined(TCP_CORK)
117394cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    return socket_setoption(fd, SOL_TCP, TCP_CORK, v);
117494cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner#else
117594cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    return 0;
117694cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner#endif
117794cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner}
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  socket_set_nodelay(int  fd)
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint socket_set_ipv6only(int  fd)
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* IPV6_ONLY is only supported since Vista on Windows,
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and the Mingw headers lack its definition anyway.
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(_WIN32) && !defined(IPV6_V6ONLY)
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	return 0;
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
11934e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint socket_get_error(int fd)
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void socket_cleanup(void)
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WSACleanup();
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_init(void)
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WSADATA Data;
12137891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner    int ret;
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = WSAStartup(MAKEWORD(2,2), &Data);
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret != 0) {
12177891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner        (void) WSAGetLastError();
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    atexit(socket_cleanup);
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_init(void)
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return 0;   /* nothing to do on Unix */
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close_handler( void*  _fd )
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   fd = (int)_fd;
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret;
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  buff[64];
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we want to drain the read side of the socket before closing it */
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = recv( fd, buff, sizeof(buff), 0 );
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (ret < 0 && WSAGetLastError() == WSAEINTR);
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, NULL, NULL, NULL );
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    closesocket( fd );
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close( int  fd )
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  old_errno = errno;
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shutdown( fd, SD_BOTH );
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we want to drain the socket before closing it */
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = old_errno;
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close( int  fd )
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  old_errno = errno;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shutdown( fd, SHUT_RDWR );
1276af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner    IGNORE_EINTR(close( fd ));
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = old_errno;
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_bind_server( int  s, const SockAddress*  to, SocketType  type )
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr(s);
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (socket_bind(s, to) < 0) {
12903e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D("could not bind server socket address %s: %s",
12913e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner          sock_address_to_string(to), errno_str);
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto FAIL;
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == SOCKET_STREAM) {
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (socket_listen(s, 4) < 0) {
12973e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            D("could not listen server socket %s: %s",
12983e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner              sock_address_to_string(to), errno_str);
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto FAIL;
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  s;
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFAIL:
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_close(s);
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_connect_client( int  s, const SockAddress*  to )
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (socket_connect(s, to) < 0) {
13143e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D( "could not connect client socket to %s: %s\n",
13153e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner           sock_address_to_string(to), errno_str );
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close(s);
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock( s );
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s;
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_in_server( int  address, int  port, SocketType  type )
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  addr;
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          s;
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &addr, address, port );
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_inet( type );
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_bind_server( s, &addr, type );
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_in_client( SockAddress*  to, SocketType  type )
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  s;
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_inet( type );
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0) return -1;
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_connect_client( s, to );
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_loopback_server( int  port, SocketType  type )
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_loopback_client( int  port, SocketType  type )
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  addr;
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_client( &addr, type );
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_network_client( const char*  host, int  port, SocketType  type )
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  addr;
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_init_resolve( &addr, host, port, 0) < 0)
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_client( &addr, type );
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_anyaddr_server( int  port, SocketType  type )
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_accept_any( int  server_fd )
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  fd;
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
13933e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D( "could not accept client connection from fd %d: %s",
13943e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner           server_fd, errno_str );
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* set to non-blocking */
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock( fd );
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fd;
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_unix_server( const char*  name, SocketType  type )
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress   addr;
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           s, ret;
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_unix( type );
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_unix( &addr, name );
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1418af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner    HANDLE_EINTR(unlink(name));
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind_server( s, &addr, type );
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_done( &addr );
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_unix_client( const char*  name, SocketType  type )
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress   addr;
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           s, ret;
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_unix(type);
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_unix( &addr, name );
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret =  socket_connect_client( s, &addr );
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_done( &addr );
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_UNIX_SOCKETS */
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_pair(int *fd1, int *fd2)
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   fds[2];
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!ret) {
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock(fds[0]);
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock(fds[1]);
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fd1 = fds[0];
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fd2 = fds[1];
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* _WIN32 */
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* on Windows, select() only works with network sockets, which
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * means we absolutely cannot use Win32 PIPEs to implement
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * socket pairs with the current event loop implementation.
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * We're going to do like Cygwin: create a random pair
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * of localhost TCP sockets and connect them together
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     */
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                 s0, s1, s2, port;
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct sockaddr_in  sockin;
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t           len;
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first, create the 'server' socket.
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * a port number of 0 means 'any port between 1024 and 5000.
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * see Winsock bind() documentation for details */
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s0 = socket_loopback_server( 0, SOCK_STREAM );
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s0 < 0)
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now connect a client socket to it, we first need to
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * extract the server socket's port number */
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = sizeof sockin;
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s0);
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    port = ntohs(sockin.sin_port);
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s2   = socket_loopback_client( port, SOCK_STREAM );
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s2 < 0) {
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket(s0);
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we need to accept the connection on the server socket
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * this will create the second socket for the pair
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     */
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = sizeof sockin;
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s1  = accept(s0, (struct sockaddr*) &sockin, &len);
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s1 == INVALID_SOCKET) {
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s0);
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s2);
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(s1);
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* close server socket */
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    closesocket(s0);
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *fd1 = s1;
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *fd2 = s2;
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* _WIN32 */
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_add_membership( int  s, uint32_t  ip )
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ip_mreq imr;
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_multiaddr.s_addr = htonl(ip);
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_interface.s_addr = htonl(INADDR_ANY);
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
15264e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                     (const char *)&imr,
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     sizeof(struct ip_mreq)) < 0 )
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
15297f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_drop_membership( int  s, uint32_t  ip )
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ip_mreq imr;
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_multiaddr.s_addr = htonl(ip);
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_interface.s_addr = htonl(INADDR_ANY);
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
15434e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                     (const char *)&imr,
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     sizeof(struct ip_mreq)) < 0 )
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
15467f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_set_loop( int  s, int  enabled )
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_set_ttl( int  s, int  ttl )
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar*
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthost_name( void )
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char buf[256];  /* 255 is the max host name length supported by DNS */
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         ret;
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return "localhost";
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return buf;
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
157794cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner
157894cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner
157994cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner// Temporary work-arounds until we get rid of this source file.
158094cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner
158194cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turnerint qemu_getsockopt(int sock, int level, int optname, void* optval,
158294cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner                    size_t* optlen) {
158394cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    socklen_t len = (socklen_t) *optlen;
158494cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    int ret = getsockopt(sock, level, optname, (char*)optval, &len);
158594cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    *optlen = (size_t) len;
158694cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner    return ret;
158794cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner}
158894cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner
158994cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turnerint qemu_setsockopt(int sock, int level, int optname, const void* optval,
159094cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner                    size_t optlen) {
159194cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner  return setsockopt(sock, level, optname, (const char*)optval,
159294cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner                    (socklen_t)optlen);
159394cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner}
159494cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner
159594cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turnerint qemu_recv(int sock, void* buf, size_t len, int flags) {
159694cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner  return recv(sock, buf, len, flags);
159794cf4e227249b0575c2f1b945357cf500864bb6eDavid 'Digit' Turner}
1598