summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/agentx.c133
-rw-r--r--lib/smux.c2
-rw-r--r--lib/thread.c49
4 files changed, 184 insertions, 2 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 73417ad8..e00ad54d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -11,7 +11,7 @@ libzebra_la_SOURCES = \
checksum.c vector.c linklist.c vty.c command.c \
sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
- zclient.c sockopt.c smux.c snmp.c md5.c if_rmap.c keychain.c privs.c \
+ zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \
sigevent.c pqueue.c jhash.c memtypes.c workqueue.c
BUILT_SOURCES = memtypes.h route_types.h
diff --git a/lib/agentx.c b/lib/agentx.c
new file mode 100644
index 00000000..9cf6de5e
--- /dev/null
+++ b/lib/agentx.c
@@ -0,0 +1,133 @@
+/* SNMP support
+ * Copyright (C) 2012 Vincent Bernat <bernat@luffy.cx>
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#if defined HAVE_SNMP && defined SNMP_AGENTX
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "command.h"
+#include "smux.h"
+
+int agentx_enabled = 0;
+
+/* AgentX node. */
+static struct cmd_node agentx_node =
+{
+ SMUX_NODE,
+ "" /* AgentX has no interface. */
+};
+
+/* Logging NetSNMP messages */
+static int
+agentx_log_callback(int major, int minor,
+ void *serverarg, void *clientarg)
+{
+ struct snmp_log_message *slm = (struct snmp_log_message *)serverarg;
+ char *msg = strdup (slm->msg);
+ if (msg) msg[strlen(msg)-1] = '\0';
+ switch (slm->priority)
+ {
+ case LOG_EMERG: zlog_err ("snmp[emerg]: %s", msg?msg:slm->msg); break;
+ case LOG_ALERT: zlog_err ("snmp[alert]: %s", msg?msg:slm->msg); break;
+ case LOG_CRIT: zlog_err ("snmp[crit]: %s", msg?msg:slm->msg); break;
+ case LOG_ERR: zlog_err ("snmp[err]: %s", msg?msg:slm->msg); break;
+ case LOG_WARNING: zlog_warn ("snmp[warning]: %s", msg?msg:slm->msg); break;
+ case LOG_NOTICE: zlog_notice("snmp[notice]: %s", msg?msg:slm->msg); break;
+ case LOG_INFO: zlog_info ("snmp[info]: %s", msg?msg:slm->msg); break;
+ case LOG_DEBUG: zlog_debug ("snmp[debug]: %s", msg?msg:slm->msg); break;
+ }
+ free(msg);
+ return SNMP_ERR_NOERROR;
+}
+
+static int
+config_write_agentx (struct vty *vty)
+{
+ if (agentx_enabled)
+ vty_out (vty, "agentx%s", VTY_NEWLINE);
+ return 0;
+}
+
+DEFUN (agentx_enable,
+ agentx_enable_cmd,
+ "agentx",
+ "SNMP AgentX protocol settings\n"
+ "SNMP AgentX settings\n")
+{
+ if (!agentx_enabled)
+ {
+ init_snmp("quagga");
+ agentx_enabled = 1;
+ return CMD_SUCCESS;
+ }
+ vty_out (vty, "SNMP AgentX already enabled%s", VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+DEFUN (no_agentx,
+ no_agentx_cmd,
+ "no agentx",
+ NO_STR
+ "SNMP AgentX protocol settings\n"
+ "SNMP AgentX settings\n")
+{
+ if (!agentx_enabled) return CMD_SUCCESS;
+ vty_out (vty, "SNMP AgentX support cannot be disabled once enabled%s", VTY_NEWLINE);
+ return CMD_WARNING;
+}
+
+void
+smux_init (struct thread_master *tm)
+{
+ netsnmp_enable_subagent ();
+ snmp_disable_log ();
+ snmp_enable_calllog ();
+ snmp_register_callback (SNMP_CALLBACK_LIBRARY,
+ SNMP_CALLBACK_LOGGING,
+ agentx_log_callback,
+ NULL);
+ init_agent ("quagga");
+
+ install_node (&agentx_node, config_write_agentx);
+ install_element (CONFIG_NODE, &agentx_enable_cmd);
+ install_element (CONFIG_NODE, &no_agentx_cmd);
+}
+
+void
+smux_register_mib (const char *descr, struct variable *var,
+ size_t width, int num,
+ oid name[], size_t namelen)
+{
+ register_mib (descr, var, width, num, name, namelen);
+}
+
+int
+smux_trap (const oid *name, size_t namelen,
+ const oid *iname, size_t inamelen,
+ const struct trap_object *trapobj, size_t trapobjlen,
+ unsigned int tick, u_char sptrap)
+{
+ return 1;
+}
+
+#endif /* HAVE_SNMP */
diff --git a/lib/smux.c b/lib/smux.c
index a5d84a8f..29370050 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -21,7 +21,7 @@
#include <zebra.h>
-#ifdef HAVE_SNMP
+#if defined HAVE_SNMP && defined SNMP_SMUX
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
diff --git a/lib/thread.c b/lib/thread.c
index 86d0ff8c..6341dfd7 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -29,6 +29,16 @@
#include "hash.h"
#include "command.h"
#include "sigevent.h"
+
+#if defined HAVE_SNMP && defined SNMP_AGENTX
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/snmp_vars.h>
+
+extern int agentx_enabled;
+#endif
+
/* Recent absolute time of day */
struct timeval recent_time;
@@ -1030,6 +1040,11 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
while (1)
{
int num = 0;
+#if defined HAVE_SNMP && defined SNMP_AGENTX
+ struct timeval snmp_timer_wait;
+ int snmpblock = 0;
+ int fdsetsize;
+#endif
/* Signals pre-empt everything */
quagga_sigevent_process ();
@@ -1065,6 +1080,26 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
timer_wait = timer_wait_bg;
}
+#if defined HAVE_SNMP && defined SNMP_AGENTX
+ /* When SNMP is enabled, we may have to select() on additional
+ FD. snmp_select_info() will add them to `readfd'. The trick
+ with this function is its last argument. We need to set it to
+ 0 if timer_wait is not NULL and we need to use the provided
+ new timer only if it is still set to 0. */
+ if (agentx_enabled)
+ {
+ fdsetsize = FD_SETSIZE;
+ snmpblock = 1;
+ if (timer_wait)
+ {
+ snmpblock = 0;
+ memcpy(&snmp_timer_wait, timer_wait, sizeof(struct timeval));
+ }
+ snmp_select_info(&fdsetsize, &readfd, &snmp_timer_wait, &snmpblock);
+ if (snmpblock == 0)
+ timer_wait = &snmp_timer_wait;
+ }
+#endif
num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
/* Signals should get quick treatment */
@@ -1076,6 +1111,20 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
return NULL;
}
+#if defined HAVE_SNMP && defined SNMP_AGENTX
+ if (agentx_enabled)
+ {
+ if (num > 0)
+ snmp_read(&readfd);
+ else if (num == 0)
+ {
+ snmp_timeout();
+ run_alarms();
+ }
+ netsnmp_check_outstanding_agent_requests();
+ }
+#endif
+
/* Check foreground timers. Historically, they have had higher
priority than I/O threads, so let's push them onto the ready
list in front of the I/O threads. */