diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2012-07-13 14:05:36 +0200 |
---|---|---|
committer | David Lamparter <equinox@opensourcerouting.org> | 2012-07-13 14:05:40 +0200 |
commit | 18a4e3715f89337ac8b70f6f63cc131c3218c82c (patch) | |
tree | 1b38b2eae4e1cee042f96a42217b14647159bf0f /lib/agentx.c | |
parent | a47c5838e9f445ab887ad927706b11ccbb181364 (diff) | |
parent | 8046ba6ec4d6e87bf8da6563c0f3e5e66c4652b3 (diff) |
Merge remote branch 'vincentbernat/feature/agentx'
Diffstat (limited to 'lib/agentx.c')
-rw-r--r-- | lib/agentx.c | 213 |
1 files changed, 213 insertions, 0 deletions
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 (¬ification_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 (¬ification_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 */ |