summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/agentx.c213
-rw-r--r--lib/smux.c142
-rw-r--r--lib/smux.h117
-rw-r--r--lib/snmp.c133
-rw-r--r--lib/thread.c49
6 files changed, 482 insertions, 176 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 890cc5ca..e00ad54d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in.
-INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib @SNMP_INCLUDES@
+INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib
DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
lib_LTLIBRARIES = libzebra.la
@@ -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 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..be6b4320
--- /dev/null
+++ b/lib/agentx.c
@@ -0,0 +1,213 @@
+/* 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 (struct variable *vp, size_t vp_len,
+ const oid *ename, size_t enamelen,
+ const oid *name, size_t namelen,
+ const oid *iname, size_t inamelen,
+ const struct trap_object *trapobj, size_t trapobjlen,
+ u_char sptrap)
+{
+ oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
+ size_t objid_snmptrap_len = sizeof objid_snmptrap / sizeof (oid);
+ oid notification_oid[MAX_OID_LEN];
+ size_t notification_oid_len;
+ unsigned int i;
+
+ netsnmp_variable_list *notification_vars = NULL;
+ if (!agentx_enabled) return 0;
+
+ /* snmpTrapOID */
+ oid_copy (notification_oid, ename, enamelen);
+ notification_oid[enamelen] = sptrap;
+ notification_oid_len = enamelen + 1;
+ snmp_varlist_add_variable (&notification_vars,
+ objid_snmptrap, objid_snmptrap_len,
+ ASN_OBJECT_ID,
+ (u_char *) notification_oid,
+ notification_oid_len * sizeof(oid));
+
+ /* Provided bindings */
+ for (i = 0; i < trapobjlen; i++)
+ {
+ unsigned int j;
+ oid oid[MAX_OID_LEN];
+ size_t oid_len, onamelen;
+ u_char *val;
+ size_t val_len;
+ WriteMethod *wm = NULL;
+ struct variable cvp;
+
+ /* Make OID. */
+ if (trapobj[i].namelen > 0)
+ {
+ /* Columnar object */
+ onamelen = trapobj[i].namelen;
+ oid_copy (oid, name, namelen);
+ oid_copy (oid + namelen, trapobj[i].name, onamelen);
+ oid_copy (oid + namelen + onamelen, iname, inamelen);
+ oid_len = namelen + onamelen + inamelen;
+ }
+ else
+ {
+ /* Scalar object */
+ onamelen = trapobj[i].namelen * (-1);
+ oid_copy (oid, name, namelen);
+ oid_copy (oid + namelen, trapobj[i].name, onamelen);
+ oid[onamelen + namelen] = 0;
+ oid_len = namelen + onamelen + 1;
+ }
+
+ /* Locate the appropriate function and type in the MIB registry. */
+ for (j = 0; j < vp_len; j++)
+ {
+ if (oid_compare (trapobj[i].name, onamelen, vp[j].name, vp[j].namelen) != 0)
+ continue;
+ /* We found the appropriate variable in the MIB registry. */
+ oid_copy(cvp.name, name, namelen);
+ oid_copy(cvp.name + namelen, vp[j].name, vp[j].namelen);
+ cvp.namelen = namelen + vp[j].namelen;
+ cvp.type = vp[j].type;
+ cvp.magic = vp[j].magic;
+ cvp.acl = vp[j].acl;
+ cvp.findVar = vp[j].findVar;
+ /* Grab the result. */
+ val = cvp.findVar (&cvp, oid, &oid_len, 1, &val_len, &wm);
+ if (!val) break;
+ snmp_varlist_add_variable (&notification_vars,
+ oid, oid_len,
+ vp[j].type,
+ val,
+ val_len);
+ break;
+ }
+ }
+
+
+ send_v2trap (notification_vars);
+ snmp_free_varbind (notification_vars);
+ return 1;
+}
+
+#endif /* HAVE_SNMP */
diff --git a/lib/smux.c b/lib/smux.c
index b7cd18d1..07466400 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -21,15 +21,9 @@
#include <zebra.h>
-#ifdef HAVE_SNMP
-#ifdef HAVE_NETSNMP
+#if defined HAVE_SNMP && defined SNMP_SMUX
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
-#else
-#include <asn1.h>
-#include <snmp.h>
-#include <snmp_impl.h>
-#endif
#include "log.h"
#include "thread.h"
@@ -40,6 +34,45 @@
#include "sockunion.h"
#include "smux.h"
+#define SMUX_PORT_DEFAULT 199
+
+#define SMUXMAXPKTSIZE 1500
+#define SMUXMAXSTRLEN 256
+
+#define SMUX_OPEN (ASN_APPLICATION | ASN_CONSTRUCTOR | 0)
+#define SMUX_CLOSE (ASN_APPLICATION | ASN_PRIMITIVE | 1)
+#define SMUX_RREQ (ASN_APPLICATION | ASN_CONSTRUCTOR | 2)
+#define SMUX_RRSP (ASN_APPLICATION | ASN_PRIMITIVE | 3)
+#define SMUX_SOUT (ASN_APPLICATION | ASN_PRIMITIVE | 4)
+
+#define SMUX_GET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)
+#define SMUX_GETNEXT (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)
+#define SMUX_GETRSP (ASN_CONTEXT | ASN_CONSTRUCTOR | 2)
+#define SMUX_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)
+#define SMUX_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 4)
+
+#define SMUX_MAX_FAILURE 3
+
+/* SNMP tree. */
+struct subtree
+{
+ /* Tree's oid. */
+ oid name[MAX_OID_LEN];
+ u_char name_len;
+
+ /* List of the variables. */
+ struct variable *variables;
+
+ /* Length of the variables list. */
+ int variables_num;
+
+ /* Width of the variables list. */
+ int variables_width;
+
+ /* Registered flag. */
+ int registered;
+};
+
#define min(A,B) ((A) < (B) ? (A) : (B))
enum smux_event {SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ};
@@ -82,62 +115,6 @@ static struct cmd_node smux_node =
/* thread master */
static struct thread_master *master;
-void *
-oid_copy (void *dest, const void *src, size_t size)
-{
- return memcpy (dest, src, size * sizeof (oid));
-}
-
-void
-oid2in_addr (oid oid[], int len, struct in_addr *addr)
-{
- int i;
- u_char *pnt;
-
- if (len == 0)
- return;
-
- pnt = (u_char *) addr;
-
- for (i = 0; i < len; i++)
- *pnt++ = oid[i];
-}
-
-void
-oid_copy_addr (oid oid[], struct in_addr *addr, int len)
-{
- int i;
- u_char *pnt;
-
- if (len == 0)
- return;
-
- pnt = (u_char *) addr;
-
- for (i = 0; i < len; i++)
- oid[i] = *pnt++;
-}
-
-int
-oid_compare (oid *o1, int o1_len, oid *o2, int o2_len)
-{
- int i;
-
- for (i = 0; i < min (o1_len, o2_len); i++)
- {
- if (o1[i] < o2[i])
- return -1;
- else if (o1[i] > o2[i])
- return 1;
- }
- if (o1_len < o2_len)
- return -1;
- if (o1_len > o2_len)
- return 1;
-
- return 0;
-}
-
static int
oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len)
{
@@ -479,7 +456,7 @@ smux_set (oid *reqid, size_t *reqid_len,
if (write_method)
{
return (*write_method)(action, val, val_type, val_len,
- statP, suffix, suffix_len, v);
+ statP, suffix, suffix_len);
}
else
{
@@ -991,11 +968,18 @@ smux_open (int sock)
return send (sock, buf, (ptr - buf), 0);
}
+/* `ename` is ignored. Instead of using the provided enterprise OID,
+ the SMUX peer is used. This keep compatibility with the previous
+ versions of Quagga.
+
+ All other fields are used as they are intended. */
int
-smux_trap (const oid *name, size_t namelen,
+smux_trap (struct variable *vp, size_t vp_len,
+ const oid *ename, size_t enamelen,
+ 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)
+ u_char sptrap)
{
unsigned int i;
u_char buf[BUFSIZ];
@@ -1360,32 +1344,6 @@ smux_peer_oid (struct vty *vty, const char *oid_str, const char *passwd_str)
return 0;
}
-int
-smux_header_generic (struct variable *v, oid *name, size_t *length, int exact,
- size_t *var_len, WriteMethod **write_method)
-{
- oid fulloid[MAX_OID_LEN];
- int ret;
-
- oid_copy (fulloid, v->name, v->namelen);
- fulloid[v->namelen] = 0;
- /* Check against full instance. */
- ret = oid_compare (name, *length, fulloid, v->namelen + 1);
-
- /* Check single instance. */
- if ((exact && (ret != 0)) || (!exact && (ret >= 0)))
- return MATCH_FAILED;
-
- /* In case of getnext, fill in full instance. */
- memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid));
- *length = v->namelen + 1;
-
- *write_method = 0;
- *var_len = sizeof(long); /* default to 'long' results */
-
- return MATCH_SUCCEEDED;
-}
-
static int
smux_peer_default (void)
{
diff --git a/lib/smux.h b/lib/smux.h
index f5754ed9..72b4eaf0 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -22,24 +22,8 @@
#ifndef _ZEBRA_SNMP_H
#define _ZEBRA_SNMP_H
-#define SMUX_PORT_DEFAULT 199
-
-#define SMUXMAXPKTSIZE 1500
-#define SMUXMAXSTRLEN 256
-
-#define SMUX_OPEN (ASN_APPLICATION | ASN_CONSTRUCTOR | 0)
-#define SMUX_CLOSE (ASN_APPLICATION | ASN_PRIMITIVE | 1)
-#define SMUX_RREQ (ASN_APPLICATION | ASN_CONSTRUCTOR | 2)
-#define SMUX_RRSP (ASN_APPLICATION | ASN_PRIMITIVE | 3)
-#define SMUX_SOUT (ASN_APPLICATION | ASN_PRIMITIVE | 4)
-
-#define SMUX_GET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)
-#define SMUX_GETNEXT (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)
-#define SMUX_GETRSP (ASN_CONTEXT | ASN_CONSTRUCTOR | 2)
-#define SMUX_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)
-#define SMUX_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 4)
-
-#define SMUX_MAX_FAILURE 3
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+#include <net-snmp/agent/snmp_vars.h>
/* Structures here are mostly compatible with UCD SNMP 4.1.1 */
#define MATCH_FAILED (-1)
@@ -55,73 +39,15 @@
#define IN_ADDR_SIZE sizeof(struct in_addr)
-struct variable;
-
+#undef REGISTER_MIB
#define REGISTER_MIB(descr, var, vartype, theoid) \
smux_register_mib(descr, (struct variable *)var, sizeof(struct vartype), \
sizeof(var)/sizeof(struct vartype), \
theoid, sizeof(theoid)/sizeof(oid))
-typedef int (WriteMethod)(int action,
- u_char *var_val,
- u_char var_val_type,
- size_t var_val_len,
- u_char *statP,
- oid *name,
- size_t length,
- struct variable *v);
-
-typedef u_char *(FindVarMethod)(struct variable *v,
- oid *name,
- size_t *length,
- int exact,
- size_t *var_len,
- WriteMethod **write_method);
-
-/* SNMP variable */
-struct variable
-{
- /* Index of the MIB.*/
- u_char magic;
-
- /* Type of variable. */
- char type;
-
- /* Access control list. */
- u_short acl;
-
- /* Callback function. */
- FindVarMethod *findVar;
-
- /* Suffix of the MIB. */
- int namelen;
- oid name[MAX_OID_LEN];
-};
-
-/* SNMP tree. */
-struct subtree
-{
- /* Tree's oid. */
- oid name[MAX_OID_LEN];
- u_char name_len;
-
- /* List of the variables. */
- struct variable *variables;
-
- /* Length of the variables list. */
- int variables_num;
-
- /* Width of the variables list. */
- int variables_width;
-
- /* Registered flag. */
- int registered;
-};
-
struct trap_object
{
- FindVarMethod *findVar;
- int namelen;
+ int namelen; /* Negative if the object is not indexed */
oid name[MAX_OID_LEN];
};
@@ -145,14 +71,41 @@ struct trap_object
)
extern void smux_init (struct thread_master *tm);
-extern void smux_start (void);
extern void smux_register_mib(const char *, struct variable *,
size_t, int, oid [], size_t);
extern int smux_header_generic (struct variable *, oid [], size_t *,
int, size_t *, WriteMethod **);
-extern int smux_trap (const oid *, size_t, const oid *, size_t,
- const struct trap_object *,
- size_t, unsigned int, u_char);
+extern int smux_header_table (struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+/* For traps, three OID are provided:
+
+ 1. The enterprise OID to use (the last argument will be appended to
+ it to form the SNMP trap OID)
+
+ 2. The base OID for objects to be sent in traps.
+
+ 3. The index OID for objects to be sent in traps. This index is used
+ to designate a particular instance of a column.
+
+ The provided trap object contains the bindings to be sent with the
+ trap. The base OID will be prefixed to the provided OID and, if the
+ length is positive, the requested OID is assumed to be a columnar
+ object and the index OID will be appended.
+
+ The two first arguments are the MIB registry used to locate the trap
+ objects.
+
+ The use of the arguments may differ depending on the implementation
+ used.
+*/
+extern int smux_trap (struct variable *, size_t,
+ const oid *, size_t,
+ const oid *, size_t,
+ const oid *, size_t,
+ const struct trap_object *, size_t,
+ u_char);
+
extern int oid_compare (oid *, int, oid *, int);
extern void oid2in_addr (oid [], int, struct in_addr *);
extern void *oid_copy (void *, const void *, size_t);
diff --git a/lib/snmp.c b/lib/snmp.c
new file mode 100644
index 00000000..79595a1e
--- /dev/null
+++ b/lib/snmp.c
@@ -0,0 +1,133 @@
+/* SNMP support
+ * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
+ *
+ * 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>
+
+#ifdef HAVE_SNMP
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "smux.h"
+
+#define min(A,B) ((A) < (B) ? (A) : (B))
+
+int
+oid_compare (oid *o1, int o1_len, oid *o2, int o2_len)
+{
+ int i;
+
+ for (i = 0; i < min (o1_len, o2_len); i++)
+ {
+ if (o1[i] < o2[i])
+ return -1;
+ else if (o1[i] > o2[i])
+ return 1;
+ }
+ if (o1_len < o2_len)
+ return -1;
+ if (o1_len > o2_len)
+ return 1;
+
+ return 0;
+}
+
+void *
+oid_copy (void *dest, const void *src, size_t size)
+{
+ return memcpy (dest, src, size * sizeof (oid));
+}
+
+void
+oid2in_addr (oid oid[], int len, struct in_addr *addr)
+{
+ int i;
+ u_char *pnt;
+
+ if (len == 0)
+ return;
+
+ pnt = (u_char *) addr;
+
+ for (i = 0; i < len; i++)
+ *pnt++ = oid[i];
+}
+
+void
+oid_copy_addr (oid oid[], struct in_addr *addr, int len)
+{
+ int i;
+ u_char *pnt;
+
+ if (len == 0)
+ return;
+
+ pnt = (u_char *) addr;
+
+ for (i = 0; i < len; i++)
+ oid[i] = *pnt++;
+}
+
+int
+smux_header_generic (struct variable *v, oid *name, size_t *length, int exact,
+ size_t *var_len, WriteMethod **write_method)
+{
+ oid fulloid[MAX_OID_LEN];
+ int ret;
+
+ oid_copy (fulloid, v->name, v->namelen);
+ fulloid[v->namelen] = 0;
+ /* Check against full instance. */
+ ret = oid_compare (name, *length, fulloid, v->namelen + 1);
+
+ /* Check single instance. */
+ if ((exact && (ret != 0)) || (!exact && (ret >= 0)))
+ return MATCH_FAILED;
+
+ /* In case of getnext, fill in full instance. */
+ memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid));
+ *length = v->namelen + 1;
+
+ *write_method = 0;
+ *var_len = sizeof(long); /* default to 'long' results */
+
+ return MATCH_SUCCEEDED;
+}
+
+int
+smux_header_table (struct variable *v, oid *name, size_t *length, int exact,
+ size_t *var_len, WriteMethod **write_method)
+{
+ /* If the requested OID name is less than OID prefix we
+ handle, adjust it to our prefix. */
+ if ((oid_compare (name, *length, v->name, v->namelen)) < 0)
+ {
+ if (exact)
+ return MATCH_FAILED;
+ oid_copy(name, v->name, v->namelen);
+ *length = v->namelen;
+ }
+
+ *write_method = 0;
+ *var_len = sizeof(long);
+
+ return MATCH_SUCCEEDED;
+}
+#endif /* HAVE_SNMP */
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. */