diff --git a/configure.ac b/configure.ac
index 94f950c76..e3bda0599 100644
--- a/configure.ac
+++ b/configure.ac
@@ -783,6 +783,7 @@ AC_CHECK_FUNCS(strdup		\
 	strcasestr		\
 	memrchr			\
 	localtime_r		\
+	getprotobynumber_r	\
 	gmtime_r		\
 	strnlen			\
 	strtok_r)
diff --git a/lib/compat/CMakeLists.txt b/lib/compat/CMakeLists.txt
index 4fa05d7e0..95fcb0e0d 100644
--- a/lib/compat/CMakeLists.txt
+++ b/lib/compat/CMakeLists.txt
@@ -10,7 +10,8 @@ set(COMPAT_HEADERS
     compat/openssl_support.h
     compat/pcre.h
     compat/getent.h
-    compat/getent-bb.h
+    compat/getent-sun.h
+    compat/getent-generic.h
     PARENT_SCOPE)
 
 set(COMPAT_SOURCES
@@ -24,7 +25,8 @@ set(COMPAT_SOURCES
     compat/strnlen.c
     compat/time.c
     compat/openssl_support.c
-    compat/getent.c
+    compat/getent-sun.c
+    compat/getent-generic.c
     PARENT_SCOPE)
 
 add_test_subdirectory(tests)
diff --git a/lib/compat/Makefile.am b/lib/compat/Makefile.am
index e5c1f4e56..8d5010558 100644
--- a/lib/compat/Makefile.am
+++ b/lib/compat/Makefile.am
@@ -13,9 +13,10 @@ compatinclude_HEADERS		= 	\
 	lib/compat/string.h		\
 	lib/compat/time.h		\
 	lib/compat/openssl_support.h	\
-	lib/compat/pcre.h	\
-	lib/compat/getent.h	\
-	lib/compat/getent-bb.h
+	lib/compat/pcre.h		\
+	lib/compat/getent.h		\
+	lib/compat/getent-sun.h		\
+	lib/compat/getent-generic.h
 
 compat_sources			= 	\
 	lib/compat/getutent.c		\
@@ -28,6 +29,7 @@ compat_sources			= 	\
 	lib/compat/strnlen.c		\
 	lib/compat/time.c		\
 	lib/compat/openssl_support.c	\
-	lib/compat/getent.c
+	lib/compat/getent-sun.c		\
+	lib/compat/getent-generic.c
 
 include lib/compat/tests/Makefile.am
diff --git a/lib/compat/getent-generic.c b/lib/compat/getent-generic.c
new file mode 100644
index 000000000..f75d1cc0a
--- /dev/null
+++ b/lib/compat/getent-generic.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017 Balabit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As an additional exemption you are allowed to compile & link against the
+ * OpenSSL libraries as published by the OpenSSL project. See the file
+ * COPYING for details.
+ *
+ */
+
+#include "compat/getent-generic.h"
+
+#ifndef SYSLOG_NG_HAVE_GETPROTOBYNUMBER_R
+
+#include <glib.h>
+#include <errno.h>
+
+G_LOCK_DEFINE_STATIC(getproto);
+
+/* this code does not support proto aliases, as we wouldn't be using
+ * them anyway.  Should we ever want to support it, we would need to
+ * suballocate @buf and store all of the aliases in the same character
+ * array.
+ */
+static void
+_extract_protoent_fields(struct protoent *dst, struct protoent *src, char *buf, size_t buflen)
+{
+  g_strlcpy(buf, src->p_name, buflen);
+  dst->p_name = buf;
+  dst->p_aliases = NULL;
+  dst->p_proto = src->p_proto;
+}
+
+int
+_compat_generic__getprotobynumber_r(int proto,
+                                    struct protoent *result_buf, char *buf,
+                                    size_t buflen, struct protoent **result)
+{
+  struct protoent *pe;
+
+  G_LOCK(getproto);
+  pe = getprotobynumber(proto);
+
+  if (pe)
+    {
+      _extract_protoent_fields(result_buf, pe, buf, buflen);
+      *result = result_buf;
+      errno = 0;
+    }
+
+  G_UNLOCK(getproto);
+  return errno;
+}
+
+int
+_compat_generic__getprotobyname_r(const char *name,
+                                  struct protoent *result_buf, char *buf,
+                                  size_t buflen, struct protoent **result)
+{
+  struct protoent *pe;
+
+  G_LOCK(getproto);
+  pe = getprotobyname(name);
+
+  if (pe)
+    {
+      _extract_protoent_fields(result_buf, pe, buf, buflen);
+      *result = result_buf;
+      errno = 0;
+    }
+
+  G_UNLOCK(getproto);
+  return errno;
+}
+
+G_LOCK_DEFINE_STATIC(getserv);
+
+/* this code does not support service aliases or using the s_proto field, as
+ * we wouldn't be using them anyway.  Should we ever want to support it, we
+ * would need to suballocate @buf and store all of the aliases in the same
+ * character array.
+ */
+static void
+_extract_servent_fields(struct servent *dst, struct servent *src, char *buf, size_t buflen)
+{
+  g_strlcpy(buf, src->s_name, buflen);
+  dst->s_name = buf;
+  dst->s_aliases = NULL;
+  dst->s_port = src->s_port;
+  /* we don't support s_proto */
+  dst->s_proto = NULL;
+}
+
+
+int
+_compat_generic__getservbyport_r(int port, const char *proto,
+                                 struct servent *result_buf, char *buf,
+                                 size_t buflen, struct servent **result)
+{
+  struct servent *se;
+
+  G_LOCK(getserv);
+  se = getservbyport(port, proto);
+
+  if (se)
+    {
+      _extract_servent_fields(result_buf, se, buf, buflen);
+      *result = result_buf;
+      errno = 0;
+    }
+
+  G_UNLOCK(getserv);
+  return errno;
+}
+
+int
+_compat_generic__getservbyname_r(const char *name, const char *proto,
+                                 struct servent *result_buf, char *buf,
+                                 size_t buflen, struct servent **result)
+{
+  struct servent *se;
+
+  G_LOCK(getserv);
+  se = getservbyname(name, proto);
+
+  if (se)
+    {
+      _extract_servent_fields(result_buf, se, buf, buflen);
+      *result = result_buf;
+      errno = 0;
+    }
+
+  G_UNLOCK(getserv);
+  return errno;
+}
+
+#endif
diff --git a/lib/compat/getent-generic.h b/lib/compat/getent-generic.h
new file mode 100644
index 000000000..cc95a2646
--- /dev/null
+++ b/lib/compat/getent-generic.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Balabit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As an additional exemption you are allowed to compile & link against the
+ * OpenSSL libraries as published by the OpenSSL project. See the file
+ * COPYING for details.
+ *
+ */
+
+#ifndef COMPAT_GETENT_GENERIC_H_INCLUDED
+#define COMPAT_GETENT_GENERIC_H_INCLUDED
+
+#include "compat/compat.h"
+
+#ifndef SYSLOG_NG_HAVE_GETPROTOBYNUMBER_R
+
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+#include <netdb.h>
+
+int _compat_generic__getprotobynumber_r(int proto,
+                                        struct protoent *result_buf, char *buf,
+                                        size_t buflen, struct protoent **result);
+
+int _compat_generic__getprotobyname_r(const char *name,
+                                      struct protoent *result_buf, char *buf,
+                                      size_t buflen, struct protoent **result);
+
+int _compat_generic__getservbyport_r(int port, const char *proto,
+                                     struct servent *result_buf, char *buf,
+                                     size_t buflen, struct servent **result);
+
+int _compat_generic__getservbyname_r(const char *name, const char *proto,
+                                     struct servent *result_buf, char *buf,
+                                     size_t buflen, struct servent **result);
+
+#endif
+
+#endif
diff --git a/lib/compat/getent.c b/lib/compat/getent-sun.c
similarity index 63%
rename from lib/compat/getent.c
rename to lib/compat/getent-sun.c
index bb9b5b431..dce676f2f 100644
--- a/lib/compat/getent.c
+++ b/lib/compat/getent-sun.c
@@ -21,40 +21,45 @@
  *
  */
 
-#if defined(sun) || defined(__sun)
+#include "compat/getent-sun.h"
 
-#include "compat/getent-bb.h"
+#if defined(sun) || defined(__sun)
 #include <errno.h>
 
-int bb__getprotobynumber_r(int proto,
-                           struct protoent *result_buf, char *buf,
-                           size_t buflen, struct protoent **result)
+int
+_compat_sun__getprotobynumber_r(int proto,
+                                struct protoent *result_buf, char *buf,
+                                size_t buflen, struct protoent **result)
 {
   *result = getprotobynumber_r(proto, result_buf, buf, buflen);
   return (*result ? NULL : errno);
 }
 
-int bb__getprotobyname_r(const char *name,
-                         struct protoent *result_buf, char *buf,
-                         size_t buflen, struct protoent **result)
+int
+_compat_sun__getprotobyname_r(const char *name,
+                              struct protoent *result_buf, char *buf,
+                              size_t buflen, struct protoent **result)
 {
   *result = getprotobyname_r(name, result_buf, buf, buflen);
   return (*result ? NULL : errno);
 }
 
-int bb__getservbyport_r(int port, const char *proto,
-                        struct servent *result_buf, char *buf,
-                        size_t buflen, struct servent **result)
+int
+_compat_sun__getservbyport_r(int port, const char *proto,
+                             struct servent *result_buf, char *buf,
+                             size_t buflen, struct servent **result)
 {
   *result =  getservbyport_r(port, proto, result_buf, buf, buflen);
   return (*result ? NULL : errno);
 }
 
-int bb__getservbyname_r(const char *name, const char *proto,
-                        struct servent *result_buf, char *buf,
-                        size_t buflen, struct servent **result)
+int
+_compat_sun__getservbyname_r(const char *name, const char *proto,
+                             struct servent *result_buf, char *buf,
+                             size_t buflen, struct servent **result)
 {
   *result =  getservbyname_r(name, proto, result_buf, buf, buflen);
   return (*result ? NULL : errno);
 }
+
 #endif
diff --git a/lib/compat/getent-bb.h b/lib/compat/getent-sun.h
similarity index 53%
rename from lib/compat/getent-bb.h
rename to lib/compat/getent-sun.h
index 15aa2f5e5..fc1eccd2c 100644
--- a/lib/compat/getent-bb.h
+++ b/lib/compat/getent-sun.h
@@ -21,8 +21,10 @@
  *
  */
 
-#ifndef GETENT_BB_H_INCLUDED
-#define GETENT_BB_H_INCLUDED
+#ifndef COMPAT_GETENT_SUN_H_INCLUDED
+#define COMPAT_GETENT_SUN_H_INCLUDED
+
+#include "compat/compat.h"
 
 #if defined(sun) || defined(__sun)
 
@@ -31,21 +33,21 @@
 #include <pwd.h>
 #include <netdb.h>
 
-int bb__getprotobynumber_r(int proto,
-                           struct protoent *result_buf, char *buf,
-                           size_t buflen, struct protoent **result);
+int _compat_sun__getprotobynumber_r(int proto,
+                                    struct protoent *result_buf, char *buf,
+                                    size_t buflen, struct protoent **result);
 
-int bb__getprotobyname_r(const char *name,
-                         struct protoent *result_buf, char *buf,
-                         size_t buflen, struct protoent **result);
+int _compat_sun__getprotobyname_r(const char *name,
+                                  struct protoent *result_buf, char *buf,
+                                  size_t buflen, struct protoent **result);
 
-int bb__getservbyport_r(int port, const char *proto,
-                        struct servent *result_buf, char *buf,
-                        size_t buflen, struct servent **result);
+int _compat_sun__getservbyport_r(int port, const char *proto,
+                                 struct servent *result_buf, char *buf,
+                                 size_t buflen, struct servent **result);
 
-int bb__getservbyname_r(const char *name, const char *proto,
-                        struct servent *result_buf, char *buf,
-                        size_t buflen, struct servent **result);
+int _compat_sun__getservbyname_r(const char *name, const char *proto,
+                                 struct servent *result_buf, char *buf,
+                                 size_t buflen, struct servent **result);
 
 #endif
 
diff --git a/lib/compat/getent.h b/lib/compat/getent.h
index 09a9f73d6..01c3deb6d 100644
--- a/lib/compat/getent.h
+++ b/lib/compat/getent.h
@@ -21,22 +21,28 @@
  *
  */
 
-#ifndef GETENT_COMPAT_H_INCLUDED
-#define GETENT_COMPAT_H_INCLUDED
+#ifndef COMPAT_GETENT_H_INCLUDED
+#define COMPAT_GETENT_H_INCLUDED
 
-#include <sys/types.h>
-#include <grp.h>
-#include <pwd.h>
-#include <netdb.h>
+#include "compat/compat.h"
 
-#if defined(sun) || defined(__sun)
+#ifndef SYSLOG_NG_HAVE_GETPROTOBYNUMBER_R
 
-#define getprotobynumber_r bb__getprotobynumber_r
-#define getprotobyname_r bb__getprotobyname_r
-#define getservbyport_r bb__getservbyport_r
-#define getservbyname_r bb__getservbyname_r
+#define getprotobynumber_r _compat_generic__getprotobynumber_r
+#define getprotobyname_r _compat_generic__getprotobyname_r
+#define getservbyport_r _compat_generic__getservbyport_r
+#define getservbyname_r _compat_generic__getservbyname_r
 
-#include "getent-bb.h"
+#include "getent-generic.h"
 
-#endif // Solaris
+#elif defined(sun) || defined(__sun)
+
+#define getprotobynumber_r _compat_sun__getprotobynumber_r
+#define getprotobyname_r _compat_sun__getprotobyname_r
+#define getservbyport_r _compat_sun__getservbyport_r
+#define getservbyname_r _compat_sun__getservbyname_r
+
+#include "getent-sun.h"
+
+#endif
 #endif