From: Gerrit Renker Date: Fri, 30 Nov 2007 09:23:51 +0000 (+0100) Subject: 02_Reverse-lookup-support.diff X-Git-Tag: v0.3.0~73^2~7 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=7f9340341574044e16e1ffc30f856f13d1e3ba6c 02_Reverse-lookup-support.diff In some parts of the code a reverse-lookup (e.g. "connection from xxx") is used. An address-family independent reverse-lookup function is provided by this patch, exploiting that a socket is described by {src addr, src port, dst addr, dst port}: * host_and_port(): prints host and port number of given socket, * local_name(): pretty-prints src-addr/src-port, * remote_name(): pretty-prints dst-addr/dst-port; Signed-off-by: Gerrit Renker --- diff --git a/net.c b/net.c index 3de57f28..8860312b 100644 --- a/net.c +++ b/net.c @@ -265,6 +265,63 @@ int para_listen(unsigned l3type, unsigned l4type, unsigned short port) return fd; } +/** + * Print numeric host and port number (beware - uses static char). + * \param sa The IPv4/IPv6 socket address to use. + * \param len The length of \p sa. + * + * \sa getnameinfo(3) + */ +char *host_and_port(struct sockaddr *sa, socklen_t len) +{ + static char output[NI_MAXHOST + NI_MAXSERV + 2]; + char hbuf[NI_MAXHOST], + sbuf[NI_MAXSERV]; + int ret; + + ret = getnameinfo(sa, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret) { + PARA_WARNING_LOG("hostname lookup error (%s).\n", gai_strerror(ret)); + sprintf(output, "(unknown)"); + } else { + sprintf(output, "%s#%s", hbuf, sbuf); + } + return output; +} + +/** + * Look up the local or remote side of a connected socket structure. + * \param fd The socket descriptor of the connected socket. + * \param getname Either \fn getsockname() for local, or \fn getpeername() for remote side. + * + * \return A static character string identifying hostname and port of the chosen side + * \sa getsockname(2), getpeername(2) + */ +static char *__get_sock_name(int fd, int (*getname)(int, struct sockaddr*, socklen_t *)) +{ + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + + if (getname(fd, (struct sockaddr *)&ss, &sslen) < 0) { + static char *dont_know = "(don't know)"; + PARA_ERROR_LOG("can not determine address from fd %d: %s\n", fd, strerror(errno)); + return dont_know; + } + + return host_and_port((struct sockaddr *)&ss, sslen); +} + +char *local_name(int sockfd) +{ + return __get_sock_name(sockfd, getsockname); +} + +char *remote_name(int sockfd) +{ + return __get_sock_name(sockfd, getpeername); +} + /* * Send out a buffer, resend on short writes. * diff --git a/net.h b/net.h index e78b7629..965273a8 100644 --- a/net.h +++ b/net.h @@ -37,6 +37,11 @@ extern int makesock(unsigned l3type, unsigned l4type, int passive, #define BACKLOG 10 extern int para_listen(unsigned l3type, unsigned l4type, unsigned short port); +/** Pretty-printing of IPv4/6 socket addresses */ +extern char *host_and_port(struct sockaddr *sa, socklen_t len); +extern char *local_name(int sockfd); +extern char *remote_name(int sockfd); + /** used to crypt the communication between para_server and para_client */ typedef void crypt_function(unsigned long len, const unsigned char *indata, unsigned char *outdata, void *private_data);