aboutsummaryrefslogtreecommitdiffstats
path: root/sockets.c
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
committerDavid 'Digit' Turner <digit@google.com>2009-09-14 14:32:27 -0700
commit5d8f37ad78fc66901af50c762029a501561f3b23 (patch)
tree206790f8f21000850a98c4f9590a79e779106278 /sockets.c
parentcd059b15f2c7df69f4a087bd66900eb172e41d1c (diff)
downloadexternal_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.zip
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.gz
external_qemu-5d8f37ad78fc66901af50c762029a501561f3b23.tar.bz2
Merge upstream QEMU 10.0.50 into the Android source tree.
This change integrates many changes from the upstream QEMU sources. Its main purpose is to enable correct ARMv6 and ARMv7 support to the Android emulator. Due to the nature of the upstream code base, this unfortunately also required changes to many other parts of the source. Note that to ensure easier integrations in the future, some source files and directories that have heavy Android-specific customization have been renamed with an -android suffix. The original files are still there for easier integration tracking, but *never* compiled. For example: net.c net-android.c qemu-char.c qemu-char-android.c slirp/ slirp-android/ etc... Tested on linux-x86, darwin-x86 and windows host machines.
Diffstat (limited to 'sockets.c')
-rw-r--r--sockets.c204
1 files changed, 196 insertions, 8 deletions
diff --git a/sockets.c b/sockets.c
index 338b176..e9be66f 100644
--- a/sockets.c
+++ b/sockets.c
@@ -196,7 +196,7 @@ socket_type_to_bsd( SocketType type )
switch (type) {
case SOCKET_DGRAM: return SOCK_DGRAM;
case SOCKET_STREAM: return SOCK_STREAM;
- default: return -1;
+ default: return 0;
}
}
@@ -206,7 +206,7 @@ socket_type_from_bsd( int type )
switch (type) {
case SOCK_DGRAM: return SOCKET_DGRAM;
case SOCK_STREAM: return SOCKET_STREAM;
- default: return (SocketType) -1;
+ default: return (SocketType) SOCKET_UNSPEC;
}
}
@@ -718,6 +718,146 @@ Exit:
return ret;
}
+/* The Winsock headers for mingw lack some definitions */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+
+SockAddress**
+sock_address_list_create( const char* hostname,
+ const char* port,
+ unsigned flags )
+{
+ SockAddress** list = NULL;
+ SockAddress* addr;
+ int nn, count, ret;
+ struct addrinfo ai, *res, *e;
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_flags |= AI_ADDRCONFIG;
+ ai.ai_family = PF_UNSPEC;
+
+ if (flags & SOCKET_LIST_FORCE_INET)
+ ai.ai_family = PF_INET;
+ else if (flags & SOCKET_LIST_FORCE_IN6)
+ ai.ai_family = PF_INET6;
+
+ if (flags & SOCKET_LIST_PASSIVE)
+ ai.ai_flags |= AI_PASSIVE;
+ else
+ ai.ai_flags |= AI_CANONNAME;
+
+ while (1) {
+ struct addrinfo hints = ai;
+
+ ret = getaddrinfo(hostname, port, &hints, &res);
+ if (ret == 0)
+ break;
+
+ switch (ret) {
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+#endif
+ case EAI_NODATA:
+ _set_errno(ENOENT);
+ break;
+ case EAI_FAMILY:
+ _set_errno(EAFNOSUPPORT);
+ break;
+ case EAI_AGAIN:
+ _set_errno(EAGAIN);
+ break;
+#ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ if (errno == EINTR)
+ continue;
+ break;
+#endif
+ default:
+ _set_errno(EINVAL);
+ }
+ return NULL;
+ }
+
+ /* allocate result list */
+ for (count = 0, e = res; e != NULL; e = e->ai_next)
+ count += 1;
+
+ list = (SockAddress**) qemu_malloc((count+1)*sizeof(SockAddress*));
+ addr = (SockAddress*) qemu_malloc(count*sizeof(SockAddress));
+
+ for (nn = 0, e = res; e != NULL; e = e->ai_next) {
+
+ ret = sock_address_from_bsd(addr, e->ai_addr, e->ai_addrlen);
+ if (ret < 0)
+ continue;
+
+ list[nn++] = addr++;
+ }
+ list[nn] = NULL;
+ freeaddrinfo(res);
+ return list;
+}
+
+void
+sock_address_list_free( SockAddress** list )
+{
+ int nn;
+ SockAddress* addr;
+
+ if (list == NULL)
+ return;
+
+ addr = list[0];
+ for (nn = 0; list[nn] != NULL; nn++) {
+ sock_address_done(list[nn]);
+ list[nn] = NULL;
+ }
+ qemu_free(addr);
+ qemu_free(list);
+}
+
+int
+sock_address_get_numeric_info( SockAddress* a,
+ char* host,
+ size_t hostlen,
+ char* serv,
+ size_t servlen )
+{
+ struct sockaddr* saddr;
+ socklen_t slen;
+ int ret;
+
+ switch (a->family) {
+ case SOCKET_INET:
+ saddr = (struct sockaddr*) &a->u.inet.address;
+ slen = sizeof(a->u.inet.address);
+ break;
+
+#if HAVE_IN6_SOCKET
+ case SOCKET_IN6:
+ saddr = (struct sockaddr*) &a->u.in6.address;
+ slen = sizeof(a->u.in6.address);
+ break;
+#endif
+ default:
+ return _set_errno(EINVAL);
+ }
+
+ ret = getnameinfo( saddr, slen, host, hostlen, serv, servlen,
+ NI_NUMERICHOST | NI_NUMERICSERV );
+
+ switch (ret) {
+ case 0:
+ break;
+ case EAI_AGAIN:
+ ret = EAGAIN;
+ break;
+ default:
+ ret = EINVAL;
+ }
+ return ret;
+}
int
socket_create( SocketFamily family, SocketType type )
@@ -872,6 +1012,20 @@ socket_get_address( int fd, SockAddress* address )
}
int
+socket_get_peer_address( int fd, SockAddress* address )
+{
+ struct sockaddr addr;
+ socklen_t addrlen = sizeof(addr);
+ int ret;
+
+ QSOCKET_CALL(ret, getpeername(fd, &addr, &addrlen));
+ if (ret < 0)
+ return _fix_errno();
+
+ return sock_address_from_bsd(address, &addr, addrlen);
+}
+
+int
socket_listen( int fd, int backlog )
{
SOCKET_CALL(listen(fd, backlog));
@@ -897,13 +1051,31 @@ socket_accept( int fd, SockAddress* address )
return ret;
}
-SocketType socket_get_type(int fd)
+static int
+socket_getoption(int fd, int domain, int option, int defaut)
{
- int opt = -1;
- int optlen = sizeof(opt);
- getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&opt, (void*)&optlen );
+ int ret;
+ while (1) {
+#ifdef _WIN32
+ DWORD opt = (DWORD)-1;
+#else
+ int opt = -1;
+#endif
+ size_t optlen = sizeof(opt);
+ ret = getsockopt(fd, domain, option, (char*)&opt, &optlen);
+ if (ret == 0)
+ return (int)opt;
+ if (errno != EINTR)
+ return defaut;
+ }
+#undef OPT_CAST
+}
+
- return socket_type_from_bsd(opt);
+SocketType socket_get_type(int fd)
+{
+ int so_type = socket_getoption(fd, SOL_SOCKET, SO_TYPE, -1);
+ return socket_type_from_bsd(so_type);
}
int socket_set_nonblock(int fd)
@@ -939,7 +1111,6 @@ socket_setoption(int fd, int domain, int option, int _flag)
return setsockopt( fd, domain, option, (const char*)&flag, sizeof(flag) );
}
-
int socket_set_xreuseaddr(int fd)
{
#ifdef _WIN32
@@ -966,6 +1137,23 @@ int socket_set_nodelay(int fd)
return socket_setoption(fd, IPPROTO_TCP, TCP_NODELAY, 1);
}
+int socket_set_ipv6only(int fd)
+{
+/* IPV6_ONLY is only supported since Vista on Windows,
+ * and the Mingw headers lack its definition anyway.
+ */
+#if defined(_WIN32) && !defined(IPV6_V6ONLY)
+ return 0;
+#else
+ return socket_setoption(fd, IPPROTO_IPV6, IPV6_V6ONLY, 1);
+#endif
+}
+
+
+int socket_get_error(int fd)
+{
+ return socket_getoption(fd, SOL_SOCKET, SO_ERROR, -1);
+}
#ifdef _WIN32
#include <stdlib.h>