2
* AgentX utility routines
5
#include <net-snmp/net-snmp-config.h>
20
#include <sys/types.h>
21
#if TIME_WITH_SYS_TIME
23
# include <sys/timeb.h>
25
# include <sys/time.h>
30
# include <sys/time.h>
37
#include <netinet/in.h>
47
#include <net-snmp/net-snmp-includes.h>
48
#include <net-snmp/agent/net-snmp-agent-includes.h>
49
#include <net-snmp/agent/agent_index.h>
51
#include "agentx/protocol.h"
52
#include "agentx/client.h"
53
#include "agentx/subagent.h"
55
extern struct timeval starttime;
58
* AgentX handling utility routines
60
* Mostly wrappers round, or re-writes of
61
* the SNMP equivalents
65
agentx_synch_input(int op,
66
netsnmp_session * session,
67
int reqid, netsnmp_pdu *pdu, void *magic)
69
struct synch_state *state = (struct synch_state *) magic;
70
struct timeval now, diff;
72
if (reqid != state->reqid) {
73
return handle_agentx_packet(op, session, reqid, pdu, magic);
76
DEBUGMSGTL(("agentx/subagent", "synching input, op 0x%02x\n", op));
78
if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
79
if (pdu->command == AGENTX_MSG_RESPONSE) {
80
state->pdu = snmp_clone_pdu(pdu);
81
state->status = STAT_SUCCESS;
82
session->s_snmp_errno = SNMPERR_SUCCESS;
85
* Synchronise sysUpTime with the master agent
87
gettimeofday(&now, NULL);
89
now.tv_usec += 1000000L;
90
diff.tv_sec = pdu->time / 100;
91
diff.tv_usec = (pdu->time - (diff.tv_sec * 100)) * 10000;
92
starttime.tv_sec = now.tv_sec - diff.tv_sec;
93
starttime.tv_usec = now.tv_usec - diff.tv_usec;
94
if (starttime.tv_usec > 1000000L) {
95
starttime.tv_usec -= 1000000L;
99
} else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) {
101
state->status = STAT_TIMEOUT;
102
session->s_snmp_errno = SNMPERR_TIMEOUT;
103
} else if (op == NETSNMP_CALLBACK_OP_DISCONNECT) {
104
return handle_agentx_packet(op, session, reqid, pdu, magic);
113
agentx_synch_response(netsnmp_session * ss, netsnmp_pdu *pdu,
114
netsnmp_pdu **response)
116
return snmp_synch_response_cb(ss, pdu, response, agentx_synch_input);
121
* AgentX PofE convenience functions
125
agentx_open_session(netsnmp_session * ss)
127
netsnmp_pdu *pdu, *response;
128
extern oid version_sysoid[];
130
DEBUGMSGTL(("agentx/subagent", "opening session \n"));
131
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
135
pdu = snmp_pdu_create(AGENTX_MSG_OPEN);
139
snmp_add_var(pdu, version_sysoid, SYSTEM_DOT_MIB_LENGTH,
140
's', "Net-SNMP AgentX sub-agent");
142
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
145
if (response->errstat != SNMP_ERR_NOERROR) {
146
snmp_free_pdu(response);
150
ss->sessid = response->sessid;
151
snmp_free_pdu(response);
153
DEBUGMSGTL(("agentx/subagent", "open \n"));
158
agentx_close_session(netsnmp_session * ss, int why)
160
netsnmp_pdu *pdu, *response;
161
DEBUGMSGTL(("agentx/subagent", "closing session\n"));
163
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
167
pdu = snmp_pdu_create(AGENTX_MSG_CLOSE);
172
pdu->sessid = ss->sessid;
174
(void) agentx_synch_response(ss, pdu, &response);
175
snmp_free_pdu(response);
176
DEBUGMSGTL(("agentx/subagent", "closed\n"));
182
agentx_register(netsnmp_session * ss, oid start[], size_t startlen,
183
int priority, int range_subid, oid range_ubound,
184
int timeout, u_char flags)
186
netsnmp_pdu *pdu, *response;
188
DEBUGMSGTL(("agentx/subagent", "registering: "));
189
DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
191
DEBUGMSG(("agentx/subagent", "\n"));
193
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
197
pdu = snmp_pdu_create(AGENTX_MSG_REGISTER);
202
pdu->priority = priority;
203
pdu->sessid = ss->sessid;
204
pdu->range_subid = range_subid;
206
if (flags & FULLY_QUALIFIED_INSTANCE) {
207
pdu->flags |= AGENTX_MSG_FLAG_INSTANCE_REGISTER;
211
snmp_pdu_add_variable(pdu, start, startlen, ASN_OBJECT_ID,
212
(u_char *) start, startlen * sizeof(oid));
213
pdu->variables->val.objid[range_subid - 1] = range_ubound;
215
snmp_add_null_var(pdu, start, startlen);
218
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS) {
219
DEBUGMSGTL(("agentx/subagent", "registering failed!\n"));
223
if (response->errstat != SNMP_ERR_NOERROR) {
224
DEBUGMSGTL(("agentx/subagent", "registering pdu failed: %d!\n",
226
snmp_free_pdu(response);
230
snmp_free_pdu(response);
231
DEBUGMSGTL(("agentx/subagent", "registered\n"));
236
agentx_unregister(netsnmp_session * ss, oid start[], size_t startlen,
237
int priority, int range_subid, oid range_ubound)
239
netsnmp_pdu *pdu, *response;
241
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
245
DEBUGMSGTL(("agentx/subagent", "unregistering: "));
246
DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
248
DEBUGMSG(("agentx/subagent", "\n"));
249
pdu = snmp_pdu_create(AGENTX_MSG_UNREGISTER);
254
pdu->priority = priority;
255
pdu->sessid = ss->sessid;
256
pdu->range_subid = range_subid;
258
snmp_pdu_add_variable(pdu, start, startlen, ASN_OBJECT_ID,
259
(u_char *) start, startlen * sizeof(oid));
260
pdu->variables->val.objid[range_subid - 1] = range_ubound;
262
snmp_add_null_var(pdu, start, startlen);
265
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
268
if (response->errstat != SNMP_ERR_NOERROR) {
269
snmp_free_pdu(response);
273
snmp_free_pdu(response);
274
DEBUGMSGTL(("agentx/subagent", "unregistered\n"));
278
netsnmp_variable_list *
279
agentx_register_index(netsnmp_session * ss,
280
netsnmp_variable_list * varbind, int flags)
282
netsnmp_pdu *pdu, *response;
283
netsnmp_variable_list *varbind2;
285
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
290
* Make a copy of the index request varbind
291
* for the AgentX request PDU
292
* (since the pdu structure will be freed)
295
(netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
296
if (varbind2 == NULL)
298
if (snmp_clone_var(varbind, varbind2)) {
299
snmp_free_varbind(varbind2);
302
if (varbind2->val.string == NULL)
303
varbind2->val.string = varbind2->buf; /* ensure it points somewhere */
305
pdu = snmp_pdu_create(AGENTX_MSG_INDEX_ALLOCATE);
307
snmp_free_varbind(varbind2);
311
pdu->sessid = ss->sessid;
312
if (flags == ALLOCATE_ANY_INDEX)
313
pdu->flags |= AGENTX_MSG_FLAG_ANY_INSTANCE;
314
if (flags == ALLOCATE_NEW_INDEX)
315
pdu->flags |= AGENTX_MSG_FLAG_NEW_INSTANCE;
318
* Just send a single index request varbind.
319
* Although the AgentX protocol supports
320
* multiple index allocations in a single
321
* request, the model used in the net-snmp agent
322
* doesn't currently take advantage of this.
323
* I believe this is our prerogative - just as
324
* long as the master side Index request handler
325
* can cope with multiple index requests.
327
pdu->variables = varbind2;
329
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
332
if (response->errstat != SNMP_ERR_NOERROR) {
333
snmp_free_pdu(response);
338
* Unlink the (single) response varbind to return
339
* to the main driving index request routine.
341
* This is a memory leak, as nothing will ever
342
* release this varbind. If this becomes a problem,
343
* we'll need to keep a list of these here, and
344
* free the memory in the "index release" routine.
345
* But the master side never frees these either (by
346
* design, since it still needs them), so expecting
347
* the subagent to is discrimination, pure & simple :-)
349
varbind2 = response->variables;
350
response->variables = NULL;
351
snmp_free_pdu(response);
356
agentx_unregister_index(netsnmp_session * ss,
357
netsnmp_variable_list * varbind)
359
netsnmp_pdu *pdu, *response;
360
netsnmp_variable_list *varbind2;
362
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
367
* Make a copy of the index request varbind
368
* for the AgentX request PDU
369
* (since the pdu structure will be freed)
372
(netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
373
if (varbind2 == NULL)
375
if (snmp_clone_var(varbind, varbind2)) {
376
snmp_free_varbind(varbind2);
380
pdu = snmp_pdu_create(AGENTX_MSG_INDEX_DEALLOCATE);
382
snmp_free_varbind(varbind2);
386
pdu->sessid = ss->sessid;
389
* Just send a single index release varbind.
392
pdu->variables = varbind2;
394
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
397
if (response->errstat != SNMP_ERR_NOERROR) {
398
snmp_free_pdu(response);
399
return -1; /* XXX - say why */
402
snmp_free_pdu(response);
403
return SNMP_ERR_NOERROR;
407
agentx_add_agentcaps(netsnmp_session * ss,
408
oid * agent_cap, size_t agent_caplen,
411
netsnmp_pdu *pdu, *response;
413
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
417
pdu = snmp_pdu_create(AGENTX_MSG_ADD_AGENT_CAPS);
421
pdu->sessid = ss->sessid;
422
snmp_add_var(pdu, agent_cap, agent_caplen, 's', descr);
424
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
427
if (response->errstat != SNMP_ERR_NOERROR) {
428
snmp_free_pdu(response);
432
snmp_free_pdu(response);
437
agentx_remove_agentcaps(netsnmp_session * ss,
438
oid * agent_cap, size_t agent_caplen)
440
netsnmp_pdu *pdu, *response;
442
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
446
pdu = snmp_pdu_create(AGENTX_MSG_REMOVE_AGENT_CAPS);
450
pdu->sessid = ss->sessid;
451
snmp_add_null_var(pdu, agent_cap, agent_caplen);
453
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
456
if (response->errstat != SNMP_ERR_NOERROR) {
457
snmp_free_pdu(response);
461
snmp_free_pdu(response);
466
agentx_send_ping(netsnmp_session * ss)
468
netsnmp_pdu *pdu, *response;
470
if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
474
pdu = snmp_pdu_create(AGENTX_MSG_PING);
478
pdu->sessid = ss->sessid;
480
if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
483
if (response->errstat != SNMP_ERR_NOERROR) {
484
snmp_free_pdu(response);
488
snmp_free_pdu(response);