shared/socket-util: add function to query remote address

This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2014-06-29 19:24:56 -04:00
parent ad95fd1d2b
commit b31f535c9a
3 changed files with 104 additions and 4 deletions

View file

@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <stddef.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include "macro.h"
#include "util.h"
@ -574,13 +575,12 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
int getpeername_pretty(int fd, char **ret) {
union sockaddr_union sa;
socklen_t salen;
socklen_t salen = sizeof(sa);
int r;
assert(fd >= 0);
assert(ret);
salen = sizeof(sa);
if (getpeername(fd, &sa.sa, &salen) < 0)
return -errno;
@ -608,12 +608,11 @@ int getpeername_pretty(int fd, char **ret) {
int getsockname_pretty(int fd, char **ret) {
union sockaddr_union sa;
socklen_t salen;
socklen_t salen = sizeof(sa);
assert(fd >= 0);
assert(ret);
salen = sizeof(sa);
if (getsockname(fd, &sa.sa, &salen) < 0)
return -errno;
@ -625,6 +624,49 @@ int getsockname_pretty(int fd, char **ret) {
return sockaddr_pretty(&sa.sa, salen, false, ret);
}
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
int r;
char host[NI_MAXHOST], *ret;
assert(_ret);
r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
if (r != 0) {
_cleanup_free_ char *sockname = NULL;
int saved_errno = errno;
r = sockaddr_pretty(&sa->sa, salen, true, &sockname);
if (r < 0)
log_error("sockadd_pretty() failed: %s", strerror(-r));
else
log_error("getnameinfo(%s) failed: %s", sockname, strerror(-r));
return -saved_errno;
}
ret = strdup(host);
if (!ret)
return log_oom();
*_ret = ret;
return 0;
}
int getnameinfo_pretty(int fd, char **ret) {
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
assert(fd >= 0);
assert(ret);
if (getsockname(fd, &sa.sa, &salen) < 0) {
log_error("getsockname(%d) failed: %m", fd);
return -errno;
}
return socknameinfo_pretty(&sa, salen, ret);
}
int socket_address_unlink(SocketAddress *a) {
assert(a);

View file

@ -101,6 +101,9 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
int getpeername_pretty(int fd, char **ret);
int getsockname_pretty(int fd, char **ret);
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);
int getnameinfo_pretty(int fd, char **ret);
const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_;
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_;

View file

@ -22,6 +22,7 @@
#include "util.h"
#include "macro.h"
#include "log.h"
#include "async.h"
static void test_socket_address_parse(void) {
SocketAddress a;
@ -212,6 +213,58 @@ static void test_in_addr_prefix_next(void) {
}
static void *connect_thread(void *arg) {
union sockaddr_union *sa = arg;
_cleanup_close_ int fd = -1;
fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
assert(fd >= 0);
assert_se(connect(fd, &sa->sa, sizeof(sa->in)) == 0);
return NULL;
}
static void test_nameinfo_pretty(void) {
_cleanup_free_ char *stdin = NULL, *localhost = NULL;
union sockaddr_union s = {
.in.sin_family = AF_INET,
.in.sin_port = 0,
.in.sin_addr.s_addr = htonl(INADDR_ANY),
};
int r;
union sockaddr_union c = {};
socklen_t slen = sizeof(c.in), clen = sizeof(c.in);
_cleanup_close_ int sfd = -1, cfd = -1, afd = -1;
r = getnameinfo_pretty(STDIN_FILENO, &stdin);
log_info("No connection remote: %s", strerror(-r));
assert_se(r < 0);
sfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
assert(sfd >= 0);
assert_se(bind(sfd, &s.sa, sizeof(s.in)) == 0);
/* find out the port number */
assert_se(getsockname(sfd, &s.sa, &slen) == 0);
assert_se(listen(sfd, 1) == 0);
assert_se(asynchronous_job(connect_thread, &s) == 0);
log_debug("Accepting new connection on fd:%d", sfd);
cfd = accept4(sfd, &c.sa, &clen, SOCK_CLOEXEC);
assert(cfd >= 0);
r = getnameinfo_pretty(cfd, &localhost);
log_info("Connection from %s", localhost);
assert(r == 0);
}
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@ -224,5 +277,7 @@ int main(int argc, char *argv[]) {
test_in_addr_prefix_intersect();
test_in_addr_prefix_next();
test_nameinfo_pretty();
return 0;
}