~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to agent/mibgroup/agentx/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   AgentX utility routines
 
3
 */
 
4
 
 
5
#include <net-snmp/net-snmp-config.h>
 
6
 
 
7
#include <stdio.h>
 
8
#include <errno.h>
 
9
#if HAVE_STDLIB_H
 
10
#include <stdlib.h>
 
11
#endif
 
12
#if HAVE_STRING_H
 
13
#include <string.h>
 
14
#else
 
15
#include <strings.h>
 
16
#endif
 
17
#if HAVE_UNISTD_H
 
18
#include <unistd.h>
 
19
#endif
 
20
#include <sys/types.h>
 
21
#if TIME_WITH_SYS_TIME
 
22
# ifdef WIN32
 
23
#  include <sys/timeb.h>
 
24
# else
 
25
#  include <sys/time.h>
 
26
# endif
 
27
# include <time.h>
 
28
#else
 
29
# if HAVE_SYS_TIME_H
 
30
#  include <sys/time.h>
 
31
# else
 
32
#  include <time.h>
 
33
# endif
 
34
#endif
 
35
 
 
36
#if HAVE_NETINET_IN_H
 
37
#include <netinet/in.h>
 
38
#endif
 
39
#if HAVE_WINSOCK_H
 
40
#include <winsock.h>
 
41
#endif
 
42
 
 
43
#if HAVE_DMALLOC_H
 
44
#include <dmalloc.h>
 
45
#endif
 
46
 
 
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>
 
50
 
 
51
#include "agentx/protocol.h"
 
52
#include "agentx/client.h"
 
53
#include "agentx/subagent.h"
 
54
 
 
55
extern struct timeval starttime;
 
56
 
 
57
        /*
 
58
         * AgentX handling utility routines
 
59
         *
 
60
         * Mostly wrappers round, or re-writes of
 
61
         *   the SNMP equivalents
 
62
         */
 
63
 
 
64
int
 
65
agentx_synch_input(int op,
 
66
                   netsnmp_session * session,
 
67
                   int reqid, netsnmp_pdu *pdu, void *magic)
 
68
{
 
69
    struct synch_state *state = (struct synch_state *) magic;
 
70
    struct timeval  now, diff;
 
71
 
 
72
    if (reqid != state->reqid) {
 
73
        return handle_agentx_packet(op, session, reqid, pdu, magic);
 
74
    }
 
75
 
 
76
    DEBUGMSGTL(("agentx/subagent", "synching input, op 0x%02x\n", op));
 
77
    state->waiting = 0;
 
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;
 
83
 
 
84
            /*
 
85
             * Synchronise sysUpTime with the master agent
 
86
             */
 
87
            gettimeofday(&now, NULL);
 
88
            now.tv_sec--;
 
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;
 
96
                starttime.tv_sec++;
 
97
            }
 
98
        }
 
99
    } else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) {
 
100
        state->pdu = NULL;
 
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);
 
105
    }
 
106
 
 
107
    return 1;
 
108
}
 
109
 
 
110
 
 
111
 
 
112
int
 
113
agentx_synch_response(netsnmp_session * ss, netsnmp_pdu *pdu,
 
114
                      netsnmp_pdu **response)
 
115
{
 
116
    return snmp_synch_response_cb(ss, pdu, response, agentx_synch_input);
 
117
}
 
118
 
 
119
 
 
120
        /*
 
121
         * AgentX PofE convenience functions
 
122
         */
 
123
 
 
124
int
 
125
agentx_open_session(netsnmp_session * ss)
 
126
{
 
127
    netsnmp_pdu    *pdu, *response;
 
128
    extern oid      version_sysoid[];
 
129
 
 
130
    DEBUGMSGTL(("agentx/subagent", "opening session \n"));
 
131
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
132
        return 0;
 
133
    }
 
134
 
 
135
    pdu = snmp_pdu_create(AGENTX_MSG_OPEN);
 
136
    if (pdu == NULL)
 
137
        return 0;
 
138
    pdu->time = 0;
 
139
    snmp_add_var(pdu, version_sysoid, SYSTEM_DOT_MIB_LENGTH,
 
140
                 's', "Net-SNMP AgentX sub-agent");
 
141
 
 
142
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
143
        return 0;
 
144
 
 
145
    if (response->errstat != SNMP_ERR_NOERROR) {
 
146
        snmp_free_pdu(response);
 
147
        return 0;
 
148
    }
 
149
 
 
150
    ss->sessid = response->sessid;
 
151
    snmp_free_pdu(response);
 
152
 
 
153
    DEBUGMSGTL(("agentx/subagent", "open \n"));
 
154
    return 1;
 
155
}
 
156
 
 
157
int
 
158
agentx_close_session(netsnmp_session * ss, int why)
 
159
{
 
160
    netsnmp_pdu    *pdu, *response;
 
161
    DEBUGMSGTL(("agentx/subagent", "closing session\n"));
 
162
 
 
163
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
164
        return 0;
 
165
    }
 
166
 
 
167
    pdu = snmp_pdu_create(AGENTX_MSG_CLOSE);
 
168
    if (pdu == NULL)
 
169
        return 0;
 
170
    pdu->time = 0;
 
171
    pdu->errstat = why;
 
172
    pdu->sessid = ss->sessid;
 
173
 
 
174
    (void) agentx_synch_response(ss, pdu, &response);
 
175
    snmp_free_pdu(response);
 
176
    DEBUGMSGTL(("agentx/subagent", "closed\n"));
 
177
 
 
178
    return 1;
 
179
}
 
180
 
 
181
int
 
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)
 
185
{
 
186
    netsnmp_pdu    *pdu, *response;
 
187
 
 
188
    DEBUGMSGTL(("agentx/subagent", "registering: "));
 
189
    DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
 
190
                      range_ubound));
 
191
    DEBUGMSG(("agentx/subagent", "\n"));
 
192
 
 
193
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
194
        return 0;
 
195
    }
 
196
 
 
197
    pdu = snmp_pdu_create(AGENTX_MSG_REGISTER);
 
198
    if (pdu == NULL) {
 
199
        return 0;
 
200
    }
 
201
    pdu->time = timeout;
 
202
    pdu->priority = priority;
 
203
    pdu->sessid = ss->sessid;
 
204
    pdu->range_subid = range_subid;
 
205
 
 
206
    if (flags & FULLY_QUALIFIED_INSTANCE) {
 
207
        pdu->flags |= AGENTX_MSG_FLAG_INSTANCE_REGISTER;
 
208
    }
 
209
 
 
210
    if (range_subid) {
 
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;
 
214
    } else {
 
215
        snmp_add_null_var(pdu, start, startlen);
 
216
    }
 
217
 
 
218
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS) {
 
219
        DEBUGMSGTL(("agentx/subagent", "registering failed!\n"));
 
220
        return 0;
 
221
    }
 
222
 
 
223
    if (response->errstat != SNMP_ERR_NOERROR) {
 
224
        DEBUGMSGTL(("agentx/subagent", "registering pdu failed: %d!\n",
 
225
                    response->errstat));
 
226
        snmp_free_pdu(response);
 
227
        return 0;
 
228
    }
 
229
 
 
230
    snmp_free_pdu(response);
 
231
    DEBUGMSGTL(("agentx/subagent", "registered\n"));
 
232
    return 1;
 
233
}
 
234
 
 
235
int
 
236
agentx_unregister(netsnmp_session * ss, oid start[], size_t startlen,
 
237
                  int priority, int range_subid, oid range_ubound)
 
238
{
 
239
    netsnmp_pdu    *pdu, *response;
 
240
 
 
241
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
242
        return 0;
 
243
    }
 
244
 
 
245
    DEBUGMSGTL(("agentx/subagent", "unregistering: "));
 
246
    DEBUGMSGOIDRANGE(("agentx/subagent", start, startlen, range_subid,
 
247
                      range_ubound));
 
248
    DEBUGMSG(("agentx/subagent", "\n"));
 
249
    pdu = snmp_pdu_create(AGENTX_MSG_UNREGISTER);
 
250
    if (pdu == NULL) {
 
251
        return 0;
 
252
    }
 
253
    pdu->time = 0;
 
254
    pdu->priority = priority;
 
255
    pdu->sessid = ss->sessid;
 
256
    pdu->range_subid = range_subid;
 
257
    if (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;
 
261
    } else {
 
262
        snmp_add_null_var(pdu, start, startlen);
 
263
    }
 
264
 
 
265
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
266
        return 0;
 
267
 
 
268
    if (response->errstat != SNMP_ERR_NOERROR) {
 
269
        snmp_free_pdu(response);
 
270
        return 0;
 
271
    }
 
272
 
 
273
    snmp_free_pdu(response);
 
274
    DEBUGMSGTL(("agentx/subagent", "unregistered\n"));
 
275
    return 1;
 
276
}
 
277
 
 
278
netsnmp_variable_list *
 
279
agentx_register_index(netsnmp_session * ss,
 
280
                      netsnmp_variable_list * varbind, int flags)
 
281
{
 
282
    netsnmp_pdu    *pdu, *response;
 
283
    netsnmp_variable_list *varbind2;
 
284
 
 
285
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
286
        return NULL;
 
287
    }
 
288
 
 
289
    /*
 
290
     * Make a copy of the index request varbind
 
291
     *    for the AgentX request PDU
 
292
     *    (since the pdu structure will be freed)
 
293
     */
 
294
    varbind2 =
 
295
        (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
 
296
    if (varbind2 == NULL)
 
297
        return NULL;
 
298
    if (snmp_clone_var(varbind, varbind2)) {
 
299
        snmp_free_varbind(varbind2);
 
300
        return NULL;
 
301
    }
 
302
    if (varbind2->val.string == NULL)
 
303
        varbind2->val.string = varbind2->buf;   /* ensure it points somewhere */
 
304
 
 
305
    pdu = snmp_pdu_create(AGENTX_MSG_INDEX_ALLOCATE);
 
306
    if (pdu == NULL) {
 
307
        snmp_free_varbind(varbind2);
 
308
        return NULL;
 
309
    }
 
310
    pdu->time = 0;
 
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;
 
316
 
 
317
    /*
 
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.
 
326
     */
 
327
    pdu->variables = varbind2;
 
328
 
 
329
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
330
        return NULL;
 
331
 
 
332
    if (response->errstat != SNMP_ERR_NOERROR) {
 
333
        snmp_free_pdu(response);
 
334
        return NULL;
 
335
    }
 
336
 
 
337
    /*
 
338
     * Unlink the (single) response varbind to return
 
339
     *  to the main driving index request routine.
 
340
     *
 
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 :-)
 
348
     */
 
349
    varbind2 = response->variables;
 
350
    response->variables = NULL;
 
351
    snmp_free_pdu(response);
 
352
    return varbind2;
 
353
}
 
354
 
 
355
int
 
356
agentx_unregister_index(netsnmp_session * ss,
 
357
                        netsnmp_variable_list * varbind)
 
358
{
 
359
    netsnmp_pdu    *pdu, *response;
 
360
    netsnmp_variable_list *varbind2;
 
361
 
 
362
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
363
        return -1;
 
364
    }
 
365
 
 
366
    /*
 
367
     * Make a copy of the index request varbind
 
368
     *    for the AgentX request PDU
 
369
     *    (since the pdu structure will be freed)
 
370
     */
 
371
    varbind2 =
 
372
        (netsnmp_variable_list *) malloc(sizeof(netsnmp_variable_list));
 
373
    if (varbind2 == NULL)
 
374
        return -1;
 
375
    if (snmp_clone_var(varbind, varbind2)) {
 
376
        snmp_free_varbind(varbind2);
 
377
        return -1;
 
378
    }
 
379
 
 
380
    pdu = snmp_pdu_create(AGENTX_MSG_INDEX_DEALLOCATE);
 
381
    if (pdu == NULL) {
 
382
        snmp_free_varbind(varbind2);
 
383
        return -1;
 
384
    }
 
385
    pdu->time = 0;
 
386
    pdu->sessid = ss->sessid;
 
387
 
 
388
    /*
 
389
     *  Just send a single index release varbind.
 
390
     *      (as above)
 
391
     */
 
392
    pdu->variables = varbind2;
 
393
 
 
394
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
395
        return -1;
 
396
 
 
397
    if (response->errstat != SNMP_ERR_NOERROR) {
 
398
        snmp_free_pdu(response);
 
399
        return -1;              /* XXX - say why */
 
400
    }
 
401
 
 
402
    snmp_free_pdu(response);
 
403
    return SNMP_ERR_NOERROR;
 
404
}
 
405
 
 
406
int
 
407
agentx_add_agentcaps(netsnmp_session * ss,
 
408
                     oid * agent_cap, size_t agent_caplen,
 
409
                     const char *descr)
 
410
{
 
411
    netsnmp_pdu    *pdu, *response;
 
412
 
 
413
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
414
        return 0;
 
415
    }
 
416
 
 
417
    pdu = snmp_pdu_create(AGENTX_MSG_ADD_AGENT_CAPS);
 
418
    if (pdu == NULL)
 
419
        return 0;
 
420
    pdu->time = 0;
 
421
    pdu->sessid = ss->sessid;
 
422
    snmp_add_var(pdu, agent_cap, agent_caplen, 's', descr);
 
423
 
 
424
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
425
        return 0;
 
426
 
 
427
    if (response->errstat != SNMP_ERR_NOERROR) {
 
428
        snmp_free_pdu(response);
 
429
        return 0;
 
430
    }
 
431
 
 
432
    snmp_free_pdu(response);
 
433
    return 1;
 
434
}
 
435
 
 
436
int
 
437
agentx_remove_agentcaps(netsnmp_session * ss,
 
438
                        oid * agent_cap, size_t agent_caplen)
 
439
{
 
440
    netsnmp_pdu    *pdu, *response;
 
441
 
 
442
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
443
        return 0;
 
444
    }
 
445
 
 
446
    pdu = snmp_pdu_create(AGENTX_MSG_REMOVE_AGENT_CAPS);
 
447
    if (pdu == NULL)
 
448
        return 0;
 
449
    pdu->time = 0;
 
450
    pdu->sessid = ss->sessid;
 
451
    snmp_add_null_var(pdu, agent_cap, agent_caplen);
 
452
 
 
453
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
454
        return 0;
 
455
 
 
456
    if (response->errstat != SNMP_ERR_NOERROR) {
 
457
        snmp_free_pdu(response);
 
458
        return 0;
 
459
    }
 
460
 
 
461
    snmp_free_pdu(response);
 
462
    return 1;
 
463
}
 
464
 
 
465
int
 
466
agentx_send_ping(netsnmp_session * ss)
 
467
{
 
468
    netsnmp_pdu    *pdu, *response;
 
469
 
 
470
    if (ss == NULL || !IS_AGENTX_VERSION(ss->version)) {
 
471
        return 0;
 
472
    }
 
473
 
 
474
    pdu = snmp_pdu_create(AGENTX_MSG_PING);
 
475
    if (pdu == NULL)
 
476
        return 0;
 
477
    pdu->time = 0;
 
478
    pdu->sessid = ss->sessid;
 
479
 
 
480
    if (agentx_synch_response(ss, pdu, &response) != STAT_SUCCESS)
 
481
        return 0;
 
482
 
 
483
    if (response->errstat != SNMP_ERR_NOERROR) {
 
484
        snmp_free_pdu(response);
 
485
        return 0;
 
486
    }
 
487
 
 
488
    snmp_free_pdu(response);
 
489
    return 1;
 
490
}