Merge branch 'V5-6-patches' into V5-7-patches

* V5-6-patches:
  CHANGES: Linux: BUG: 2238: Add libnl3 support

Conflicts:
	configure
diff --git a/Makefile.top b/Makefile.top
index 862fb94..9abd5de 100644
--- a/Makefile.top
+++ b/Makefile.top
@@ -116,5 +116,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 92b1ff3..135ab83 100644
--- a/agent/mibgroup/mibII/tcpTable.c
+++ b/agent/mibgroup/mibII/tcpTable.c
@@ -568,11 +568,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,
@@ -582,7 +606,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"));
@@ -590,20 +614,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);
@@ -611,9 +637,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;
 		}
 
@@ -662,7 +688,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 8e296fd..d252395 100755
--- a/configure
+++ b/configure
@@ -699,6 +699,7 @@
 target
 NON_GNU_VPATH
 GNU_vpath
+EXTERNAL_MIBGROUP_INCLUDES
 MIBGROUP_INCLUDES
 HELPER_INCLUDES
 AGENT_INCLUDES
@@ -15287,6 +15288,7 @@
 
 
 
+
 ##
 #   System-related compilation checks:
 ##
@@ -22481,6 +22483,97 @@
 if test "x$with_nl" != "xno"; then
     case $target_os in
     linux*) # Check for libnl (linux)
+        netsnmp_save_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="-I/usr/include/libnl3 $CPPFLAGS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nl_connect" >&5
+$as_echo_n "checking for library containing nl_connect... " >&6; }
+if ${netsnmp_cv_func_nl_connect_LIBS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  netsnmp_func_search_save_LIBS="$LIBS"
+     netsnmp_target_val="$LIBS"
+          netsnmp_temp_LIBS=" ${LIBS}"
+     netsnmp_result=no
+     LIBS="${netsnmp_temp_LIBS}"
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_connect ();
+int
+main ()
+{
+return nl_connect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result="none required"
+else
+  for netsnmp_cur_lib in nl-3 ; do
+              LIBS="-l${netsnmp_cur_lib} ${netsnmp_temp_LIBS}"
+              cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_connect ();
+int
+main ()
+{
+return nl_connect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  netsnmp_result=-l${netsnmp_cur_lib}
+                   break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+          done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     LIBS="${netsnmp_func_search_save_LIBS}"
+     netsnmp_cv_func_nl_connect_LIBS="${netsnmp_result}"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $netsnmp_cv_func_nl_connect_LIBS" >&5
+$as_echo "$netsnmp_cv_func_nl_connect_LIBS" >&6; }
+ if test "${netsnmp_cv_func_nl_connect_LIBS}" != "no" ; then
+    if test "${netsnmp_cv_func_nl_connect_LIBS}" != "none required" ; then
+       LIBS="${netsnmp_result} ${netsnmp_target_val}"
+    fi
+    for ac_header in netlink/netlink.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "netlink/netlink.h" "ac_cv_header_netlink_netlink_h" "$ac_includes_default"
+if test "x$ac_cv_header_netlink_netlink_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETLINK_NETLINK_H 1
+_ACEOF
+
+fi
+
+done
+
+            EXTERNAL_MIBGROUP_INCLUDES="$EXTERNAL_MIBGROUP_INCLUDES -I/usr/include/libnl3"
+ else
+    CPPFLAGS="$netsnmp_save_CPPFLAGS"
+ fi
+
+        if test "x$ac_cv_header_netlink_netlink_h" != xyes; then
 
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nl_connect" >&5
 $as_echo_n "checking for library containing nl_connect... " >&6; }
@@ -22552,7 +22645,8 @@
     if test "${netsnmp_cv_func_nl_connect_LMIBLIBS}" != "none required" ; then
        LMIBLIBS="${netsnmp_result} ${netsnmp_target_val}"
     fi
-    for ac_header in netlink/netlink.h
+
+                for ac_header in netlink/netlink.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "netlink/netlink.h" "ac_cv_header_netlink_netlink_h" "$ac_includes_default"
 if test "x$ac_cv_header_netlink_netlink_h" = xyes; then :
@@ -22567,6 +22661,22 @@
 
  fi
 
+        fi
+        if test "x$ac_cv_header_netlink_netlink_h" = xyes; then
+            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <netlink/socket.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "nl_socket_free" >/dev/null 2>&1; then :
+
+$as_echo "#define HAVE_LIBNL3 1" >>confdefs.h
+
+fi
+rm -f conftest*
+
+        fi
     ;;
     esac
 fi
diff --git a/configure.d/config_os_libs2 b/configure.d/config_os_libs2
index 34642b8..cb1dde9 100644
--- a/configure.d/config_os_libs2
+++ b/configure.d/config_os_libs2
@@ -225,9 +225,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 c9a60a2..df2e83f 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 f6f8e54..89cc0d8 100644
--- a/include/net-snmp/net-snmp-config.h.in
+++ b/include/net-snmp/net-snmp-config.h.in
@@ -347,6 +347,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