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
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sockets.h"
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stddef.h>
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu_debug.h"
21ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner#include "qemu-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"
26ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner#include "android/utils/misc.h"
2718fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner#include "android/utils/system.h"
283e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
293e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner#define  D(...) VERBOSE_PRINT(socket,__VA_ARGS__)
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define xxWIN32_LEAN_AND_MEAN
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <windows.h>
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <winsock2.h>
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <ws2tcpip.h>
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <sys/ioctl.h>
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <sys/socket.h>
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <netinet/in.h>
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  include <netinet/tcp.h>
414e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#  include <netdb.h>
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if HAVE_UNIX_SOCKETS
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    include <sys/un.h>
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    ifndef UNIX_PATH_MAX
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#      define  UNIX_PATH_MAX  (sizeof(((struct sockaddr_un*)0)->sun_path)-1)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#    endif
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* QSOCKET_CALL is used to deal with the fact that EINTR happens pretty
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * easily in QEMU since we use SIGALRM to implement periodic timers
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  QSOCKET_CALL(_ret,_cmd)   \
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do { _ret = (_cmd); } while ( _ret < 0 && WSAGetLastError() == WSAEINTR )
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  QSOCKET_CALL(_ret,_cmd)   \
607410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner    do { \
617410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner        errno = 0; \
627410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner        do { _ret = (_cmd); } while ( _ret < 0 && errno == EINTR ); \
637410e8a38956bc52b7a8ba18c0c9618bd4af8000David 'Digit' Turner    } while (0);
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h>
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int  winsock_error;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  WINSOCK_ERRORS_LIST \
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_INVALID_HANDLE,EINVAL,"invalid handle") \
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_NOT_ENOUGH_MEMORY,ENOMEM,"not enough memory") \
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSA_INVALID_PARAMETER,EINVAL,"invalid parameter") \
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEINTR,EINTR,"interrupted function call") \
77ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEALREADY,EALREADY,"operation already in progress") \
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEBADF,EBADF,"bad file descriptor") \
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEACCES,EACCES,"permission denied") \
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEFAULT,EFAULT,"bad address") \
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEINVAL,EINVAL,"invalid argument") \
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEMFILE,EMFILE,"too many opened files") \
83ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEWOULDBLOCK,EWOULDBLOCK,"resource temporarily unavailable") \
84ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    EE(WSAEINPROGRESS,EINPROGRESS,"operation now in progress") \
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEALREADY,EAGAIN,"operation already in progress") \
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOTSOCK,EBADF,"socket operation not on socket") \
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEDESTADDRREQ,EDESTADDRREQ,"destination address required") \
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEMSGSIZE,EMSGSIZE,"message too long") \
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEPROTOTYPE,EPROTOTYPE,"wrong protocol type for socket") \
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOPROTOOPT,ENOPROTOOPT,"bad protocol option") \
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEADDRINUSE,EADDRINUSE,"address already in use") \
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEADDRNOTAVAIL,EADDRNOTAVAIL,"cannot assign requested address") \
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETDOWN,ENETDOWN,"network is down") \
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETUNREACH,ENETUNREACH,"network unreachable") \
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENETRESET,ENETRESET,"network dropped connection on reset") \
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNABORTED,ECONNABORTED,"software caused connection abort") \
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNRESET,ECONNRESET,"connection reset by peer") \
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOBUFS,ENOBUFS,"no buffer space available") \
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEISCONN,EISCONN,"socket is already connected") \
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENOTCONN,ENOTCONN,"socket is not connected") \
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAESHUTDOWN,ESHUTDOWN,"cannot send after socket shutdown") \
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAETOOMANYREFS,ETOOMANYREFS,"too many references") \
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAETIMEDOUT,ETIMEDOUT,"connection timed out") \
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAECONNREFUSED,ECONNREFUSED,"connection refused") \
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAELOOP,ELOOP,"cannot translate name") \
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAENAMETOOLONG,ENAMETOOLONG,"name too long") \
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEHOSTDOWN,EHOSTDOWN,"host is down") \
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EE(WSAEHOSTUNREACH,EHOSTUNREACH,"no route to host") \
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          winsock;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          unix;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  string;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} WinsockError;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const WinsockError  _winsock_errors[] = {
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  EE(w,u,s)   { w, u, s },
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WINSOCK_ERRORS_LIST
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef   EE
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { -1, -1, NULL }
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function reads the latest winsock error code and updates
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * errno to a matching value. It also returns the new value of
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * errno.
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1287f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehfix_errno( void )
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const WinsockError*  werr = _winsock_errors;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                  unix = EINVAL;  /* generic error code */
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13326722dde31c3467cd31a078662810927eec05de5David 'Digit' Turner    winsock_error = WSAGetLastError();
1344e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; werr->string != NULL; werr++ ) {
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (werr->winsock == winsock_error) {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unix = werr->unix;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1403e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    }
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = unix;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1467f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehset_errno( int  code )
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    winsock_error = -1;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno         = code;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function returns a string describing the latest Winsock error */
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project_errno_str(void)
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const WinsockError*  werr   = _winsock_errors;
158ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    const char*          result = NULL;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; werr->string; werr++ ) {
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (werr->winsock == winsock_error) {
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            result = werr->string;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
167ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    if (result == NULL) {
168ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner        result = tempstr_format(
169ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner                    "Unkown socket error (Winsock=0x%08x) errno=%d: %s",
170ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner                    winsock_error, errno, strerror(errno));
171ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner    }
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1767f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehfix_errno( void )
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1827f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsiehset_errno( int  code )
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = code;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* socket types */
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_family_to_bsd( SocketFamily  family )
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (family) {
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET: return AF_INET;
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:  return AF_INET6;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX: return AF_LOCAL;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return -1;
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_to_bsd( SocketType  type )
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (type) {
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCKET_DGRAM:  return SOCK_DGRAM;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCKET_STREAM: return SOCK_STREAM;
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default: return 0;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic SocketType
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_from_bsd( int  type )
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (type) {
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCK_DGRAM:  return SOCKET_DGRAM;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case SOCK_STREAM: return SOCKET_STREAM;
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:          return (SocketType) SOCKET_UNSPEC;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_type_check( SocketType  type )
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (type == SOCKET_DGRAM || type == SOCKET_STREAM);
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
232b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnertypedef union {
233b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr     sa[1];
234b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_in  in[1];
235b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#if HAVE_IN6_SOCKETS
236b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_in6 in6[1];
237b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#endif
238b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#if HAVE_UNIX_SOCKETS
239b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    struct sockaddr_un  un[1];
240b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner#endif
241b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner} sockaddr_storage;
242b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* socket addresses */
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_inet( SockAddress*  a, uint32_t  ip, uint16_t  port )
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family         = SOCKET_INET;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.inet.port    = port;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.inet.address = ip;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_in6 ( SockAddress*  a, const uint8_t*  ip6[16], uint16_t  port )
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family = SOCKET_IN6;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u.in6.port = port;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( a->u.in6.address, ip6, sizeof(a->u.in6.address) );
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_unix( SockAddress*  a, const char*  path )
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->family       = SOCKET_UNIX;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u._unix.path  = strdup(path ? path : "");
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a->u._unix.owner = 1;
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid  sock_address_done( SockAddress*  a )
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_UNIX && a->u._unix.owner) {
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u._unix.owner = 0;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        free((char*)a->u._unix.path);
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_char( char*  buf, char*  end, int  c )
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2800b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    if (buf < end) {
2810b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        if (buf+1 == end) {
2820b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf++ = 0;
2830b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        } else {
2840b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf++ = (char) c;
2850b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner            *buf    = 0;
2860b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner        }
2870b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    }
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_str( char*  buf, char*  end, const char*  str )
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = strlen(str);
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  avail = end - buf;
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > avail)
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = avail;
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( buf, str, len );
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf += len;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (buf == end)
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[-1] = 0;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf[0] = 0;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_unsigned( char*  buf, char*  end, unsigned  val )
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  temp[16];
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( nn = 0; val != 0; nn++ ) {
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  rem = val % 10;
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = '0'+rem;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val /= 10;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn++] = '0';
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (nn > 0)
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char(buf, end, temp[--nn]);
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_hex( char*  buf, char*  end, unsigned  val, int  ndigits )
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   shift = 4*ndigits;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char   hex[16] = "0123456789abcdef";
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (shift >= 0) {
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char(buf, end, hex[(val >> shift) & 15]);
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift -= 4;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_ip4( char*  buf, char*  end, uint32_t  ip )
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)(ip >> 24) );
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)((ip >> 16) & 255));
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)((ip >> 8) & 255));
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_char( buf, end, '.');
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buf = format_unsigned( buf, end, (unsigned)(ip & 255));
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic char*
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectformat_ip6( char*  buf, char*  end, const uint8_t*  ip6 )
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < 8; nn++) {
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  val = (ip6[0] << 16) | ip6[1];
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ip6 += 2;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (nn > 0)
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buf = format_char(buf, end, ':');
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val == 0)
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf  = format_hex(buf, end, val, 4);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_to_string( const SockAddress*  a )
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char buf0[MAX_PATH];
3780b7cd6c0d6af071951a86810d2600d155fa53b05David 'Digit' Turner    char *buf = buf0, *end = buf + sizeof(buf0);
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_ip4( buf, end, a->u.inet.address );
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char( buf, end, ':' );
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_unsigned( buf, end, (unsigned) a->u.inet.port );
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_ip6( buf, end, a->u.in6.address );
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_char( buf, end, ':' );
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_unsigned( buf, end, (unsigned) a->u.in6.port );
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buf = format_str( buf, end, a->u._unix.path );
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buf0;
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_equal( const SockAddress*  a, const SockAddress*  b )
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family != b->family)
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (a->u.inet.address == b->u.inet.address &&
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                a->u.inet.port    == b->u.inet.port);
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (!memcmp(a->u.in6.address, b->u.in6.address, 16) &&
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                a->u.in6.port == b->u.in6.port);
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (!strcmp(a->u._unix.path, b->u._unix.path));
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_port( const SockAddress*  a )
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.inet.port;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.in6.port;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_set_port( SockAddress*  a, uint16_t  port )
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u.inet.port = port;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a->u.in6.port = port;
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ;
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectconst char*
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_path( const SockAddress*  a )
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_UNIX)
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u._unix.path;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_get_ip( const SockAddress*  a )
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (a->family == SOCKET_INET)
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return a->u.inet.address;
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar*
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectbufprint_sock_address( char*  p, char*  end, const SockAddress*  a )
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t  ip = a->u.inet.address;
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint( p, end, "%d.%d.%d.%d:%d",
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (ip >> 24) & 255, (ip >> 16) & 255,
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         (ip >> 8) & 255, ip & 255,
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         a->u.inet.port );
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int             nn     = 0;
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char*     column = "";
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const uint8_t*  tab    = a->u.in6.address;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (nn = 0; nn < 16; nn += 2) {
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p = bufprint(p, end, "%s%04x", column, (tab[n] << 8) | tab[n+1]);
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                column = ":";
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint(p, end, ":%d", a->u.in6.port);
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return bufprint(p, end, "%s", a->u._unix.path);
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return p;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnerstatic int
5094e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turnersock_address_to_bsd( const SockAddress*  a, sockaddr_storage*  paddress, socklen_t  *psize )
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET:
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
514b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_in*  dst = paddress->in;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = sizeof(*dst);
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memset( paddress, 0, *psize );
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_family      = AF_INET;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_port        = htons(a->u.inet.port);
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin_addr.s_addr = htonl(a->u.inet.address);
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_IN6_SOCKETS
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
529b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_in6*  dst = paddress->in6;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = sizeof(*dst);
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memset( paddress, 0, *psize );
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin6_family = AF_INET6;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sin6_port   = htons(a->u.in6.port);
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy( dst->sin6_addr.s6_addr, a->u.in6.address, 16 );
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_IN6_SOCKETS */
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_UNIX:
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int                  slen = strlen(a->u._unix.path);
546b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            struct sockaddr_un*  dst = paddress->un;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (slen >= UNIX_PATH_MAX)
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
551b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner            memset( dst, 0, sizeof(*dst) );
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sun_family = AF_LOCAL;
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy( dst->sun_path, a->u._unix.path, slen );
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dst->sun_path[slen] = 0;
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *psize = (char*)&dst->sun_path[slen+1] - (char*)dst;
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_UNIX_SOCKETS */
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
5637f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
569b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turnerstatic int
5704e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turnersock_address_from_bsd( SockAddress*  a, const void*  from, size_t  fromlen )
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5724e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner    switch (((struct sockaddr *)from)->sa_family) {
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_INET:
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5754e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner           const struct sockaddr_in*  src = from;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
5787f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family         = SOCKET_INET;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.inet.port    = ntohs(src->sin_port);
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.inet.address = ntohl(src->sin_addr.s_addr);
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_IN6_SOCKETS
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_INET6:
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
5894e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner            const struct sockaddr_in6*  src = from;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
5927f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family     = SOCKET_IN6;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u.in6.port = ntohs(src->sin6_port);
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memcpy(a->u.in6.address, src->sin6_addr.s6_addr, 16);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_UNIX_SOCKETS
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case AF_LOCAL:
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
6044e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner            const struct sockaddr_un*  src = from;
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char*                end;
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (fromlen < sizeof(*src))
6087f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check that the path is zero-terminated */
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            end = memchr(src->sun_path, 0, UNIX_PATH_MAX);
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (end == NULL)
6137f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh                return set_errno(EINVAL);
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->family = SOCKET_UNIX;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u._unix.owner = 1;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            a->u._unix.path  = strdup(src->sun_path);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
6237f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsock_address_init_resolve( SockAddress*  a, const char*  hostname, uint16_t  port, int  preferIn6 )
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct addrinfo   hints[1];
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct addrinfo*  res;
6344e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner    int                ret;
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(hints, 0, sizeof(hints));
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hints->ai_family   = preferIn6 ? AF_INET6 : AF_UNSPEC;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
639669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner    ret = getaddrinfo(hostname, NULL, hints, &res);
640669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner    if (ret != 0) {
641669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        int  err;
642669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
643669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        switch (ret) {
644669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_AGAIN:  /* server is down */
645669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_FAIL:   /* server is sick */
646669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = EHOSTDOWN;
647669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
648669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
6497f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh/* NOTE that in x86_64-w64-mingw32 both EAI_NODATA and EAI_NONAME are the same */
6507f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
651669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_NODATA:
652f5be61d70b1f548e180ba11ab87c54c03704e819Nick Pelly#endif
653669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_NONAME:
654669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = ENOENT;
655669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
656669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
657669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        case EAI_MEMORY:
658669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = ENOMEM;
659669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            break;
660669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner
661669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        default:
662669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner            err = EINVAL;
663669c47953c86f489d2a7ce8893bc9a5e1f0620e5David Turner        }
6647f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(err);
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6673e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    /* Parse the returned list of addresses. */
6683e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    {
6693e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  res_ipv4 = NULL;
6703e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  res_ipv6 = NULL;
6713e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        struct addrinfo*  r;
6723e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
6733e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner       /* If preferIn6 is false, we stop on the first IPv4 address,
6743e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        * otherwise, we stop on the first IPv6 one
6753e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        */
6763e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        for (r = res; r != NULL; r = r->ai_next) {
6773e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r->ai_family == AF_INET && res_ipv4 == NULL) {
6783e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                res_ipv4 = r;
6793e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                if (!preferIn6)
6803e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                    break;
6813e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            }
6823e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            else if (r->ai_family == AF_INET6 && res_ipv6 == NULL) {
6833e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                res_ipv6 = r;
6843e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                if (preferIn6)
6853e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                    break;
6863e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            }
6873e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
6883e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
6893e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        /* Select the best address in 'r', which will be NULL
6903e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner         * if there is no corresponding address.
6913e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner         */
6923e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (preferIn6) {
6933e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            r = res_ipv6;
6943e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r == NULL)
6953e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                r = res_ipv4;
6963e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        } else {
6973e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            r = res_ipv4;
6983e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            if (r == NULL)
6993e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner                r = res_ipv6;
7003e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
7013e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
7023e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (r == NULL) {
7037f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            ret = set_errno(ENOENT);
7043e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            goto Exit;
7053e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        }
7063e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner
7073e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        /* Convert to a SockAddress */
7083e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        ret = sock_address_from_bsd( a, r->ai_addr, r->ai_addrlen );
7093e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        if (ret < 0)
7103e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            goto Exit;
7113e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    }
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* need to set the port */
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (a->family) {
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_INET: a->u.inet.port = port; break;
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case SOCKET_IN6:  a->u.in6.port  = port; break;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: ;
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7203e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' TurnerExit:
7213e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner    freeaddrinfo(res);
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* The Winsock headers for mingw lack some definitions */
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef AI_ADDRCONFIG
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#  define  AI_ADDRCONFIG  0
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerSockAddress**
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_list_create( const char*  hostname,
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          const char*  port,
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                          unsigned     flags )
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress**    list = NULL;
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress*     addr;
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int              nn, count, ret;
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct addrinfo  ai, *res, *e;
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(&ai, 0, sizeof(ai));
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ai.ai_flags   |= AI_ADDRCONFIG;
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ai.ai_family   = PF_UNSPEC;
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (flags & SOCKET_LIST_FORCE_INET)
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_family = PF_INET;
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else if (flags & SOCKET_LIST_FORCE_IN6)
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_family = PF_INET6;
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (flags & SOCKET_LIST_PASSIVE)
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_flags |= AI_PASSIVE;
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ai.ai_flags |= AI_CANONNAME;
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
754c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner    if (flags & SOCKET_LIST_DGRAM)
755c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner        ai.ai_socktype = SOCK_DGRAM;
756c611a19e65c13248bfd881a2d30681d7e24ea773David 'Digit' Turner
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (1) {
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        struct addrinfo  hints = ai;
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = getaddrinfo(hostname, port, &hints, &res);
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret == 0)
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        switch (ret) {
7654e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#ifdef EAI_ADDRFAMILY
7664e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner        case EAI_ADDRFAMILY:
7674e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_NODATA:
7697f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(ENOENT);
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_FAMILY:
7727f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EAFNOSUPPORT);
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_AGAIN:
7757f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EAGAIN);
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7774e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#ifdef EAI_SYSTEM
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case EAI_SYSTEM:
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (errno == EINTR)
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                continue;
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
7824e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        default:
7847f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh            set_errno(EINVAL);
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* allocate result list */
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (count = 0, e = res; e != NULL; e = e->ai_next)
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        count += 1;
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
79318fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AARRAY_NEW(list, count+1);
79418fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AARRAY_NEW(addr, count);
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (nn = 0, e = res; e != NULL; e = e->ai_next) {
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0)
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            continue;
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list[nn++] = addr++;
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    list[nn] = NULL;
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    freeaddrinfo(res);
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return list;
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
80950eef01259415a59067de542a21f30f6f4b829d0Vladimir ChtchetkineSockAddress**
81050eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkinesock_address_list_create2(const char* host_and_port, unsigned flags )
81150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine{
81250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    char host_name[512];
81350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    const char* actual_host_name = "localhost";
81450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    // Parse host and port name.
81550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    const char* port_name = strchr(host_and_port, ':');
81650eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    if (port_name != NULL) {
81750eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        int to_copy = MIN(sizeof(host_name)-1, port_name - host_and_port);
81850eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        if (to_copy != 0) {
81950eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            memcpy(host_name, host_and_port, to_copy);
82050eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            host_name[to_copy] = '\0';
82150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            actual_host_name = host_name;
82250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            port_name++;
82350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        } else {
82450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine            return NULL;
82550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        }
82650eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    } else {
82750eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        port_name = host_and_port;
82850eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    }
82950eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    // Make sure that port_name is not empty.
83050eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    if (port_name[0] == '\0') {
83150eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine        return NULL;
83250eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    }
83350eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine    return sock_address_list_create(actual_host_name, port_name, flags);
83450eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine}
83550eef01259415a59067de542a21f30f6f4b829d0Vladimir Chtchetkine
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_list_free( SockAddress**  list )
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int  nn;
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress*  addr;
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (list == NULL)
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = list[0];
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (nn = 0; list[nn] != NULL; nn++) {
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        sock_address_done(list[nn]);
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        list[nn] = NULL;
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
85018fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AFREE(addr);
85118fe86e8245878f3b7a2813bd59b8cfcf636e15cDavid 'Digit' Turner    AFREE(list);
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersock_address_get_numeric_info( SockAddress*  a,
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               char*         host,
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               size_t        hostlen,
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               char*         serv,
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               size_t        servlen )
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr*  saddr;
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socklen_t         slen;
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int               ret;
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (a->family) {
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case SOCKET_INET:
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        saddr = (struct sockaddr*) &a->u.inet.address;
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        slen  = sizeof(a->u.inet.address);
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if HAVE_IN6_SOCKET
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case SOCKET_IN6:
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        saddr = (struct sockaddr*) &a->u.in6.address;
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        slen  = sizeof(a->u.in6.address);
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
8787f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                       NI_NUMERICHOST | NI_NUMERICSERV );
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (ret) {
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0:
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case EAI_AGAIN:
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = EAGAIN;
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = EINVAL;
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return ret;
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create( SocketFamily  family, SocketType  type )
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret;
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   sfamily = socket_family_to_bsd(family);
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   stype   = socket_type_to_bsd(type);
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sfamily < 0 || stype < 0) {
9047f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return set_errno(EINVAL);
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, socket(sfamily, stype, 0));
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
9097f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_inet( SocketType  type )
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_INET, type );
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_IN6_SOCKETS
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_in6 ( SocketType  type )
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_IN6, type );
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_create_unix( SocketType  type )
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_create( SOCKET_UNIX, type );
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  socket_can_read(int  fd)
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long  opt;
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctlsocket(fd, FIONREAD, &opt) < 0)
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return opt;
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  opt;
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ioctl(fd, FIONREAD, &opt) < 0)
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return opt;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define   SOCKET_CALL(cmd)  \
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  ret; \
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, (cmd)); \
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) \
9607f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno(); \
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret; \
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_send(int  fd, const void*  buf, int  buflen)
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(send(fd, buf, buflen, 0))
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_send_oob( int  fd, const void*  buf, int  buflen )
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(send(fd, buf, buflen, MSG_OOB));
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_sendto(int  fd, const void*  buf, int  buflen, const SockAddress*  to)
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
978b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  sa;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         salen;
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(to, &sa, &salen) < 0)
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
984b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(sendto(fd, buf, buflen, 0, sa.sa, salen));
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_recv(int  fd, void*  buf, int  len)
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(recv(fd, buf, len, 0));
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_recvfrom(int  fd, void*  buf, int  len, SockAddress*  from)
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
996b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  sa;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         salen = sizeof(sa);
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1000b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret,recvfrom(fd,buf,len,0,sa.sa,&salen));
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10027f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_from_bsd(from, &sa, salen) < 0)
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_connect( int  fd, const SockAddress*  address )
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1013b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1019b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(connect(fd,addr.sa,addrlen));
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_bind( int  fd, const SockAddress*  address )
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1025b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
1026b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    socklen_t         addrlen;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_to_bsd(address, &addr, &addrlen) < 0)
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1031b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    SOCKET_CALL(bind(fd, addr.sa, addrlen));
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_get_address( int  fd, SockAddress*  address )
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1037b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen = sizeof(addr);
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1041b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, getsockname(fd, addr.sa, &addrlen));
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10437f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return sock_address_from_bsd(address, &addr, addrlen);
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocket_get_peer_address( int  fd, SockAddress*  address )
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1051b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socklen_t         addrlen = sizeof(addr);
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int               ret;
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1055b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, getpeername(fd, addr.sa, &addrlen));
10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (ret < 0)
10577f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return sock_address_from_bsd(address, &addr, addrlen);
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_listen( int  fd, int  backlog )
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SOCKET_CALL(listen(fd, backlog));
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_accept( int  fd, SockAddress*  address )
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1071b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    sockaddr_storage  addr;
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t         addrlen = sizeof(addr);
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               ret;
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1075b6f4df8626f2ba311566466c01cc8c18ccf40392David 'Digit' Turner    QSOCKET_CALL(ret, accept(fd, addr.sa, &addrlen));
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
10777f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (address) {
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sock_address_from_bsd(address, &addr, addrlen) < 0) {
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            socket_close(ret);
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocket_getoption(int  fd, int  domain, int  option, int  defaut)
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int  ret;
10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    while (1) {
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        DWORD opt = (DWORD)-1;
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int  opt  = -1;
10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
10984e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner        socklen_t  optlen = sizeof(opt);
10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = getsockopt(fd, domain, option, (char*)&opt, &optlen);
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret == 0)
11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return (int)opt;
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (errno != EINTR)
11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return defaut;
11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11054e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#undef OPT_CAST
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerSocketType socket_get_type(int fd)
11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int   so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_type_from_bsd(so_type);
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_nonblock(int fd)
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long opt = 1;
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ioctlsocket(fd, FIONBIO, &opt);
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   flags = fcntl(fd, F_GETFL);
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_blocking(int fd)
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long opt = 0;
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ioctlsocket(fd, FIONBIO, &opt);
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   flags = fcntl(fd, F_GETFL);
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_setoption(int  fd, int  domain, int  option, int  _flag)
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD  flag = (DWORD) _flag;
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    flag = _flag;
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_xreuseaddr(int  fd)
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* on Windows, SO_REUSEADDR is used to indicate that several programs can
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * bind to the same port. this is completely different from the Unix
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * semantics. instead of SO_EXCLUSIVEADDR to ensure that explicitely prevent
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * this.
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1);
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_REUSEADDR, 1);
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_set_oobinline(int  fd)
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, SOL_SOCKET, SO_OOBINLINE, 1);
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  socket_set_nodelay(int  fd)
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint socket_set_ipv6only(int  fd)
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* IPV6_ONLY is only supported since Vista on Windows,
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * and the Mingw headers lack its definition anyway.
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(_WIN32) && !defined(IPV6_V6ONLY)
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	return 0;
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
11834e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner#endif
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint socket_get_error(int fd)
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void socket_cleanup(void)
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WSACleanup();
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_init(void)
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WSADATA Data;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, err;
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = WSAStartup(MAKEWORD(2,2), &Data);
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret != 0) {
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        err = WSAGetLastError();
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    atexit(socket_cleanup);
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint socket_init(void)
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return 0;   /* nothing to do on Unix */
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close_handler( void*  _fd )
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   fd = (int)_fd;
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret;
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  buff[64];
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we want to drain the read side of the socket before closing it */
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = recv( fd, buff, sizeof(buff), 0 );
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (ret < 0 && WSAGetLastError() == WSAEINTR);
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, NULL, NULL, NULL );
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    closesocket( fd );
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close( int  fd )
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  old_errno = errno;
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shutdown( fd, SD_BOTH );
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we want to drain the socket before closing it */
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = old_errno;
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !_WIN32 */
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_close( int  fd )
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  old_errno = errno;
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shutdown( fd, SHUT_RDWR );
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close( fd );
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    errno = old_errno;
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !_WIN32 */
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_bind_server( int  s, const SockAddress*  to, SocketType  type )
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr(s);
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (socket_bind(s, to) < 0) {
12803e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D("could not bind server socket address %s: %s",
12813e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner          sock_address_to_string(to), errno_str);
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto FAIL;
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (type == SOCKET_STREAM) {
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (socket_listen(s, 4) < 0) {
12873e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner            D("could not listen server socket %s: %s",
12883e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner              sock_address_to_string(to), errno_str);
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto FAIL;
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return  s;
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectFAIL:
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_close(s);
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_connect_client( int  s, const SockAddress*  to )
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (socket_connect(s, to) < 0) {
13043e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D( "could not connect client socket to %s: %s\n",
13053e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner           sock_address_to_string(to), errno_str );
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close(s);
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock( s );
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s;
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_in_server( int  address, int  port, SocketType  type )
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  addr;
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          s;
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &addr, address, port );
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_inet( type );
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_bind_server( s, &addr, type );
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_in_client( SockAddress*  to, SocketType  type )
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  s;
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_inet( type );
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0) return -1;
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_connect_client( s, to );
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_loopback_server( int  port, SocketType  type )
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_server( SOCK_ADDRESS_INET_LOOPBACK, port, type );
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_loopback_client( int  port, SocketType  type )
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  addr;
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &addr, SOCK_ADDRESS_INET_LOOPBACK, port );
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_client( &addr, type );
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_network_client( const char*  host, 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    if (sock_address_init_resolve( &addr, host, port, 0) < 0)
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_client( &addr, type );
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_anyaddr_server( int  port, SocketType  type )
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_in_server( SOCK_ADDRESS_INET_ANY, port, type );
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_accept_any( int  server_fd )
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  fd;
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(fd, accept( server_fd, NULL, 0 ));
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
13833e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner        D( "could not accept client connection from fd %d: %s",
13843e7a92854dbf66902da5522ca3dfb2011c0ce8beDavid 'Digit' Turner           server_fd, errno_str );
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* set to non-blocking */
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock( fd );
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return fd;
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if HAVE_UNIX_SOCKETS
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_unix_server( const char*  name, SocketType  type )
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress   addr;
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           s, ret;
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_unix( type );
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_unix( &addr, name );
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = unlink( name );
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (ret < 0 && errno == EINTR);
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind_server( s, &addr, type );
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_done( &addr );
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_unix_client( const char*  name, SocketType  type )
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress   addr;
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           s, ret;
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = socket_create_unix(type);
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s < 0)
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_unix( &addr, name );
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret =  socket_connect_client( s, &addr );
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_done( &addr );
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* HAVE_UNIX_SOCKETS */
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_pair(int *fd1, int *fd2)
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef _WIN32
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   fds[2];
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!ret) {
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock(fds[0]);
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock(fds[1]);
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fd1 = fds[0];
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *fd2 = fds[1];
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return ret;
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* _WIN32 */
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* on Windows, select() only works with network sockets, which
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * means we absolutely cannot use Win32 PIPEs to implement
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * socket pairs with the current event loop implementation.
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * We're going to do like Cygwin: create a random pair
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * of localhost TCP sockets and connect them together
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     */
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                 s0, s1, s2, port;
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct sockaddr_in  sockin;
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socklen_t           len;
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* first, create the 'server' socket.
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * a port number of 0 means 'any port between 1024 and 5000.
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * see Winsock bind() documentation for details */
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s0 = socket_loopback_server( 0, SOCK_STREAM );
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s0 < 0)
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* now connect a client socket to it, we first need to
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * extract the server socket's port number */
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = sizeof sockin;
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (getsockname(s0, (struct sockaddr*) &sockin, &len) < 0) {
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s0);
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    port = ntohs(sockin.sin_port);
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s2   = socket_loopback_client( port, SOCK_STREAM );
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s2 < 0) {
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket(s0);
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we need to accept the connection on the server socket
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     * this will create the second socket for the pair
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     */
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = sizeof sockin;
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s1  = accept(s0, (struct sockaddr*) &sockin, &len);
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s1 == INVALID_SOCKET) {
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s0);
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        closesocket (s2);
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(s1);
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* close server socket */
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    closesocket(s0);
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *fd1 = s1;
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *fd2 = s2;
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* _WIN32 */
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_add_membership( int  s, uint32_t  ip )
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ip_mreq imr;
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_multiaddr.s_addr = htonl(ip);
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_interface.s_addr = htonl(INADDR_ANY);
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
15184e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                     (const char *)&imr,
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     sizeof(struct ip_mreq)) < 0 )
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
15217f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_drop_membership( int  s, uint32_t  ip )
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ip_mreq imr;
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_multiaddr.s_addr = htonl(ip);
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    imr.imr_interface.s_addr = htonl(INADDR_ANY);
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
15354e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner                     (const char *)&imr,
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     sizeof(struct ip_mreq)) < 0 )
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
15387f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh        return fix_errno();
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_set_loop( int  s, int  enabled )
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_LOOP, !!enabled );
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsocket_mcast_inet_set_ttl( int  s, int  ttl )
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return socket_setoption( s, IPPROTO_IP, IP_MULTICAST_TTL, ttl );
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectchar*
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthost_name( void )
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char buf[256];  /* 255 is the max host name length supported by DNS */
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         ret;
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    QSOCKET_CALL(ret, gethostname(buf, sizeof(buf)));
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0)
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return "localhost";
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return buf;
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1569