]>
git.proxmox.com Git - mirror_frr.git/blob - lib/agentx.c
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
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
25 #include <net-snmp/net-snmp-config.h>
26 #include <net-snmp/net-snmp-includes.h>
27 #include <net-snmp/agent/net-snmp-agent-includes.h>
28 #include <net-snmp/agent/snmp_vars.h>
36 static int agentx_enabled
= 0;
38 static struct thread_master
*agentx_tm
;
39 static struct thread
*timeout_thr
= NULL
;
40 static struct list
*events
= NULL
;
42 static void agentx_events_update(void);
44 static int agentx_timeout(struct thread
*t
)
50 netsnmp_check_outstanding_agent_requests();
51 agentx_events_update();
55 static int agentx_read(struct thread
*t
)
58 struct listnode
*ln
= THREAD_ARG(t
);
59 list_delete_node(events
, ln
);
62 FD_SET(THREAD_FD(t
), &fds
);
65 netsnmp_check_outstanding_agent_requests();
66 agentx_events_update();
70 static void agentx_events_update(void)
74 struct timeval timeout
= {.tv_sec
= 0, .tv_usec
= 0};
80 THREAD_OFF(timeout_thr
);
83 snmp_select_info(&maxfd
, &fds
, &timeout
, &block
);
86 timeout_thr
= thread_add_timer_tv(agentx_tm
, agentx_timeout
,
89 ln
= listhead(events
);
90 thr
= ln
? listgetdata(ln
) : NULL
;
91 thr_fd
= thr
? THREAD_FD(thr
) : -1;
93 /* "two-pointer" / two-list simultaneous iteration
94 * ln/thr/thr_fd point to the next existing event listener to hit while
95 * fd counts to catch up */
96 for (fd
= 0; fd
< maxfd
; fd
++) {
99 struct listnode
*nextln
= listnextnode(ln
);
100 if (!FD_ISSET(fd
, &fds
)) {
102 list_delete_node(events
, ln
);
105 thr
= ln
? listgetdata(ln
) : NULL
;
106 thr_fd
= thr
? THREAD_FD(thr
) : -1;
108 /* need listener, but haven't hit one where it would be */
109 else if (FD_ISSET(fd
, &fds
)) {
110 struct listnode
*newln
;
111 thr
= thread_add_read(agentx_tm
, agentx_read
, NULL
, fd
);
112 newln
= listnode_add_before(events
, ln
, thr
);
117 /* leftover event listeners at this point have fd > maxfd, delete them
120 struct listnode
*nextln
= listnextnode(ln
);
121 thread_cancel(listgetdata(ln
));
122 list_delete_node(events
, ln
);
128 static struct cmd_node agentx_node
= {
129 SMUX_NODE
, "" /* AgentX has no interface. */
132 /* Logging NetSNMP messages */
133 static int agentx_log_callback(int major
, int minor
, void *serverarg
,
136 struct snmp_log_message
*slm
= (struct snmp_log_message
*)serverarg
;
137 char *msg
= XSTRDUP(MTYPE_TMP
, slm
->msg
);
139 msg
[strlen(msg
) - 1] = '\0';
140 switch (slm
->priority
) {
142 zlog_err("snmp[emerg]: %s", msg
? msg
: slm
->msg
);
145 zlog_err("snmp[alert]: %s", msg
? msg
: slm
->msg
);
148 zlog_err("snmp[crit]: %s", msg
? msg
: slm
->msg
);
151 zlog_err("snmp[err]: %s", msg
? msg
: slm
->msg
);
154 zlog_warn("snmp[warning]: %s", msg
? msg
: slm
->msg
);
157 zlog_notice("snmp[notice]: %s", msg
? msg
: slm
->msg
);
160 zlog_info("snmp[info]: %s", msg
? msg
: slm
->msg
);
163 zlog_debug("snmp[debug]: %s", msg
? msg
: slm
->msg
);
166 XFREE(MTYPE_TMP
, msg
);
167 return SNMP_ERR_NOERROR
;
170 static int config_write_agentx(struct vty
*vty
)
173 vty_out(vty
, "agentx%s", VTY_NEWLINE
);
177 DEFUN (agentx_enable
,
180 "SNMP AgentX protocol settings\n"
181 "SNMP AgentX settings\n")
183 if (!agentx_enabled
) {
184 init_snmp(FRR_SMUX_NAME
);
186 agentx_events_update();
190 vty_out(vty
, "SNMP AgentX already enabled%s", VTY_NEWLINE
);
198 "SNMP AgentX protocol settings\n"
199 "SNMP AgentX settings\n")
203 vty_out(vty
, "SNMP AgentX support cannot be disabled once enabled%s",
208 void smux_init(struct thread_master
*tm
)
212 netsnmp_enable_subagent();
214 snmp_enable_calllog();
215 snmp_register_callback(SNMP_CALLBACK_LIBRARY
, SNMP_CALLBACK_LOGGING
,
216 agentx_log_callback
, NULL
);
217 init_agent(FRR_SMUX_NAME
);
219 install_node(&agentx_node
, config_write_agentx
);
220 install_element(CONFIG_NODE
, &agentx_enable_cmd
);
221 install_element(CONFIG_NODE
, &no_agentx_cmd
);
224 void smux_register_mib(const char *descr
, struct variable
*var
, size_t width
,
225 int num
, oid name
[], size_t namelen
)
227 register_mib(descr
, var
, width
, num
, name
, namelen
);
230 int smux_trap(struct variable
*vp
, size_t vp_len
, const oid
*ename
,
231 size_t enamelen
, const oid
*name
, size_t namelen
,
232 const oid
*iname
, size_t inamelen
,
233 const struct trap_object
*trapobj
, size_t trapobjlen
,
236 oid objid_snmptrap
[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};
237 size_t objid_snmptrap_len
= sizeof objid_snmptrap
/ sizeof(oid
);
238 oid notification_oid
[MAX_OID_LEN
];
239 size_t notification_oid_len
;
242 netsnmp_variable_list
*notification_vars
= NULL
;
247 oid_copy(notification_oid
, ename
, enamelen
);
248 notification_oid
[enamelen
] = sptrap
;
249 notification_oid_len
= enamelen
+ 1;
250 snmp_varlist_add_variable(¬ification_vars
, objid_snmptrap
,
251 objid_snmptrap_len
, ASN_OBJECT_ID
,
252 (u_char
*)notification_oid
,
253 notification_oid_len
* sizeof(oid
));
255 /* Provided bindings */
256 for (i
= 0; i
< trapobjlen
; i
++) {
258 oid oid
[MAX_OID_LEN
];
259 size_t oid_len
, onamelen
;
262 WriteMethod
*wm
= NULL
;
266 if (trapobj
[i
].namelen
> 0) {
267 /* Columnar object */
268 onamelen
= trapobj
[i
].namelen
;
269 oid_copy(oid
, name
, namelen
);
270 oid_copy(oid
+ namelen
, trapobj
[i
].name
, onamelen
);
271 oid_copy(oid
+ namelen
+ onamelen
, iname
, inamelen
);
272 oid_len
= namelen
+ onamelen
+ inamelen
;
275 onamelen
= trapobj
[i
].namelen
* (-1);
276 oid_copy(oid
, name
, namelen
);
277 oid_copy(oid
+ namelen
, trapobj
[i
].name
, onamelen
);
278 oid
[onamelen
+ namelen
] = 0;
279 oid_len
= namelen
+ onamelen
+ 1;
282 /* Locate the appropriate function and type in the MIB registry.
284 for (j
= 0; j
< vp_len
; j
++) {
285 if (oid_compare(trapobj
[i
].name
, onamelen
, vp
[j
].name
,
289 /* We found the appropriate variable in the MIB
291 oid_copy(cvp
.name
, name
, namelen
);
292 oid_copy(cvp
.name
+ namelen
, vp
[j
].name
, vp
[j
].namelen
);
293 cvp
.namelen
= namelen
+ vp
[j
].namelen
;
294 cvp
.type
= vp
[j
].type
;
295 cvp
.magic
= vp
[j
].magic
;
297 cvp
.findVar
= vp
[j
].findVar
;
298 /* Grab the result. */
299 val
= cvp
.findVar(&cvp
, oid
, &oid_len
, 1, &val_len
,
303 snmp_varlist_add_variable(¬ification_vars
, oid
,
304 oid_len
, vp
[j
].type
, val
,
311 send_v2trap(notification_vars
);
312 snmp_free_varbind(notification_vars
);
313 agentx_events_update();
317 #endif /* SNMP_AGENTX */