--- net-snmp-5.4.2.1-dev/configure.in 2009-01-22 20:00:37.030183514 +0200 +++ net-snmp-5.4.2.1-netlink/configure.in 2009-01-23 01:30:24.148211644 +0200 @@ -310,6 +310,12 @@ AC_ARG_ENABLE(efence,, AC_MSG_ERROR([ Invalid option. Use --with-efence/--without-efence instead ]) ) +AC_ARG_WITH(nl, +[ --with-nl Look for and use libnl (linux only).], + use_nl="$withval") +AC_ARG_ENABLE(nl,, + AC_MSG_ERROR([ Invalid option. Use --with-nl/--without-nl instead ]) ) + tryrsaref=no AC_ARG_WITH(rsaref, [ --with-rsaref=PATH Look for librsaref in PATH/lib.], @@ -2664,6 +2670,21 @@ AC_CHECK_LIB(efence, EF_Exit) fi +if test "x$use_nl" != "xno"; then + case $target_os in + linux*) # Check for libnl (linux) + AC_CHECK_HEADERS(netlink/netlink.h, + AC_CHECK_LIB(nl, nl_connect, [ + AC_DEFINE_UNQUOTED(HAVE_NL, "1", [have libnl]) + LIBNL_LIBS="-lnl" + LIBNL="Yes" + ]) + ) + ;; + esac +fi +AC_SUBST(LIBNL_LIBS) + # Checks for libraries. # AC_CHECK_LIB(des, main) # AC_CHECK_LIB(m, asin) --- net-snmp-5.4.2.1/agent/Makefile.in 2009-01-23 01:31:48.951541328 +0200 +++ net-snmp-5.4.2.1/agent/Makefile.in 2009-02-05 20:50:30.825174223 +0200 @@ -81,7 +81,7 @@ LOCAL_LIBS = -L../snmplib/.libs -L../snmplib -L./.libs -L./helpers/.libs -L./helpers LAGENTLIBS = @LAGENTLIBS@ -LMIBLIBS = @LMIBLIBS@ +LMIBLIBS = @LMIBLIBS@ @LIBNL_LIBS@ PERLLDOPTS_FOR_APPS = @PERLLDOPTS_FOR_APPS@ PERLLDOPTS_FOR_LIBS = @PERLLDOPTS_FOR_LIBS@ LIBS = $(USELIBS) @AGENTLIBS@ $(PERLLDOPTS_FOR_APPS) --- net-snmp-5.4.2.1-nl/agent/mibgroup/mibII/tcpTable.c 2009-03-10 21:53:36.453773342 +0200 +++ net-snmp-5.4.2.1-nl/agent/mibgroup/mibII/tcpTable.c 2009-03-10 22:49:50.326352782 +0200 @@ -29,6 +29,11 @@ #if HAVE_NETINET_TCP_VAR_H #include #endif +#if HAVE_NETLINK_NETLINK_H +#include +#include +#include +#endif #include #include @@ -543,6 +548,112 @@ #else /* hpux11 */ #ifdef linux + +// see +#define TCP_ALL ((1 << (TCP_CLOSING + 1)) - 1) + +static int +tcpTable_load_netlink() +{ + // TODO: perhaps use permanent nl handle? + struct nl_handle *nl = nl_handle_alloc(); + + if (nl == NULL) { + DEBUGMSGTL(("mibII/tcpTable", "Failed to allocate netlink handle\n")); + snmp_log(LOG_ERR, "snmpd: Failed to allocate netlink handle\n"); + 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); + return -1; + } + + struct inet_diag_req req = { + .idiag_family = AF_INET, + .idiag_states = TCP_ALL, + }; + + struct nl_msg *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); + return -1; + } + nlmsg_free(nm); + + struct sockaddr_nl peer; + unsigned char *buf = NULL; + int running = 1, len; + + while (running) { + 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); + return -1; + } + + struct nlmsghdr *h = (struct nlmsghdr*)buf; + while (nlmsg_ok(h, len)) { + if (h->nlmsg_type == NLMSG_DONE) { + running = 0; + break; + } + + struct inet_diag_msg *r = nlmsg_data(h); + + if (r->idiag_family != AF_INET) { + h = nlmsg_next(h, &len); + continue; + } + + struct inpcb pcb, *nnew; + static int linux_states[12] = + { 1, 5, 3, 4, 6, 7, 11, 1, 8, 9, 2, 10 }; + + memcpy(&pcb.inp_laddr.s_addr, r->id.idiag_src, r->idiag_family == AF_INET ? 4 : 6); + memcpy(&pcb.inp_faddr.s_addr, r->id.idiag_dst, r->idiag_family == AF_INET ? 4 : 6); + + pcb.inp_lport = r->id.idiag_sport; + pcb.inp_fport = r->id.idiag_dport; + + pcb.inp_state = (r->idiag_state & 0xf) < 12 ? linux_states[r->idiag_state & 0xf] : 2; + if (pcb.inp_state == 5 /* established */ || + pcb.inp_state == 8 /* closeWait */ ) + tcp_estab++; + pcb.uid = r->idiag_uid; + + nnew = SNMP_MALLOC_TYPEDEF(struct inpcb); + if (nnew == NULL) { + running = 0; + // XXX report malloc error and return -1? + break; + } + memcpy(nnew, &pcb, sizeof(struct inpcb)); + nnew->inp_next = tcp_head; + tcp_head = nnew; + + h = nlmsg_next(h, &len); + } + free(buf); + } + + nl_handle_destroy(nl); + + if (tcp_head) { + DEBUGMSGTL(("mibII/tcpTable", "Loaded TCP Table using netlink\n")); + return 0; + } + DEBUGMSGTL(("mibII/tcpTable", "Failed to load TCP Table (netlink)\n")); + return -1; +} + int tcpTable_load(netsnmp_cache *cache, void *vmagic) { @@ -551,6 +662,10 @@ tcpTable_free(cache, NULL); + if (tcpTable_load_netlink() == 0) { + return 0; + } + if (!(in = fopen("/proc/net/tcp", "r"))) { DEBUGMSGTL(("mibII/tcpTable", "Failed to load TCP Table (linux1)\n")); snmp_log(LOG_ERR, "snmpd: cannot open /proc/net/tcp ...\n");