]>
git.proxmox.com Git - mirror_frr.git/blob - lib/agentx.c
d058779aff02202bdd8688e0ada62292cfc7f341
2 * Copyright (C) 2012 Vincent Bernat <bernat@luffy.cx>
4 * This file is part of GNU Zebra.
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
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.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <net-snmp/net-snmp-config.h>
25 #include <net-snmp/net-snmp-includes.h>
26 #include <net-snmp/agent/net-snmp-agent-includes.h>
27 #include <net-snmp/agent/snmp_vars.h>
35 static int agentx_enabled
= 0;
37 static struct thread_master
*agentx_tm
;
38 static struct thread
*timeout_thr
= NULL
;
39 static struct list
*events
= NULL
;
41 static void agentx_events_update(void);
44 agentx_timeout(struct thread
*t
)
50 netsnmp_check_outstanding_agent_requests ();
51 agentx_events_update ();
56 agentx_read(struct thread
*t
)
59 struct listnode
*ln
= THREAD_ARG (t
);
60 list_delete_node (events
, ln
);
63 FD_SET (THREAD_FD (t
), &fds
);
66 netsnmp_check_outstanding_agent_requests ();
67 agentx_events_update ();
72 agentx_events_update(void)
76 struct timeval timeout
= { .tv_sec
= 0, .tv_usec
= 0 };
82 THREAD_OFF (timeout_thr
);
85 snmp_select_info (&maxfd
, &fds
, &timeout
, &block
);
89 thread_add_timer_tv(agentx_tm
, agentx_timeout
, NULL
, &timeout
,
93 ln
= listhead (events
);
94 thr
= ln
? listgetdata (ln
) : NULL
;
95 thr_fd
= thr
? THREAD_FD (thr
) : -1;
97 /* "two-pointer" / two-list simultaneous iteration
98 * ln/thr/thr_fd point to the next existing event listener to hit while
99 * fd counts to catch up */
100 for (fd
= 0; fd
< maxfd
; fd
++)
105 struct listnode
*nextln
= listnextnode (ln
);
106 if (!FD_ISSET (fd
, &fds
))
109 list_delete_node (events
, ln
);
112 thr
= ln
? listgetdata (ln
) : NULL
;
113 thr_fd
= thr
? THREAD_FD (thr
) : -1;
115 /* need listener, but haven't hit one where it would be */
116 else if (FD_ISSET (fd
, &fds
))
118 struct listnode
*newln
;
120 thread_add_read(agentx_tm
, agentx_read
, NULL
, fd
, &thr
);
121 newln
= listnode_add_before (events
, ln
, thr
);
126 /* leftover event listeners at this point have fd > maxfd, delete them */
129 struct listnode
*nextln
= listnextnode (ln
);
130 thread_cancel (listgetdata (ln
));
131 list_delete_node (events
, ln
);
137 static struct cmd_node agentx_node
=
140 "", /* AgentX has no interface. */
144 /* Logging NetSNMP messages */
146 agentx_log_callback(int major
, int minor
,
147 void *serverarg
, void *clientarg
)
149 struct snmp_log_message
*slm
= (struct snmp_log_message
*)serverarg
;
150 char *msg
= XSTRDUP(MTYPE_TMP
, slm
->msg
);
151 if (msg
) msg
[strlen(msg
)-1] = '\0';
152 switch (slm
->priority
)
154 case LOG_EMERG
: zlog_err ("snmp[emerg]: %s", msg
?msg
:slm
->msg
); break;
155 case LOG_ALERT
: zlog_err ("snmp[alert]: %s", msg
?msg
:slm
->msg
); break;
156 case LOG_CRIT
: zlog_err ("snmp[crit]: %s", msg
?msg
:slm
->msg
); break;
157 case LOG_ERR
: zlog_err ("snmp[err]: %s", msg
?msg
:slm
->msg
); break;
158 case LOG_WARNING
: zlog_warn ("snmp[warning]: %s", msg
?msg
:slm
->msg
); break;
159 case LOG_NOTICE
: zlog_notice("snmp[notice]: %s", msg
?msg
:slm
->msg
); break;
160 case LOG_INFO
: zlog_info ("snmp[info]: %s", msg
?msg
:slm
->msg
); break;
161 case LOG_DEBUG
: zlog_debug ("snmp[debug]: %s", msg
?msg
:slm
->msg
); break;
163 XFREE(MTYPE_TMP
, msg
);
164 return SNMP_ERR_NOERROR
;
168 config_write_agentx (struct vty
*vty
)
171 vty_outln (vty
, "agentx");
175 DEFUN (agentx_enable
,
178 "SNMP AgentX protocol settings\n")
182 init_snmp(FRR_SMUX_NAME
);
184 agentx_events_update ();
188 vty_outln (vty
, "SNMP AgentX already enabled");
196 "SNMP AgentX protocol settings\n")
198 if (!agentx_enabled
) return CMD_SUCCESS
;
199 vty_outln (vty
, "SNMP AgentX support cannot be disabled once enabled");
204 smux_init (struct thread_master
*tm
)
208 netsnmp_enable_subagent ();
210 snmp_enable_calllog ();
211 snmp_register_callback (SNMP_CALLBACK_LIBRARY
,
212 SNMP_CALLBACK_LOGGING
,
215 init_agent (FRR_SMUX_NAME
);
217 install_node (&agentx_node
, config_write_agentx
);
218 install_element (CONFIG_NODE
, &agentx_enable_cmd
);
219 install_element (CONFIG_NODE
, &no_agentx_cmd
);
223 smux_register_mib (const char *descr
, struct variable
*var
,
224 size_t width
, int num
,
225 oid name
[], size_t namelen
)
227 register_mib (descr
, var
, width
, num
, name
, namelen
);
231 smux_trap (struct variable
*vp
, size_t vp_len
,
232 const oid
*ename
, size_t enamelen
,
233 const oid
*name
, size_t namelen
,
234 const oid
*iname
, size_t inamelen
,
235 const struct trap_object
*trapobj
, size_t trapobjlen
,
238 oid objid_snmptrap
[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
239 size_t objid_snmptrap_len
= sizeof objid_snmptrap
/ sizeof (oid
);
240 oid notification_oid
[MAX_OID_LEN
];
241 size_t notification_oid_len
;
244 netsnmp_variable_list
*notification_vars
= NULL
;
245 if (!agentx_enabled
) return 0;
248 oid_copy (notification_oid
, ename
, enamelen
);
249 notification_oid
[enamelen
] = sptrap
;
250 notification_oid_len
= enamelen
+ 1;
251 snmp_varlist_add_variable (¬ification_vars
,
252 objid_snmptrap
, objid_snmptrap_len
,
254 (u_char
*) notification_oid
,
255 notification_oid_len
* sizeof(oid
));
257 /* Provided bindings */
258 for (i
= 0; i
< trapobjlen
; i
++)
261 oid oid
[MAX_OID_LEN
];
262 size_t oid_len
, onamelen
;
265 WriteMethod
*wm
= NULL
;
269 if (trapobj
[i
].namelen
> 0)
271 /* Columnar object */
272 onamelen
= trapobj
[i
].namelen
;
273 oid_copy (oid
, name
, namelen
);
274 oid_copy (oid
+ namelen
, trapobj
[i
].name
, onamelen
);
275 oid_copy (oid
+ namelen
+ onamelen
, iname
, inamelen
);
276 oid_len
= namelen
+ onamelen
+ inamelen
;
281 onamelen
= trapobj
[i
].namelen
* (-1);
282 oid_copy (oid
, name
, namelen
);
283 oid_copy (oid
+ namelen
, trapobj
[i
].name
, onamelen
);
284 oid
[onamelen
+ namelen
] = 0;
285 oid_len
= namelen
+ onamelen
+ 1;
288 /* Locate the appropriate function and type in the MIB registry. */
289 for (j
= 0; j
< vp_len
; j
++)
291 if (oid_compare (trapobj
[i
].name
, onamelen
, vp
[j
].name
, vp
[j
].namelen
) != 0)
293 /* We found the appropriate variable in the MIB registry. */
294 oid_copy(cvp
.name
, name
, namelen
);
295 oid_copy(cvp
.name
+ namelen
, vp
[j
].name
, vp
[j
].namelen
);
296 cvp
.namelen
= namelen
+ vp
[j
].namelen
;
297 cvp
.type
= vp
[j
].type
;
298 cvp
.magic
= vp
[j
].magic
;
300 cvp
.findVar
= vp
[j
].findVar
;
301 /* Grab the result. */
302 val
= cvp
.findVar (&cvp
, oid
, &oid_len
, 1, &val_len
, &wm
);
304 snmp_varlist_add_variable (¬ification_vars
,
314 send_v2trap (notification_vars
);
315 snmp_free_varbind (notification_vars
);
316 agentx_events_update ();
320 #endif /* SNMP_AGENTX */