diff options
author | David 'Digit' Turner <digit@android.com> | 2010-12-23 00:59:44 +0100 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-01-02 22:09:05 +0100 |
commit | ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48 (patch) | |
tree | ed261be80a75ad5c2508a154f27a3101a7752d16 | |
parent | 8423ffa1a8c56e65220e2a354cd62f71f99a7a06 (diff) | |
download | external_qemu-ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48.zip external_qemu-ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48.tar.gz external_qemu-ca6a2e034bce665a08d9d748ac11d6a7cfcd7c48.tar.bz2 |
qemu-sockets-android.c: Add inet_dgram_opts
Change-Id: I30b3905332925d369481612a571342e21a5a7ed9
-rw-r--r-- | qemu-sockets-android.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/qemu-sockets-android.c b/qemu-sockets-android.c index e7d5e18..b07129b 100644 --- a/qemu-sockets-android.c +++ b/qemu-sockets-android.c @@ -26,6 +26,10 @@ # define AI_ADDRCONFIG 0 #endif +#ifndef INET6_ADDRSTRLEN +# define INET6_ADDRSTRLEN 46 +#endif + static int sockets_debug = 0; static const int on=1, off=0; @@ -252,6 +256,114 @@ EXIT: return sock; } +int inet_dgram_opts(QemuOpts *opts) +{ + SockAddress** peer_list = NULL; + SockAddress** local_list = NULL; + SockAddress* e; + unsigned flags = 0; + const char *addr; + const char *port; + char uaddr[INET6_ADDRSTRLEN+1]; + char uport[33]; + int sock = -1; + int nn; + + /* lookup peer addr */ + addr = qemu_opt_get(opts, "host"); + port = qemu_opt_get(opts, "port"); + if (addr == NULL || strlen(addr) == 0) { + addr = "localhost"; + } + if (port == NULL || strlen(port) == 0) { + fprintf(stderr, "inet_dgram: port not specified\n"); + return -1; + } + + flags = SOCKET_LIST_DGRAM; + if (qemu_opt_get_bool(opts, "ipv4", 0)) { + flags &= SOCKET_LIST_FORCE_IN6; + flags |= SOCKET_LIST_FORCE_INET; + } + if (qemu_opt_get_bool(opts, "ipv6", 0)) { + flags &= SOCKET_LIST_FORCE_INET; + flags |= SOCKET_LIST_FORCE_IN6; + } + + peer_list = sock_address_list_create(addr, port, flags); + if (peer_list == NULL) { + fprintf(stderr,"getaddrinfo(%s,%s): %s\n", + addr, port, errno_str); + return -1; + } + + /* lookup local addr */ + addr = qemu_opt_get(opts, "localaddr"); + port = qemu_opt_get(opts, "localport"); + if (addr == NULL || strlen(addr) == 0) { + addr = NULL; + } + if (!port || strlen(port) == 0) + port = "0"; + + flags = SOCKET_LIST_DGRAM | SOCKET_LIST_PASSIVE; + local_list = sock_address_list_create(addr, port, flags); + if (local_list == NULL) { + fprintf(stderr,"getaddrinfo(%s,%s): %s\n", + addr, port, errno_str); + goto EXIT; + } + + if (sock_address_get_numeric_info(local_list[0], + uaddr, INET6_ADDRSTRLEN, + uport, 32)) { + fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); + goto EXIT; + } + + for (nn = 0; peer_list[nn] != NULL; nn++) { + SockAddress *local = local_list[0]; + e = peer_list[nn]; + sock = socket_create(sock_address_get_family(e), SOCKET_DGRAM); + if (sock < 0) { + fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, + sock_address_strfamily(e), errno_str); + continue; + } + socket_set_xreuseaddr(sock); + + /* bind socket */ + if (socket_bind(sock, local) < 0) { + fprintf(stderr,"%s: bind(%s,%s,%s): OK\n", __FUNCTION__, + sock_address_strfamily(local), addr, port); + socket_close(sock); + continue; + } + + /* connect to peer */ + if (socket_connect(sock,e) < 0) { + if (sockets_debug) + fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, + sock_address_strfamily(e), + sock_address_to_string(e), addr, port, strerror(errno)); + socket_close(sock); + continue; + } + if (sockets_debug) + fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__, + sock_address_strfamily(e), + sock_address_to_string(e), addr, port); + + goto EXIT; + } + sock = -1; +EXIT: + if (local_list) + sock_address_list_free(local_list); + if (peer_list) + sock_address_list_free(peer_list); + return sock; +} /* compatibility wrapper */ static int inet_parse(QemuOpts *opts, const char *str) |