diff --git a/apps/snmp/snmp_main.c b/apps/snmp/snmp_main.c index bc7c8846..b1eafb2c 100644 --- a/apps/snmp/snmp_main.c +++ b/apps/snmp/snmp_main.c @@ -30,7 +30,6 @@ the terms of any one of the Apache License version 2 or the GPL. ***** END LICENSE BLOCK ***** - */ #ifdef HAVE_CONFIG_H @@ -45,7 +44,10 @@ #include #include +/* net-snmp */ #include +#include +#include /* cligen */ #include @@ -56,18 +58,181 @@ /* Command line options to be passed to getopt(3) */ #define SNMP_OPTS "hD:f:l:o:" -/*! XXX netsnmp API goes here +#if 1 // XXX hardcoded MIB object from https://github.com/net-snmp/subagent-example/blob/master/example-demon.c +/* cp NET-SNMP-TUTORIAL-MIB.txt ~/.snmp/mibs/ + * sudo /usr/local/sbin/snmpd -Lo -C --rwcommunity=public --master=agentx -f + * sudo example_demon + * snmpget -v 2c -c public localhost NET-SNMP-TUTORIAL-MIB::nstAgentSubagentObject.0 + */ +/*! + * our initialization routine, automatically called by the agent + * (to get called, the function name must match init_FILENAME()) + * the variable we want to tie an OID to. The agent will handle all + * * GET and SET requests to this variable changing it's value as needed. + */ +static long nstAgentSubagentObject = 2; + +static void +init_nstAgentSubagentObject(clicon_handle h) +{ + static oid nstAgentSubagentObject_oid[] = + { 1, 3, 6, 1, 4, 1, 8072, 2, 4, 1, 1, 2, 0 }; + + clicon_debug(1, "%s", __FUNCTION__); + /* + * a debugging statement. Run the agent with -DnstAgentSubagentObject to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("nstAgentSubagentObject", + "Initializing the nstAgentSubagentObject module\n")); + + /* + * the line below registers our variables defined above as + * accessible and makes it writable. A read only version of any + * of these registration would merely call + * register_read_only_long_instance() instead. The functions + * called below should be consistent with your MIB, however. + * + * If we wanted a callback when the value was retrieved or set + * (even though the details of doing this are handled for you), + * you could change the NULL pointer below to a valid handler + * function. + */ + DEBUGMSGTL(("nstAgentSubagentObject", + "Initalizing nstAgentSubagentObject scalar integer. Default value = %ld\n", + nstAgentSubagentObject)); + + netsnmp_register_long_instance("nstAgentSubagentObject", + nstAgentSubagentObject_oid, + OID_LENGTH(nstAgentSubagentObject_oid), + &nstAgentSubagentObject, NULL); + + DEBUGMSGTL(("nstAgentSubagentObject", + "Done initalizing nstAgentSubagentObject module\n")); +} +#endif // XXX Hardcoded + +/*! Signal terminates process + * Just set exit flag for proper exit in event loop + */ +static void +clixon_snmp_sig_term(int arg) +{ + clicon_log(LOG_NOTICE, "%s: %s: pid: %u Signal %d", + __PROGRAM__, __FUNCTION__, getpid(), arg); + /* This should ensure no more accepts or incoming packets are processed because next time eventloop + * is entered, it will terminate. + * However there may be a case of sockets closing rather abruptly for clients + */ + clixon_exit_set(1); +} + +/*! Callback for single socket + * This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling + * the snmp api + * @param[in] s Read socket + * @param[in] arg Clixon handle */ static int -snmp_input_cb(int s, - void *arg) +clixon_snmp_input_cb(int s, + void *arg) { - int retval = -1; + int retval = -1; + fd_set readfds; + // clicon_handle h = (clicon_handle)arg; + + clicon_debug(1, "%s", __FUNCTION__); + FD_ZERO(&readfds); + FD_SET(s, &readfds); + snmp_read(&readfds); retval = 0; // done: return retval; } +/*! Get which sockets are used from SNMP API, the register single sockets into clixon event system + * + * This is a workaround for netsnmps API usiing fdset:s, instead an fdset is created before calling + * the snmp api + * if you use select(), see snmp_select_info() in snmp_api(3) + * snmp_select_info(int *numfds, fd_set *fdset, struct timeval *timeout, int *block) + * @see clixon_snmp_input_cb + */ +static int +clixon_snmp_fdset_register(clicon_handle h) +{ + int retval = -1; + int numfds = 0; + fd_set readfds; + struct timeval timeout = { LONG_MAX, 0 }; + int block = 0; + int nr; + int i; + + FD_ZERO(&readfds); + if ((nr = snmp_sess_select_info(NULL, &numfds, &readfds, &timeout, &block)) < 0){ + clicon_err(OE_SNMP, errno, "snmp_select_error"); + goto done; + } + for (i=0; i&6; } if test "$enable_netsnmp" = "yes"; then # All libs are: - # libnetsnmp, libnetsnmpmibs, libnetsnmpagent, libnetsnmptrapd, libnetsnmphelpers - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snmp_open in -lnetsnmp" >&5 -$as_echo_n "checking for snmp_open in -lnetsnmp... " >&6; } -if ${ac_cv_lib_netsnmp_snmp_open+:} false; then : + # libnetsnmp, libnetsnmpagent, libnetsnmpmibs, libnetsnmptrapd, libnetsnmphelpers + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init_snmp in -lnetsnmp" >&5 +$as_echo_n "checking for init_snmp in -lnetsnmp... " >&6; } +if ${ac_cv_lib_netsnmp_init_snmp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -5341,33 +5341,78 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char snmp_open (); +char init_snmp (); int main () { -return snmp_open (); +return init_snmp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_netsnmp_snmp_open=yes + ac_cv_lib_netsnmp_init_snmp=yes else - ac_cv_lib_netsnmp_snmp_open=no + ac_cv_lib_netsnmp_init_snmp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmp_snmp_open" >&5 -$as_echo "$ac_cv_lib_netsnmp_snmp_open" >&6; } -if test "x$ac_cv_lib_netsnmp_snmp_open" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmp_init_snmp" >&5 +$as_echo "$ac_cv_lib_netsnmp_init_snmp" >&6; } +if test "x$ac_cv_lib_netsnmp_init_snmp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNETSNMP 1 _ACEOF LIBS="-lnetsnmp $LIBS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init_agent in -lnetsnmpagent" >&5 +$as_echo_n "checking for init_agent in -lnetsnmpagent... " >&6; } +if ${ac_cv_lib_netsnmpagent_init_agent+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnetsnmpagent $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 init_agent (); +int +main () +{ +return init_agent (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_netsnmpagent_init_agent=yes +else + ac_cv_lib_netsnmpagent_init_agent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmpagent_init_agent" >&5 +$as_echo "$ac_cv_lib_netsnmpagent_init_agent" >&6; } +if test "x$ac_cv_lib_netsnmpagent_init_agent" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNETSNMPAGENT 1 +_ACEOF + + LIBS="-lnetsnmpagent $LIBS" + fi for ac_header in net-snmp/net-snmp-config.h diff --git a/configure.ac b/configure.ac index 0a86da2e..07abc414 100644 --- a/configure.ac +++ b/configure.ac @@ -289,8 +289,9 @@ AC_MSG_RESULT(checking netsnmp is enabled: $enable_netsnmp) if test "$enable_netsnmp" = "yes"; then # All libs are: - # libnetsnmp, libnetsnmpmibs, libnetsnmpagent, libnetsnmptrapd, libnetsnmphelpers - AC_CHECK_LIB(netsnmp, snmp_open) + # libnetsnmp, libnetsnmpagent, libnetsnmpmibs, libnetsnmptrapd, libnetsnmphelpers + AC_CHECK_LIB(netsnmp, init_snmp) + AC_CHECK_LIB(netsnmpagent, init_agent) AC_CHECK_HEADERS(net-snmp/net-snmp-config.h,[], AC_MSG_ERROR([snmp is missing])) fi diff --git a/include/clixon_config.h.in b/include/clixon_config.h.in index 046d92ff..ddb18d98 100644 --- a/include/clixon_config.h.in +++ b/include/clixon_config.h.in @@ -63,6 +63,9 @@ /* Define to 1 if you have the `netsnmp' library (-lnetsnmp). */ #undef HAVE_LIBNETSNMP +/* Define to 1 if you have the `netsnmpagent' library (-lnetsnmpagent). */ +#undef HAVE_LIBNETSNMPAGENT + /* Define to 1 if you have the `nghttp2' library (-lnghttp2). */ #undef HAVE_LIBNGHTTP2 diff --git a/lib/clixon/clixon_err.h b/lib/clixon/clixon_err.h index 3d31dddb..1878c043 100644 --- a/lib/clixon/clixon_err.h +++ b/lib/clixon/clixon_err.h @@ -74,6 +74,7 @@ enum clicon_err{ OE_RESTCONF, /* RESTCONF errors */ OE_PLUGIN, /* plugin loading, etc */ OE_YANG , /* Yang error */ + OE_SNMP , /* Netsnmp error */ OE_FATAL, /* Fatal error */ OE_UNDEF, /*-- From here error extensions using clixon_err_cat_reg, XXX register dynamically? --*/