mirror of https://github.com/xemu-project/xemu.git
sockets: add helpers for creating SocketAddress from a socket
Add two helper methods that, given a socket file descriptor, can return a populated SocketAddress struct containing either the local or remote address information. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
c14e42d7a4
commit
17c55decec
|
@ -88,4 +88,34 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
|
||||||
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
int parse_host_port(struct sockaddr_in *saddr, const char *str);
|
||||||
int socket_init(void);
|
int socket_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* socket_local_address:
|
||||||
|
* @fd: the socket file handle
|
||||||
|
* @errp: pointer to uninitialized error object
|
||||||
|
*
|
||||||
|
* Get the string representation of the local socket
|
||||||
|
* address. A pointer to the allocated address information
|
||||||
|
* struct will be returned, which the caller is required to
|
||||||
|
* release with a call qapi_free_SocketAddress when no
|
||||||
|
* longer required.
|
||||||
|
*
|
||||||
|
* Returns: the socket address struct, or NULL on error
|
||||||
|
*/
|
||||||
|
SocketAddress *socket_local_address(int fd, Error **errp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* socket_remote_address:
|
||||||
|
* @fd: the socket file handle
|
||||||
|
* @errp: pointer to uninitialized error object
|
||||||
|
*
|
||||||
|
* Get the string representation of the remote socket
|
||||||
|
* address. A pointer to the allocated address information
|
||||||
|
* struct will be returned, which the caller is required to
|
||||||
|
* release with a call qapi_free_SocketAddress when no
|
||||||
|
* longer required.
|
||||||
|
*
|
||||||
|
* Returns: the socket address struct, or NULL on error
|
||||||
|
*/
|
||||||
|
SocketAddress *socket_remote_address(int fd, Error **errp);
|
||||||
|
|
||||||
#endif /* QEMU_SOCKET_H */
|
#endif /* QEMU_SOCKET_H */
|
||||||
|
|
|
@ -1018,3 +1018,113 @@ int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SocketAddress *
|
||||||
|
socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
|
||||||
|
socklen_t salen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
char host[NI_MAXHOST];
|
||||||
|
char serv[NI_MAXSERV];
|
||||||
|
SocketAddress *addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = getnameinfo((struct sockaddr *)sa, salen,
|
||||||
|
host, sizeof(host),
|
||||||
|
serv, sizeof(serv),
|
||||||
|
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||||
|
if (ret != 0) {
|
||||||
|
error_setg(errp, "Cannot format numeric socket address: %s",
|
||||||
|
gai_strerror(ret));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = g_new0(SocketAddress, 1);
|
||||||
|
addr->kind = SOCKET_ADDRESS_KIND_INET;
|
||||||
|
addr->inet = g_new0(InetSocketAddress, 1);
|
||||||
|
addr->inet->host = g_strdup(host);
|
||||||
|
addr->inet->port = g_strdup(serv);
|
||||||
|
if (sa->ss_family == AF_INET) {
|
||||||
|
addr->inet->has_ipv4 = addr->inet->ipv4 = true;
|
||||||
|
} else {
|
||||||
|
addr->inet->has_ipv6 = addr->inet->ipv6 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
static SocketAddress *
|
||||||
|
socket_sockaddr_to_address_unix(struct sockaddr_storage *sa,
|
||||||
|
socklen_t salen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
SocketAddress *addr;
|
||||||
|
struct sockaddr_un *su = (struct sockaddr_un *)sa;
|
||||||
|
|
||||||
|
addr = g_new0(SocketAddress, 1);
|
||||||
|
addr->kind = SOCKET_ADDRESS_KIND_UNIX;
|
||||||
|
addr->q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
|
if (su->sun_path[0]) {
|
||||||
|
addr->q_unix->path = g_strndup(su->sun_path,
|
||||||
|
sizeof(su->sun_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
static SocketAddress *
|
||||||
|
socket_sockaddr_to_address(struct sockaddr_storage *sa,
|
||||||
|
socklen_t salen,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
switch (sa->ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
case AF_INET6:
|
||||||
|
return socket_sockaddr_to_address_inet(sa, salen, errp);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
case AF_UNIX:
|
||||||
|
return socket_sockaddr_to_address_unix(sa, salen, errp);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_setg(errp, "socket family %d unsupported",
|
||||||
|
sa->ss_family);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SocketAddress *socket_local_address(int fd, Error **errp)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
socklen_t sslen = sizeof(ss);
|
||||||
|
|
||||||
|
if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
|
||||||
|
error_setg_errno(errp, socket_error(), "%s",
|
||||||
|
"Unable to query local socket address");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket_sockaddr_to_address(&ss, sslen, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SocketAddress *socket_remote_address(int fd, Error **errp)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
socklen_t sslen = sizeof(ss);
|
||||||
|
|
||||||
|
if (getpeername(fd, (struct sockaddr *)&ss, &sslen) < 0) {
|
||||||
|
error_setg_errno(errp, socket_error(), "%s",
|
||||||
|
"Unable to query remote socket address");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket_sockaddr_to_address(&ss, sslen, errp);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue