diff --git a/lib/prototypes.h b/lib/prototypes.h index d2314dcd..066252c6 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -193,6 +194,9 @@ extern bool gr_append_member (struct group *grp, char *member); /* hushed.c */ extern bool hushed (const char *username); +/* inet_sockaddr2str.c */ +extern const char *inet_sockaddr2str(const struct sockaddr *sa); + /* audit_help.c */ #ifdef WITH_AUDIT extern int audit_fd; diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index c2277a02..5484c8a5 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -38,6 +38,7 @@ libmisc_la_SOURCES = \ hushed.c \ idmapping.h \ idmapping.c \ + inet_sockaddr2str.c \ isexpired.c \ limits.c \ list.c log.c \ diff --git a/libmisc/inet_sockaddr2str.c b/libmisc/inet_sockaddr2str.c new file mode 100644 index 00000000..ce7466ca --- /dev/null +++ b/libmisc/inet_sockaddr2str.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2022, Alejandro Colomar + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#ident "$Id$" + +#include "defines.h" +#include "prototypes.h" + + +#if !defined(INET_ADDRSTRLENMAX) +#define INET_ADDRSTRLENMAX MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) +#endif + + +/* + * SYNOPSIS + * const char *inet_sockaddr2str(const struct sockaddr *sa); + * + * DESCRIPTION + * This function is similar to inet_ntop(3). It transforms an address + * in 'struct in_addr' or 'struct in6_addr' form into a human-readable + * string. + * + * It receives a sockaddr structure, which is simpler to pass after + * receiving it from getaddrinfo(3). However, this function is not + * reentrant, and like inet_ntoa(3), it uses an internal buffer, for + * simplicity; anyway we're not in a multithreaded program, and it + * doesn't contain any sensitive data, so it's fine to use static + * storage here. + * + * RETURN VALUE + * This function returns a pointer to a statically allocated buffer, + * which subsequent calls will overwrite. + * + * On error, it returns NULL. + * + * ERRORS + * EAFNOSUPPORT + * The address family in sa->sa_family is not AF_INET or AF_INET6. + * + * CAVEATS + * This function is not reentrant. + */ + + +const char * +inet_sockaddr2str(const struct sockaddr *sa) +{ + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + static char buf[INET_ADDRSTRLENMAX]; + + switch (sa->sa_family) { + case AF_INET: + sin = (struct sockaddr_in *) sa; + inet_ntop(AF_INET, &sin->sin_addr, buf, NITEMS(buf)); + return buf; + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + inet_ntop(AF_INET6, &sin6->sin6_addr, buf, NITEMS(buf)); + return buf; + default: + errno = EAFNOSUPPORT; + return NULL; + } +}