CHANGES: Linux: BUG: 2238: Add libnl3 support
diff --git a/Makefile.top b/Makefile.top
index 7190e90..334fbb8 100644
--- a/Makefile.top
+++ b/Makefile.top
@@ -114,5 +114,5 @@
 SNMPLIB_INCLUDES        = $(@SNMPLIB_INCLUDES@)
 AGENT_INCLUDES          = $(@AGENT_INCLUDES@)
 HELPER_INCLUDES         = $(@HELPER_INCLUDES@)
-MIBGROUP_INCLUDES       = $(@MIBGROUP_INCLUDES@)
+MIBGROUP_INCLUDES       = $(@MIBGROUP_INCLUDES@) @EXTERNAL_MIBGROUP_INCLUDES@
 
diff --git a/agent/mibgroup/mibII/tcpTable.c b/agent/mibgroup/mibII/tcpTable.c
index ddd4b2c..9f6889f 100644
--- a/agent/mibgroup/mibII/tcpTable.c
+++ b/agent/mibgroup/mibII/tcpTable.c
@@ -559,11 +559,35 @@
 const static int linux_states[12] = { 1, 5, 3, 4, 6, 7, 11, 1, 8, 9, 2, 10 };
 
 #if HAVE_NETLINK_NETLINK_H
+
+#if !defined(HAVE_LIBNL3)
+/* libnl3 API implemented on top of the libnl1 API */
+
+#define nl_sock nl_handle
+
+static const char *nl_geterror_compat(int e)
+{
+    return nl_geterror();
+}
+
+#define nl_geterror(e) nl_geterror_compat(e)
+
+static struct nl_socket *nl_socket_alloc(void)
+{
+    return nl_handle_alloc();
+}
+
+static void nl_socket_free(struct nl_socket *ns)
+{
+    nl_handle_destroy(ns);
+}
+#endif /* HAVE_LIBNL3 */
+
 static int
 tcpTable_load_netlink(void)
 {
-	/*  TODO: perhaps use permanent nl handle? */
-	struct nl_handle *nl = nl_handle_alloc();
+	/* TODO: perhaps use permanent nl socket ? */
+	struct nl_sock *nl = nl_socket_alloc();
 	struct inet_diag_req req = {
 		.idiag_family = AF_INET,
 		.idiag_states = TCP_ALL,
@@ -573,7 +597,7 @@
 
 	struct sockaddr_nl peer;
 	unsigned char *buf = NULL;
-	int running = 1, len;
+	int running = 1, len, err;
 
 	if (nl == NULL) {
 		DEBUGMSGTL(("mibII/tcpTable", "Failed to allocate netlink handle\n"));
@@ -581,20 +605,22 @@
 		return -1;
 	}
 
-	if (nl_connect(nl, NETLINK_INET_DIAG) < 0) {
-		DEBUGMSGTL(("mibII/tcpTable", "Failed to connect to netlink: %s\n", nl_geterror()));
-		snmp_log(LOG_ERR, "snmpd: Couldn't connect to netlink: %s\n", nl_geterror());
-		nl_handle_destroy(nl);
+	err = nl_connect(nl, NETLINK_INET_DIAG);
+	if (err < 0) {
+		DEBUGMSGTL(("mibII/tcpTable", "Failed to connect to netlink: %s\n", nl_geterror(err)));
+		snmp_log(LOG_ERR, "snmpd: Couldn't connect to netlink: %s\n", nl_geterror(err));
+		nl_socket_free(nl);
 		return -1;
 	}
 
 	nm = nlmsg_alloc_simple(TCPDIAG_GETSOCK, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST);
 	nlmsg_append(nm, &req, sizeof(struct inet_diag_req), 0);
 
-	if (nl_send_auto_complete(nl, nm) < 0) {
-		DEBUGMSGTL(("mibII/tcpTable", "nl_send_autocomplete(): %s\n", nl_geterror()));
-		snmp_log(LOG_ERR, "snmpd: nl_send_autocomplete(): %s\n", nl_geterror());
-		nl_handle_destroy(nl);
+	err = nl_send_auto_complete(nl, nm);
+	if (err < 0) {
+		DEBUGMSGTL(("mibII/tcpTable", "nl_send_autocomplete(): %s\n", nl_geterror(err)));
+		snmp_log(LOG_ERR, "snmpd: nl_send_autocomplete(): %s\n", nl_geterror(err));
+		nl_socket_free(nl);
 		return -1;
 	}
 	nlmsg_free(nm);
@@ -602,9 +628,9 @@
 	while (running) {
 		struct nlmsghdr *h;
 		if ((len = nl_recv(nl, &peer, &buf, NULL)) <= 0) {
-			DEBUGMSGTL(("mibII/tcpTable", "nl_recv(): %s\n", nl_geterror()));
-			snmp_log(LOG_ERR, "snmpd: nl_recv(): %s\n", nl_geterror());
-			nl_handle_destroy(nl);
+			DEBUGMSGTL(("mibII/tcpTable", "nl_recv(): %s\n", nl_geterror(len)));
+			snmp_log(LOG_ERR, "snmpd: nl_recv(): %s\n", nl_geterror(len));
+			nl_socket_free(nl);
 			return -1;
 		}
 
@@ -653,7 +679,7 @@
 		free(buf);
 	}
 
-	nl_handle_destroy(nl);
+	nl_socket_free(nl);
 
 	if (tcp_head) {
 		DEBUGMSGTL(("mibII/tcpTable", "Loaded TCP Table using netlink\n"));
diff --git a/configure b/configure
index 4812f37..4b9a232 100755
--- a/configure
+++ b/configure
Binary files differ
diff --git a/configure.d/config_os_libs2 b/configure.d/config_os_libs2
index a698319..3414678 100644
--- a/configure.d/config_os_libs2
+++ b/configure.d/config_os_libs2
@@ -207,9 +207,22 @@
 if test "x$with_nl" != "xno"; then
     case $target_os in
     linux*) # Check for libnl (linux)
-	NETSNMP_SEARCH_LIBS(
-	    nl_connect, nl,
-	    [AC_CHECK_HEADERS(netlink/netlink.h)],,, LMIBLIBS)
+        netsnmp_save_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="-I/usr/include/libnl3 $CPPFLAGS"
+        NETSNMP_SEARCH_LIBS(nl_connect, nl-3,
+            [AC_CHECK_HEADERS(netlink/netlink.h)
+            EXTERNAL_MIBGROUP_INCLUDES="$EXTERNAL_MIBGROUP_INCLUDES -I/usr/include/libnl3"],
+            [CPPFLAGS="$netsnmp_save_CPPFLAGS"], [], [], [LMIBLIBS])
+        if test "x$ac_cv_header_netlink_netlink_h" != xyes; then
+            NETSNMP_SEARCH_LIBS(nl_connect, nl, [
+                AC_CHECK_HEADERS(netlink/netlink.h)], [], [], LMIBLIBS)
+        fi
+        if test "x$ac_cv_header_netlink_netlink_h" = xyes; then
+            AC_EGREP_HEADER([nl_socket_free], [netlink/socket.h],
+                            [AC_DEFINE([HAVE_LIBNL3], [1],
+                            [Define to 1 if <netlink/netlink.h> provides the
+                            libnl3 API])])
+        fi
     ;;
     esac
 fi
diff --git a/configure.d/config_os_progs b/configure.d/config_os_progs
index dd3eb0f..a60714e 100644
--- a/configure.d/config_os_progs
+++ b/configure.d/config_os_progs
@@ -171,6 +171,7 @@
 AC_SUBST(AGENT_INCLUDES)
 AC_SUBST(HELPER_INCLUDES)
 AC_SUBST(MIBGROUP_INCLUDES)
+AC_SUBST(EXTERNAL_MIBGROUP_INCLUDES)
 AC_SUBST(GNU_vpath)
 AC_SUBST(NON_GNU_VPATH)
 
diff --git a/include/net-snmp/net-snmp-config.h.in b/include/net-snmp/net-snmp-config.h.in
index e09dd76..8bbd50a 100644
--- a/include/net-snmp/net-snmp-config.h.in
+++ b/include/net-snmp/net-snmp-config.h.in
@@ -320,6 +320,9 @@
 /* Define to 1 if you have the `mld' library (-lmld). */
 #undef HAVE_LIBMLD
 
+/* Define to 1 if <netlink/netlink.h> provides the libnl3 API */
+#undef HAVE_LIBNL3
+
 /* define if you have libnm */
 #undef HAVE_LIBNM