1/* SNMP support 2 * Copyright (C) 2012 Vincent Bernat <bernat@luffy.cx> 3 * 4 * This file is part of GNU Zebra. 5 * 6 * GNU Zebra is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation; either version 2, or (at your option) any 9 * later version. 10 * 11 * GNU Zebra is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with GNU Zebra; see the file COPYING. If not, write to the Free 18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 19 * 02111-1307, USA. 20 */ 21 22#include <zebra.h> 23 24#if defined HAVE_SNMP && defined SNMP_AGENTX 25#include <net-snmp/net-snmp-config.h> 26#include <net-snmp/net-snmp-includes.h> 27 28#include "command.h" 29#include "smux.h" 30 31int agentx_enabled = 0; 32 33/* AgentX node. */ 34static struct cmd_node agentx_node = 35{ 36 SMUX_NODE, 37 "" /* AgentX has no interface. */ 38}; 39 40/* Logging NetSNMP messages */ 41static int 42agentx_log_callback(int major, int minor, 43 void *serverarg, void *clientarg) 44{ 45 struct snmp_log_message *slm = (struct snmp_log_message *)serverarg; 46 char *msg = strdup (slm->msg); 47 if (msg) msg[strlen(msg)-1] = '\0'; 48 switch (slm->priority) 49 { 50 case LOG_EMERG: zlog_err ("snmp[emerg]: %s", msg?msg:slm->msg); break; 51 case LOG_ALERT: zlog_err ("snmp[alert]: %s", msg?msg:slm->msg); break; 52 case LOG_CRIT: zlog_err ("snmp[crit]: %s", msg?msg:slm->msg); break; 53 case LOG_ERR: zlog_err ("snmp[err]: %s", msg?msg:slm->msg); break; 54 case LOG_WARNING: zlog_warn ("snmp[warning]: %s", msg?msg:slm->msg); break; 55 case LOG_NOTICE: zlog_notice("snmp[notice]: %s", msg?msg:slm->msg); break; 56 case LOG_INFO: zlog_info ("snmp[info]: %s", msg?msg:slm->msg); break; 57 case LOG_DEBUG: zlog_debug ("snmp[debug]: %s", msg?msg:slm->msg); break; 58 } 59 free(msg); 60 return SNMP_ERR_NOERROR; 61} 62 63static int 64config_write_agentx (struct vty *vty) 65{ 66 if (agentx_enabled) 67 vty_out (vty, "agentx%s", VTY_NEWLINE); 68 return 0; 69} 70 71DEFUN (agentx_enable, 72 agentx_enable_cmd, 73 "agentx", 74 "SNMP AgentX protocol settings\n" 75 "SNMP AgentX settings\n") 76{ 77 if (!agentx_enabled) 78 { 79 init_snmp("quagga"); 80 agentx_enabled = 1; 81 return CMD_SUCCESS; 82 } 83 vty_out (vty, "SNMP AgentX already enabled%s", VTY_NEWLINE); 84 return CMD_WARNING; 85} 86 87DEFUN (no_agentx, 88 no_agentx_cmd, 89 "no agentx", 90 NO_STR 91 "SNMP AgentX protocol settings\n" 92 "SNMP AgentX settings\n") 93{ 94 if (!agentx_enabled) return CMD_SUCCESS; 95 vty_out (vty, "SNMP AgentX support cannot be disabled once enabled%s", VTY_NEWLINE); 96 return CMD_WARNING; 97} 98 99void 100smux_init (struct thread_master *tm) 101{ 102 netsnmp_enable_subagent (); 103 snmp_disable_log (); 104 snmp_enable_calllog (); 105 snmp_register_callback (SNMP_CALLBACK_LIBRARY, 106 SNMP_CALLBACK_LOGGING, 107 agentx_log_callback, 108 NULL); 109 init_agent ("quagga"); 110 111 install_node (&agentx_node, config_write_agentx); 112 install_element (CONFIG_NODE, &agentx_enable_cmd); 113 install_element (CONFIG_NODE, &no_agentx_cmd); 114} 115 116void 117smux_register_mib (const char *descr, struct variable *var, 118 size_t width, int num, 119 oid name[], size_t namelen) 120{ 121 register_mib (descr, var, width, num, name, namelen); 122} 123 124int 125smux_trap (struct variable *vp, size_t vp_len, 126 const oid *ename, size_t enamelen, 127 const oid *name, size_t namelen, 128 const oid *iname, size_t inamelen, 129 const struct trap_object *trapobj, size_t trapobjlen, 130 u_char sptrap) 131{ 132 oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 }; 133 size_t objid_snmptrap_len = sizeof objid_snmptrap / sizeof (oid); 134 oid notification_oid[MAX_OID_LEN]; 135 size_t notification_oid_len; 136 unsigned int i; 137 138 netsnmp_variable_list *notification_vars = NULL; 139 if (!agentx_enabled) return 0; 140 141 /* snmpTrapOID */ 142 oid_copy (notification_oid, ename, enamelen); 143 notification_oid[enamelen] = sptrap; 144 notification_oid_len = enamelen + 1; 145 snmp_varlist_add_variable (¬ification_vars, 146 objid_snmptrap, objid_snmptrap_len, 147 ASN_OBJECT_ID, 148 (u_char *) notification_oid, 149 notification_oid_len * sizeof(oid)); 150 151 /* Provided bindings */ 152 for (i = 0; i < trapobjlen; i++) 153 { 154 unsigned int j; 155 oid oid[MAX_OID_LEN]; 156 size_t oid_len, onamelen; 157 u_char *val; 158 size_t val_len; 159 WriteMethod *wm = NULL; 160 struct variable cvp; 161 162 /* Make OID. */ 163 if (trapobj[i].namelen > 0) 164 { 165 /* Columnar object */ 166 onamelen = trapobj[i].namelen; 167 oid_copy (oid, name, namelen); 168 oid_copy (oid + namelen, trapobj[i].name, onamelen); 169 oid_copy (oid + namelen + onamelen, iname, inamelen); 170 oid_len = namelen + onamelen + inamelen; 171 } 172 else 173 { 174 /* Scalar object */ 175 onamelen = trapobj[i].namelen * (-1); 176 oid_copy (oid, name, namelen); 177 oid_copy (oid + namelen, trapobj[i].name, onamelen); 178 oid[onamelen + namelen] = 0; 179 oid_len = namelen + onamelen + 1; 180 } 181 182 /* Locate the appropriate function and type in the MIB registry. */ 183 for (j = 0; j < vp_len; j++) 184 { 185 if (oid_compare (trapobj[i].name, onamelen, vp[j].name, vp[j].namelen) != 0) 186 continue; 187 /* We found the appropriate variable in the MIB registry. */ 188 oid_copy(cvp.name, name, namelen); 189 oid_copy(cvp.name + namelen, vp[j].name, vp[j].namelen); 190 cvp.namelen = namelen + vp[j].namelen; 191 cvp.type = vp[j].type; 192 cvp.magic = vp[j].magic; 193 cvp.acl = vp[j].acl; 194 cvp.findVar = vp[j].findVar; 195 /* Grab the result. */ 196 val = cvp.findVar (&cvp, oid, &oid_len, 1, &val_len, &wm); 197 if (!val) break; 198 snmp_varlist_add_variable (¬ification_vars, 199 oid, oid_len, 200 vp[j].type, 201 val, 202 val_len); 203 break; 204 } 205 } 206 207 208 send_v2trap (notification_vars); 209 snmp_free_varbind (notification_vars); 210 return 1; 211} 212 213#endif /* HAVE_SNMP */ 214