We should aim to use the thread-safe variants of getprotoby{name,number} and getservbyport(). However, they may not be available with other libc, so it requires a configure check. As that is cumbersome, add wrappers that do that at one place. Signed-off-by: Thomas Haller <thaller@xxxxxxxxxx> --- configure.ac | 4 +++ src/nftutils.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/nftutils.h | 16 +++++++++ 3 files changed, 117 insertions(+) diff --git a/configure.ac b/configure.ac index b0201ac3528e..42f0dc4cf392 100644 --- a/configure.ac +++ b/configure.ac @@ -108,6 +108,10 @@ AC_DEFINE([HAVE_LIBJANSSON], [1], [Define if you have libjansson]) ]) AM_CONDITIONAL([BUILD_JSON], [test "x$with_json" != xno]) +AC_CHECK_DECLS([getprotobyname_r, getprotobynumber_r, getservbyport_r], [], [], [[ +#include <netdb.h> +]]) + AC_CONFIG_FILES([ \ Makefile \ libnftables.pc \ diff --git a/src/nftutils.c b/src/nftutils.c index 758283d1b650..13f879ddc5c7 100644 --- a/src/nftutils.c +++ b/src/nftutils.c @@ -3,3 +3,100 @@ #include <config.h> #include "nftutils.h" + +#include <netdb.h> +#include <string.h> +#include <stdint.h> + +/* Buffer size used for getprotobynumber_r() and similar. The manual comments + * that a buffer of 1024 should be sufficient "for most applications"(??), so + * let's double it. It still fits reasonably on the stack, so no need to + * choose a smaller one. */ +#define NETDB_BUFSIZE 2048 + +bool nft_getprotobynumber(int proto, char *out_name, size_t name_len) +{ + const struct protoent *result; + +#if HAVE_DECL_GETPROTOBYNUMBER_R + struct protoent result_buf; + char buf[NETDB_BUFSIZE]; + int r; + + r = getprotobynumber_r(proto, + &result_buf, + buf, + sizeof(buf), + (struct protoent **) &result); + if (r != 0 || result != &result_buf) + result = NULL; +#else + result = getprotobynumber(proto); +#endif + + if (!result) + return false; + + if (strlen(result->p_name) >= name_len) + return false; + strcpy(out_name, result->p_name); + return true; +} + +int nft_getprotobyname(const char *name) +{ + const struct protoent *result; + +#if HAVE_DECL_GETPROTOBYNAME_R + struct protoent result_buf; + char buf[NETDB_BUFSIZE]; + int r; + + r = getprotobyname_r(name, + &result_buf, + buf, + sizeof(buf), + (struct protoent **) &result); + if (r != 0 || result != &result_buf) + result = NULL; +#else + result = getprotobyname(name); +#endif + + if (!result) + return -1; + + if (result->p_proto < 0 || result->p_proto > UINT8_MAX) + return -1; + return (uint8_t) result->p_proto; +} + +bool nft_getservbyport(int port, const char *proto, char *out_name, size_t name_len) +{ + const struct servent *result; + +#if HAVE_DECL_GETSERVBYPORT_R + struct servent result_buf; + char buf[NETDB_BUFSIZE]; + int r; + + r = getservbyport_r(port, + proto, + &result_buf, + buf, + sizeof(buf), + (struct servent**) &result); + if (r != 0 || result != &result_buf) + result = NULL; +#else + result = getservbyport(port, proto); +#endif + + if (!result) + return false; + + if (strlen(result->s_name) >= name_len) + return false; + strcpy(out_name, result->s_name); + return true; +} diff --git a/src/nftutils.h b/src/nftutils.h index 9ad68d55ce47..cb584b9ca32b 100644 --- a/src/nftutils.h +++ b/src/nftutils.h @@ -2,4 +2,20 @@ #ifndef NFTUTILS_H #define NFTUTILS_H +#include <stdbool.h> +#include <stddef.h> + +/* The maximum buffer size for (struct protoent).p_name. It is excessively large, + * while still reasonably fitting on the stack. Arbitrarily chosen. */ +#define NFT_PROTONAME_MAXSIZE 1024 + +bool nft_getprotobynumber(int number, char *out_name, size_t name_len); +int nft_getprotobyname(const char *name); + +/* The maximum buffer size for (struct servent).s_name. It is excessively large, + * while still reasonably fitting on the stack. Arbitrarily chosen. */ +#define NFT_SERVNAME_MAXSIZE 1024 + +bool nft_getservbyport(int port, const char *proto, char *out_name, size_t name_len); + #endif /* NFTUTILS_H */ -- 2.41.0