~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to agent/mibgroup/examples/delayed_instance.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
/**  @example delayed_instance.c
 
2
 *  This example implements the netSnmpExampleSleeper object.
 
3
 *
 
4
 *  It demonstrates 2 things:
 
5
 *
 
6
 *  - The instance helper, which is a way of registering an exact OID
 
7
 *    such that GENEXT requests are handled entirely by the helper.
 
8
 *
 
9
 *  - how to implement objects which normally would block the agent as
 
10
 *    it waits for external events in such a way that the agent can
 
11
 *    continue responding to other requests while this implementation
 
12
 *    waits.
 
13
 *
 
14
 *  - Added bonus: normally the nsTransactionTable is empty, since
 
15
 *    there aren't any outstanding requests generally.  When accessed,
 
16
 *    this module will create some however.  Try setting
 
17
 *    netSnmpExampleSleeper.0 to 10 and then accessing it (use
 
18
 *    "snmpget -t 15 ..." to access it), and then walk the
 
19
 *    nsTransactionTable from another shell to see that not only is
 
20
 *    the walk not blocked, but that the nsTransactionTable is not
 
21
 *    empty.
 
22
 *
 
23
 */
 
24
 
 
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
 
 
29
#include "delayed_instance.h"
 
30
 
 
31
static u_long   delay_time = 1;
 
32
 
 
33
void
 
34
init_delayed_instance(void)
 
35
{
 
36
    static oid      my_delayed_oid[] =
 
37
        { 1, 3, 6, 1, 4, 1, 8072, 2, 1, 2, 0 };
 
38
    /*
 
39
     * delayed handler test
 
40
     */
 
41
    netsnmp_handler_registration *my_test;
 
42
 
 
43
    my_test =
 
44
        netsnmp_create_handler_registration("delayed_instance_example",
 
45
                                            delayed_instance_handler,
 
46
                                            my_delayed_oid,
 
47
                                            OID_LENGTH(my_delayed_oid),
 
48
                                            HANDLER_CAN_RWRITE);
 
49
 
 
50
    netsnmp_register_instance(my_test);
 
51
}
 
52
 
 
53
#define DELAYED_INSTANCE_SET_NAME "test_delayed"
 
54
 
 
55
int
 
56
delayed_instance_handler(netsnmp_mib_handler *handler,
 
57
                         netsnmp_handler_registration *reginfo,
 
58
                         netsnmp_agent_request_info *reqinfo,
 
59
                         netsnmp_request_info *requests)
 
60
{
 
61
 
 
62
    DEBUGMSGTL(("delayed_instance", "Got request, mode = %d:\n",
 
63
                reqinfo->mode));
 
64
 
 
65
    switch (reqinfo->mode) {
 
66
        /*
 
67
         * here we merely mention that we'll answer this request
 
68
         * later.  we don't actually care about the mode type in this
 
69
         * example, but for certain cases you may, so I'll leave in the
 
70
         * otherwise useless switch and case statements 
 
71
         */
 
72
 
 
73
    default:
 
74
        /*
 
75
         * mark this variable as something that can't be handled now.
 
76
         * We'll answer it later. 
 
77
         */
 
78
        requests->delegated = 1;
 
79
 
 
80
        /*
 
81
         * register an alarm to update the results at a later
 
82
         * time.  Normally, we might have to query something else
 
83
         * (like an external request sent to a different network
 
84
         * or system socket, etc), but for this example we'll do
 
85
         * something really simply and just insert an alarm for a
 
86
         * certain period of time 
 
87
         */
 
88
        snmp_alarm_register(delay_time, /* seconds */
 
89
                            0,  /* dont repeat. */
 
90
                            return_delayed_response,    /* the function
 
91
                                                         * to call */
 
92
                            /*
 
93
                             * here we create a "cache" of useful
 
94
                             * information that we'll want later
 
95
                             * on.  This argument is passed back
 
96
                             * to us in the callback function for
 
97
                             * an alarm 
 
98
                             */
 
99
                            (void *)
 
100
                            netsnmp_create_delegated_cache(handler,
 
101
                                                           reginfo,
 
102
                                                           reqinfo,
 
103
                                                           requests,
 
104
                                                           NULL));
 
105
        break;
 
106
 
 
107
    }
 
108
 
 
109
    return SNMP_ERR_NOERROR;
 
110
}
 
111
 
 
112
void
 
113
return_delayed_response(unsigned int clientreg, void *clientarg)
 
114
{
 
115
    /*
 
116
     * extract the cache from the passed argument 
 
117
     */
 
118
    netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg;
 
119
 
 
120
    netsnmp_request_info *requests;
 
121
    netsnmp_agent_request_info *reqinfo;
 
122
    u_long         *delay_time_cache = NULL;
 
123
 
 
124
    /*
 
125
     * here we double check that the cache we created earlier is still
 
126
     * * valid.  If not, the request timed out for some reason and we
 
127
     * * don't need to keep processing things.  Should never happen, but
 
128
     * * this double checks. 
 
129
     */
 
130
    cache = netsnmp_handler_check_cache(cache);
 
131
 
 
132
    if (!cache) {
 
133
        snmp_log(LOG_ERR, "illegal call to return delayed response\n");
 
134
        return;
 
135
    }
 
136
 
 
137
    /*
 
138
     * re-establish the previous pointers we are used to having 
 
139
     */
 
140
    reqinfo = cache->reqinfo;
 
141
    requests = cache->requests;
 
142
 
 
143
    DEBUGMSGTL(("delayed_instance",
 
144
                "continuing delayed request, mode = %d\n",
 
145
                cache->reqinfo->mode));
 
146
 
 
147
    /*
 
148
     * mention that it's no longer delegated, and we've now answered
 
149
     * the query (which we'll do down below). 
 
150
     */
 
151
    requests->delegated = 0;
 
152
 
 
153
    switch (cache->reqinfo->mode) {
 
154
        /*
 
155
         * registering as an instance means we don't need to deal with
 
156
         * getnext processing, so we don't handle it here at all.
 
157
         * 
 
158
         * However, since the instance handler already reset the mode
 
159
         * back to GETNEXT from the faked GET mode, we need to do the
 
160
         * same thing in both cases.  This should be fixed in future
 
161
         * versions of net-snmp hopefully. 
 
162
         */
 
163
 
 
164
    case MODE_GET:
 
165
    case MODE_GETNEXT:
 
166
        /*
 
167
         * return the currend delay time 
 
168
         */
 
169
        snmp_set_var_typed_value(cache->requests->requestvb,
 
170
                                 ASN_INTEGER,
 
171
                                 (u_char *) & delay_time,
 
172
                                 sizeof(delay_time));
 
173
        break;
 
174
 
 
175
    case MODE_SET_RESERVE1:
 
176
        /*
 
177
         * check type 
 
178
         */
 
179
        if (requests->requestvb->type != ASN_INTEGER) {
 
180
            /*
 
181
             * not an integer.  Bad dog, no bone. 
 
182
             */
 
183
            netsnmp_set_request_error(reqinfo, requests,
 
184
                                      SNMP_ERR_WRONGTYPE);
 
185
            /*
 
186
             * we don't need the cache any longer 
 
187
             */
 
188
            netsnmp_free_delegated_cache(cache);
 
189
            return;
 
190
        }
 
191
        break;
 
192
 
 
193
    case MODE_SET_RESERVE2:
 
194
        /*
 
195
         * store old value for UNDO support in the future. 
 
196
         */
 
197
        memdup((u_char **) & delay_time_cache,
 
198
               (u_char *) & delay_time, sizeof(delay_time));
 
199
 
 
200
        /*
 
201
         * malloc failed 
 
202
         */
 
203
        if (delay_time_cache == NULL) {
 
204
            netsnmp_set_request_error(reqinfo, requests,
 
205
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
 
206
            netsnmp_free_delegated_cache(cache);
 
207
            return;
 
208
        }
 
209
 
 
210
        /*
 
211
         * Add our temporary information to the request itself.
 
212
         * This is then retrivable later.  The free function
 
213
         * passed auto-frees it when the request is later
 
214
         * deleted.  
 
215
         */
 
216
        netsnmp_request_add_list_data(requests,
 
217
                                      netsnmp_create_data_list
 
218
                                      (DELAYED_INSTANCE_SET_NAME,
 
219
                                       delay_time_cache, free));
 
220
        break;
 
221
 
 
222
    case MODE_SET_ACTION:
 
223
        /*
 
224
         * update current value 
 
225
         */
 
226
        delay_time = *(requests->requestvb->val.integer);
 
227
        DEBUGMSGTL(("testhandler", "updated delay_time -> %d\n",
 
228
                    delay_time));
 
229
        break;
 
230
 
 
231
    case MODE_SET_UNDO:
 
232
        /*
 
233
         * ack, something somewhere failed.  We reset back to the
 
234
         * previously old value by extracting the previosuly
 
235
         * stored information back out of the request 
 
236
         */
 
237
        delay_time =
 
238
            *((u_long *) netsnmp_request_get_list_data(requests,
 
239
                                                       DELAYED_INSTANCE_SET_NAME));
 
240
        break;
 
241
 
 
242
    case MODE_SET_COMMIT:
 
243
    case MODE_SET_FREE:
 
244
        /*
 
245
         * the only thing to do here is free the old memdup'ed
 
246
         * value, but it's auto-freed by the datalist recovery, so
 
247
         * we don't have anything to actually do here 
 
248
         */
 
249
        break;
 
250
    }
 
251
 
 
252
    /*
 
253
     * free the information cache 
 
254
     */
 
255
    netsnmp_free_delegated_cache(cache);
 
256
}