blob: 179e2ee3b4a30b38a3376efa725f4a29500f6006 [file] [log] [blame]
Dave Shielde42fbdf2000-05-12 15:15:37 +00001/*
2 * agent_index.c
3 *
4 * Maintain a registry of index allocations
Wes Hardaker6d1f6022002-04-20 07:08:20 +00005 * (Primarily required for AgentX support,
6 * but it could be more widely useable).
Dave Shielde42fbdf2000-05-12 15:15:37 +00007 */
8
9
Wes Hardakereb6d4fc2002-01-04 21:00:48 +000010#include <net-snmp/net-snmp-config.h>
Dave Shielde42fbdf2000-05-12 15:15:37 +000011#include <signal.h>
12#if HAVE_STRING_H
13#include <string.h>
14#endif
15#if HAVE_STDLIB_H
16#include <stdlib.h>
17#endif
18#include <sys/types.h>
19#include <stdio.h>
20#include <fcntl.h>
21#if HAVE_WINSOCK_H
22#include <winsock.h>
23#endif
24#if TIME_WITH_SYS_TIME
25# ifdef WIN32
26# include <sys/timeb.h>
27# else
28# include <sys/time.h>
29# endif
30# include <time.h>
31#else
32# if HAVE_SYS_TIME_H
33# include <sys/time.h>
34# else
35# include <time.h>
36# endif
37#endif
Wes Hardaker9743e9f2001-10-11 21:01:50 +000038#if HAVE_NETINET_IN_H
39#include <netinet/in.h>
40#endif
Dave Shielde42fbdf2000-05-12 15:15:37 +000041
42#if HAVE_DMALLOC_H
43#include <dmalloc.h>
44#endif
45
Dave Shield1f17c992002-02-08 15:45:13 +000046#include <net-snmp/net-snmp-includes.h>
47#include <net-snmp/agent/net-snmp-agent-includes.h>
Wes Hardaker40342b72002-01-14 16:05:52 +000048#include <net-snmp/agent/agent_callbacks.h>
49#include <net-snmp/agent/agent_index.h>
Dave Shielde42fbdf2000-05-12 15:15:37 +000050
51#include "snmpd.h"
52#include "mibgroup/struct.h"
Dave Shield1f17c992002-02-08 15:45:13 +000053#include <net-snmp/agent/table.h>
54#include <net-snmp/agent/table_iterator.h>
Dave Shielde42fbdf2000-05-12 15:15:37 +000055#include "mib_module_includes.h"
56
57#ifdef USING_AGENTX_SUBAGENT_MODULE
58#include "agentx/subagent.h"
59#include "agentx/client.h"
60#endif
61
Wes Hardaker6d1f6022002-04-20 07:08:20 +000062 /*
63 * Initial support for index allocation
64 */
Dave Shielde42fbdf2000-05-12 15:15:37 +000065
66struct snmp_index {
Wes Hardaker6d1f6022002-04-20 07:08:20 +000067 netsnmp_variable_list *varbind; /* or pointer to var_list ? */
68 int allocated;
69 netsnmp_session *session;
70 struct snmp_index *next_oid;
71 struct snmp_index *prev_oid;
72 struct snmp_index *next_idx;
73} *snmp_index_head = NULL;
Dave Shielde42fbdf2000-05-12 15:15:37 +000074
Wes Hardaker73925b82002-03-09 00:28:07 +000075extern netsnmp_session *main_session;
Dave Shielde42fbdf2000-05-12 15:15:37 +000076
Wes Hardaker6d1f6022002-04-20 07:08:20 +000077/*
78 * The caller is responsible for free()ing the memory returned by
79 * this function.
80 */
John Naylona5bf3312001-06-06 14:37:08 +000081
Wes Hardaker6d1f6022002-04-20 07:08:20 +000082char *
83register_string_index(oid * name, size_t name_len, char *cp)
Dave Shielde42fbdf2000-05-12 15:15:37 +000084{
Wes Hardaker73925b82002-03-09 00:28:07 +000085 netsnmp_variable_list varbind, *res;
Wes Hardaker6d1f6022002-04-20 07:08:20 +000086
87 memset(&varbind, 0, sizeof(netsnmp_variable_list));
Dave Shielde42fbdf2000-05-12 15:15:37 +000088 varbind.type = ASN_OCTET_STR;
Wes Hardaker6d1f6022002-04-20 07:08:20 +000089 snmp_set_var_objid(&varbind, name, name_len);
90 if (cp != ANY_STRING_INDEX) {
91 snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
92 res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
John Naylona5bf3312001-06-06 14:37:08 +000093 } else {
Wes Hardaker6d1f6022002-04-20 07:08:20 +000094 res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Dave Shielde42fbdf2000-05-12 15:15:37 +000095 }
Dave Shielde42fbdf2000-05-12 15:15:37 +000096
John Naylona5bf3312001-06-06 14:37:08 +000097 if (res == NULL) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +000098 return NULL;
John Naylona5bf3312001-06-06 14:37:08 +000099 } else {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000100 char *rv = strdup(res->val.string);
101 free(res);
102 return rv;
John Naylona5bf3312001-06-06 14:37:08 +0000103 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000104}
105
106int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000107register_int_index(oid * name, size_t name_len, int val)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000108{
Wes Hardaker73925b82002-03-09 00:28:07 +0000109 netsnmp_variable_list varbind, *res;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000110
111 memset(&varbind, 0, sizeof(netsnmp_variable_list));
Dave Shielde42fbdf2000-05-12 15:15:37 +0000112 varbind.type = ASN_INTEGER;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000113 snmp_set_var_objid(&varbind, name, name_len);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000114 varbind.val.string = varbind.buf;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000115 if (val != ANY_INTEGER_INDEX) {
Dave Shielde42fbdf2000-05-12 15:15:37 +0000116 varbind.val_len = sizeof(long);
117 *varbind.val.integer = val;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000118 res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
John Naylona5bf3312001-06-06 14:37:08 +0000119 } else {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000120 res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000121 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000122
John Naylona5bf3312001-06-06 14:37:08 +0000123 if (res == NULL) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000124 return -1;
John Naylona5bf3312001-06-06 14:37:08 +0000125 } else {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000126 int rv = *(res->val.integer);
127 free(res);
128 return rv;
John Naylona5bf3312001-06-06 14:37:08 +0000129 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000130}
131
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000132/*
133 * The caller is responsible for free()ing the memory returned by
134 * this function.
135 */
John Naylona5bf3312001-06-06 14:37:08 +0000136
Wes Hardaker73925b82002-03-09 00:28:07 +0000137netsnmp_variable_list *
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000138register_oid_index(oid * name, size_t name_len,
139 oid * value, size_t value_len)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000140{
Wes Hardaker73925b82002-03-09 00:28:07 +0000141 netsnmp_variable_list varbind;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000142
143 memset(&varbind, 0, sizeof(netsnmp_variable_list));
Dave Shielde42fbdf2000-05-12 15:15:37 +0000144 varbind.type = ASN_OBJECT_ID;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000145 snmp_set_var_objid(&varbind, name, name_len);
John Naylona5bf3312001-06-06 14:37:08 +0000146 if (value != ANY_OID_INDEX) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000147 snmp_set_var_value(&varbind, (u_char *) value,
148 value_len * sizeof(oid));
149 return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
John Naylona5bf3312001-06-06 14:37:08 +0000150 } else {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000151 return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000152 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000153}
154
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000155/*
156 * The caller is responsible for free()ing the memory returned by
157 * this function.
158 */
John Naylona5bf3312001-06-06 14:37:08 +0000159
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000160netsnmp_variable_list *
161register_index(netsnmp_variable_list * varbind, int flags,
162 netsnmp_session * ss)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000163{
Wes Hardaker73925b82002-03-09 00:28:07 +0000164 netsnmp_variable_list *rv = NULL;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000165 struct snmp_index *new_index, *idxptr, *idxptr2;
166 struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000167 int res, res2, i;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000168
John Naylondb64aeb2002-03-05 16:48:42 +0000169 DEBUGMSGTL(("register_index", "register "));
170 DEBUGMSGVAR(("register_index", varbind));
171 DEBUGMSG(("register_index", "for session %08p\n", ss));
John Naylon9a60b412001-06-05 10:10:45 +0000172
Dave Shielde42fbdf2000-05-12 15:15:37 +0000173#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
John Naylonbb401c12002-05-15 12:53:01 +0000174 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
175 NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000176 return (agentx_register_index(ss, varbind, flags));
John Naylonbb401c12002-05-15 12:53:01 +0000177 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000178#endif
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000179 /*
180 * Look for the requested OID entry
181 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000182 prev_oid_ptr = NULL;
183 prev_idx_ptr = NULL;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000184 res = 1;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000185 res2 = 1;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000186 for (idxptr = snmp_index_head; idxptr != NULL;
187 prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
188 if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
189 idxptr->varbind->name,
190 idxptr->varbind->name_length)) <= 0)
191 break;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000192 }
193
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000194 /*
195 * Found the OID - now look at the registered indices
196 */
197 if (res == 0 && idxptr) {
198 if (varbind->type != idxptr->varbind->type)
199 return NULL; /* wrong type */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000200
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000201 /*
202 * If we've been asked for an arbitrary new value,
203 * then find the end of the list.
204 * If we've been asked for any arbitrary value,
205 * then look for an unused entry, and use that.
206 * If there aren't any, continue as for new.
207 * Otherwise, locate the given value in the (sorted)
208 * list of already allocated values
209 */
210 if (flags & ALLOCATE_ANY_INDEX) {
211 for (idxptr2 = idxptr; idxptr2 != NULL;
212 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
John Naylon496ba562001-06-19 16:44:38 +0000213
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000214 if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
215 if ((rv =
216 snmp_clone_varbind(idxptr2->varbind)) != NULL) {
217 idxptr2->session = ss;
218 idxptr2->allocated = 1;
219 }
220 return rv;
221 }
222 }
223 } else {
224 for (idxptr2 = idxptr; idxptr2 != NULL;
225 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
226 switch (varbind->type) {
227 case ASN_INTEGER:
228 res2 =
229 (*varbind->val.integer -
230 *idxptr2->varbind->val.integer);
231 break;
232 case ASN_OCTET_STR:
233 i = SNMP_MIN(varbind->val_len,
234 idxptr2->varbind->val_len);
235 res2 =
236 memcmp(varbind->val.string,
237 idxptr2->varbind->val.string, i);
238 break;
239 case ASN_OBJECT_ID:
240 res2 =
241 snmp_oid_compare(varbind->val.objid,
242 varbind->val_len / sizeof(oid),
243 idxptr2->varbind->val.objid,
244 idxptr2->varbind->val_len /
245 sizeof(oid));
246 break;
247 default:
248 return NULL; /* wrong type */
249 }
250 if (res2 <= 0)
251 break;
252 }
253 if (res2 == 0) {
254 if (idxptr2->allocated) {
255 /*
256 * No good: the index is in use.
257 */
258 return NULL;
259 } else {
260 /*
261 * Okay, it's unallocated, we can just claim ownership
262 * here.
263 */
264 if ((rv =
265 snmp_clone_varbind(idxptr2->varbind)) != NULL) {
266 idxptr2->session = ss;
267 idxptr2->allocated = 1;
268 }
269 return rv;
270 }
271 }
272 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000273 }
274
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000275 /*
276 * OK - we've now located where the new entry needs to
277 * be fitted into the index registry tree
278 * To recap:
279 * 'prev_oid_ptr' points to the head of the OID index
280 * list prior to this one. If this is null, then
281 * it means that this is the first OID in the list.
282 * 'idxptr' points either to the head of this OID list,
283 * or the next OID (if this is a new OID request)
284 * These can be distinguished by the value of 'res'.
285 *
286 * 'prev_idx_ptr' points to the index entry that sorts
287 * immediately prior to the requested value (if any).
288 * If an arbitrary value is required, then this will
289 * point to the last allocated index.
290 * If this pointer is null, then either this is a new
291 * OID request, or the requested value is the first
292 * in the list.
293 * 'idxptr2' points to the next sorted index (if any)
294 * but is not actually needed any more.
295 *
296 * Clear? Good!
297 * I hope you've been paying attention.
298 * There'll be a test later :-)
299 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000300
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000301 /*
302 * We proceed by creating the new entry
303 * (by copying the entry provided)
304 */
305 new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
306 if (new_index == NULL)
307 return NULL;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000308
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000309 if (0 == snmp_varlist_add_variable(&new_index->varbind,
310 varbind->name,
311 varbind->name_length,
312 varbind->type,
313 varbind->val.string,
314 varbind->val_len)) {
315 /*
316 * if (snmp_clone_var( varbind, new_index->varbind ) != 0 )
317 */
318 free(new_index);
319 return NULL;
320 }
321 new_index->session = ss;
322 new_index->allocated = 1;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000323
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000324 if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
325 new_index->varbind->val.string[new_index->varbind->val_len] = 0;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000326
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000327 /*
328 * If we've been given a value, then we can use that, but
329 * otherwise, we need to create a new value for this entry.
330 * Note that ANY_INDEX and NEW_INDEX are both covered by this
331 * test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
332 */
333 if (flags & ALLOCATE_ANY_INDEX) {
334 if (prev_idx_ptr) {
335 if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
336 != 0) {
337 free(new_index);
338 return NULL;
339 }
340 } else
341 new_index->varbind->val.string = new_index->varbind->buf;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000342
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000343 switch (varbind->type) {
344 case ASN_INTEGER:
345 if (prev_idx_ptr) {
346 (*new_index->varbind->val.integer)++;
347 } else
348 *(new_index->varbind->val.integer) = 1;
349 new_index->varbind->val_len = sizeof(long);
350 break;
351 case ASN_OCTET_STR:
352 if (prev_idx_ptr) {
353 i = new_index->varbind->val_len - 1;
354 while (new_index->varbind->buf[i] == 'z') {
355 new_index->varbind->buf[i] = 'a';
356 i--;
357 if (i < 0) {
358 i = new_index->varbind->val_len;
359 new_index->varbind->buf[i] = 'a';
360 new_index->varbind->buf[i + 1] = 0;
361 }
362 }
363 new_index->varbind->buf[i]++;
364 } else
365 strcpy((char *) new_index->varbind->buf, "aaaa");
366 new_index->varbind->val_len =
367 strlen((char *) new_index->varbind->buf);
368 break;
369 case ASN_OBJECT_ID:
370 if (prev_idx_ptr) {
371 i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
372 while (new_index->varbind->val.objid[i] == 255) {
373 new_index->varbind->val.objid[i] = 1;
374 i--;
375 if (i == 0 && new_index->varbind->val.objid[0] == 2) {
376 new_index->varbind->val.objid[0] = 1;
377 i = new_index->varbind->val_len / sizeof(oid);
378 new_index->varbind->val.objid[i] = 0;
379 new_index->varbind->val_len += sizeof(oid);
380 }
381 }
382 new_index->varbind->val.objid[i]++;
383 } else {
384 /*
385 * If the requested OID name is small enough,
386 * * append another OID (1) and use this as the
387 * * default starting value for new indexes.
388 */
389 if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
390 for (i = 0; i < (int) varbind->name_length; i++)
391 new_index->varbind->val.objid[i] =
392 varbind->name[i];
393 new_index->varbind->val.objid[varbind->name_length] =
394 1;
395 new_index->varbind->val_len =
396 (varbind->name_length + 1) * sizeof(oid);
397 } else {
398 /*
399 * Otherwise use '.1.1.1.1...'
400 */
401 i = 40 / sizeof(oid);
402 if (i > 4)
403 i = 4;
404 new_index->varbind->val_len = i * (sizeof(oid));
405 for (i--; i >= 0; i--)
406 new_index->varbind->val.objid[i] = 1;
407 }
408 }
409 break;
410 default:
411 snmp_free_var(new_index->varbind);
412 free(new_index);
413 return NULL; /* Index type not supported */
414 }
415 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000416
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000417 /*
418 * Try to duplicate the new varbind for return.
419 */
John Naylona5bf3312001-06-06 14:37:08 +0000420
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000421 if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
422 snmp_free_var(new_index->varbind);
423 free(new_index);
424 return NULL;
425 }
John Naylona5bf3312001-06-06 14:37:08 +0000426
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000427 /*
428 * Right - we've set up the new entry.
429 * All that remains is to link it into the tree.
430 * There are a number of possible cases here,
431 * so watch carefully.
432 */
433 if (prev_idx_ptr) {
434 new_index->next_idx = prev_idx_ptr->next_idx;
435 new_index->next_oid = prev_idx_ptr->next_oid;
436 prev_idx_ptr->next_idx = new_index;
437 } else {
438 if (res == 0 && idxptr) {
439 new_index->next_idx = idxptr;
440 new_index->next_oid = idxptr->next_oid;
441 } else {
442 new_index->next_idx = NULL;
443 new_index->next_oid = idxptr;
444 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000445
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000446 if (prev_oid_ptr) {
447 while (prev_oid_ptr) {
448 prev_oid_ptr->next_oid = new_index;
449 prev_oid_ptr = prev_oid_ptr->next_idx;
450 }
451 } else
452 snmp_index_head = new_index;
453 }
John Naylona5bf3312001-06-06 14:37:08 +0000454 return rv;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000455}
456
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000457 /*
458 * Release an allocated index,
459 * to allow it to be used elsewhere
460 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000461int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000462release_index(netsnmp_variable_list * varbind)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000463{
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000464 return (unregister_index(varbind, TRUE, NULL));
Dave Shielde42fbdf2000-05-12 15:15:37 +0000465}
466
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000467 /*
468 * Completely remove an allocated index,
469 * due to errors in the registration process.
470 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000471int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000472remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000473{
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000474 return (unregister_index(varbind, FALSE, ss));
Dave Shielde42fbdf2000-05-12 15:15:37 +0000475}
476
477void
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000478unregister_index_by_session(netsnmp_session * ss)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000479{
480 struct snmp_index *idxptr, *idxptr2;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000481 for (idxptr = snmp_index_head; idxptr != NULL;
482 idxptr = idxptr->next_oid)
483 for (idxptr2 = idxptr; idxptr2 != NULL;
484 idxptr2 = idxptr2->next_idx)
485 if (idxptr2->session == ss) {
486 idxptr2->allocated = 0;
487 idxptr2->session = NULL;
488 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000489}
490
491
492int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000493unregister_index(netsnmp_variable_list * varbind, int remember,
494 netsnmp_session * ss)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000495{
496 struct snmp_index *idxptr, *idxptr2;
497 struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000498 int res, res2, i;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000499
500#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
John Naylonbb401c12002-05-15 12:53:01 +0000501 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
502 NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000503 return (agentx_unregister_index(ss, varbind));
John Naylonbb401c12002-05-15 12:53:01 +0000504 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000505#endif
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000506 /*
507 * Look for the requested OID entry
508 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000509 prev_oid_ptr = NULL;
510 prev_idx_ptr = NULL;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000511 res = 1;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000512 res2 = 1;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000513 for (idxptr = snmp_index_head; idxptr != NULL;
514 prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
515 if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
516 idxptr->varbind->name,
517 idxptr->varbind->name_length)) <= 0)
518 break;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000519 }
520
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000521 if (res != 0)
522 return INDEX_ERR_NOT_ALLOCATED;
523 if (varbind->type != idxptr->varbind->type)
524 return INDEX_ERR_WRONG_TYPE;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000525
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000526 for (idxptr2 = idxptr; idxptr2 != NULL;
527 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
528 i = SNMP_MIN(varbind->val_len, idxptr2->varbind->val_len);
529 res2 =
530 memcmp(varbind->val.string, idxptr2->varbind->val.string, i);
531 if (res2 <= 0)
532 break;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000533 }
John Naylon496ba562001-06-19 16:44:38 +0000534 if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000535 return INDEX_ERR_NOT_ALLOCATED;
John Naylon496ba562001-06-19 16:44:38 +0000536 }
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000537 if (ss != idxptr2->session)
538 return INDEX_ERR_WRONG_SESSION;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000539
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000540 /*
541 * If this is a "normal" index unregistration,
542 * mark the index entry as unused, but leave
543 * it in situ. This allows differentiation
544 * between ANY_INDEX and NEW_INDEX
545 */
546 if (remember) {
547 idxptr2->allocated = 0; /* Unused index */
548 idxptr2->session = NULL;
549 return SNMP_ERR_NOERROR;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000550 }
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000551 /*
552 * If this is a failed attempt to register a
553 * number of indexes, the successful ones
554 * must be removed completely.
555 */
556 if (prev_idx_ptr) {
557 prev_idx_ptr->next_idx = idxptr2->next_idx;
558 } else if (prev_oid_ptr) {
559 if (idxptr2->next_idx) /* Use p_idx_ptr as a temp variable */
560 prev_idx_ptr = idxptr2->next_idx;
561 else
562 prev_idx_ptr = idxptr2->next_oid;
563 while (prev_oid_ptr) {
564 prev_oid_ptr->next_oid = prev_idx_ptr;
565 prev_oid_ptr = prev_oid_ptr->next_idx;
566 }
567 } else {
568 if (idxptr2->next_idx)
569 snmp_index_head = idxptr2->next_idx;
570 else
571 snmp_index_head = idxptr2->next_oid;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000572 }
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000573 snmp_free_var(idxptr2->varbind);
574 free(idxptr2);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000575 return SNMP_ERR_NOERROR;
576}
577
John Naylon481a3092001-11-20 16:29:41 +0000578int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000579unregister_string_index(oid * name, size_t name_len, char *cp)
John Naylon481a3092001-11-20 16:29:41 +0000580{
Wes Hardaker73925b82002-03-09 00:28:07 +0000581 netsnmp_variable_list varbind;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000582
583 memset(&varbind, 0, sizeof(netsnmp_variable_list));
John Naylon481a3092001-11-20 16:29:41 +0000584 varbind.type = ASN_OCTET_STR;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000585 snmp_set_var_objid(&varbind, name, name_len);
586 snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
John Naylon481a3092001-11-20 16:29:41 +0000587 return (unregister_index(&varbind, FALSE, main_session));
588}
589
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000590int
591unregister_int_index(oid * name, size_t name_len, int val)
John Naylon481a3092001-11-20 16:29:41 +0000592{
Wes Hardaker73925b82002-03-09 00:28:07 +0000593 netsnmp_variable_list varbind;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000594
Wes Hardaker73925b82002-03-09 00:28:07 +0000595 memset(&varbind, 0, sizeof(netsnmp_variable_list));
John Naylon481a3092001-11-20 16:29:41 +0000596 varbind.type = ASN_INTEGER;
597 snmp_set_var_objid(&varbind, name, name_len);
598 varbind.val.string = varbind.buf;
599 varbind.val_len = sizeof(long);
600 *varbind.val.integer = val;
601 return (unregister_index(&varbind, FALSE, main_session));
602}
603
604int
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000605unregister_oid_index(oid * name, size_t name_len,
606 oid * value, size_t value_len)
John Naylon481a3092001-11-20 16:29:41 +0000607{
Wes Hardaker73925b82002-03-09 00:28:07 +0000608 netsnmp_variable_list varbind;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000609
610 memset(&varbind, 0, sizeof(netsnmp_variable_list));
John Naylon481a3092001-11-20 16:29:41 +0000611 varbind.type = ASN_OBJECT_ID;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000612 snmp_set_var_objid(&varbind, name, name_len);
613 snmp_set_var_value(&varbind, (u_char *) value,
614 value_len * sizeof(oid));
John Naylon481a3092001-11-20 16:29:41 +0000615 return (unregister_index(&varbind, FALSE, main_session));
616}
Dave Shielde42fbdf2000-05-12 15:15:37 +0000617
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000618void
619dump_idx_registry(void)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000620{
621 struct snmp_index *idxptr, *idxptr2;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000622 u_char *sbuf = NULL, *ebuf = NULL;
623 size_t sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000624
John Naylon3bee5ee2002-02-27 12:35:42 +0000625 if (snmp_index_head != NULL) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000626 printf("\nIndex Allocations:\n");
John Naylon3bee5ee2002-02-27 12:35:42 +0000627 }
628
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000629 for (idxptr = snmp_index_head; idxptr != NULL;
630 idxptr = idxptr->next_oid) {
631 sout_len = 0;
632 if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
633 idxptr->varbind->name,
634 idxptr->varbind->name_length)) {
635 printf("%s indexes:\n", sbuf);
636 } else {
637 printf("%s [TRUNCATED] indexes:\n", sbuf);
638 }
John Naylon3bee5ee2002-02-27 12:35:42 +0000639
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000640 for (idxptr2 = idxptr; idxptr2 != NULL;
641 idxptr2 = idxptr2->next_idx) {
642 switch (idxptr2->varbind->type) {
643 case ASN_INTEGER:
John Naylona1a4a842002-07-10 09:35:38 +0000644 printf(" %ld for session %8p, allocated %d\n",
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000645 *idxptr2->varbind->val.integer, idxptr2->session,
646 idxptr2->allocated);
647 break;
648 case ASN_OCTET_STR:
John Naylona1a4a842002-07-10 09:35:38 +0000649 printf(" \"%s\" for session %8p, allocated %d\n",
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000650 idxptr2->varbind->val.string, idxptr2->session,
651 idxptr2->allocated);
652 break;
653 case ASN_OBJECT_ID:
654 eout_len = 0;
655 if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
656 idxptr2->varbind->val.objid,
657 idxptr2->varbind->val_len /
658 sizeof(oid))) {
John Naylona1a4a842002-07-10 09:35:38 +0000659 printf(" %s for session %8p, allocated %d\n", ebuf,
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000660 idxptr2->session, idxptr2->allocated);
661 } else {
662 printf
John Naylona1a4a842002-07-10 09:35:38 +0000663 (" %s [TRUNCATED] for sess %8p, allocated %d\n",
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000664 ebuf, idxptr2->session, idxptr2->allocated);
665 }
666 break;
667 default:
668 printf("unsupported type (%d/0x%02x)\n",
669 idxptr2->varbind->type, idxptr2->varbind->type);
670 }
671 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000672 }
John Naylon3bee5ee2002-02-27 12:35:42 +0000673
674 if (sbuf != NULL) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000675 free(sbuf);
John Naylon3bee5ee2002-02-27 12:35:42 +0000676 }
677 if (ebuf != NULL) {
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000678 free(ebuf);
John Naylon3bee5ee2002-02-27 12:35:42 +0000679 }
Dave Shielde42fbdf2000-05-12 15:15:37 +0000680}
681
John Naylona5f53ae2001-06-20 13:44:18 +0000682unsigned long
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000683count_indexes(oid * name, size_t namelen, int include_unallocated)
John Naylona5f53ae2001-06-20 13:44:18 +0000684{
685 struct snmp_index *i = NULL, *j = NULL;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000686 unsigned long n = 0;
John Naylona5f53ae2001-06-20 13:44:18 +0000687
688 for (i = snmp_index_head; i != NULL; i = i->next_oid) {
Wes Hardakerbb4d05c2002-08-15 15:14:22 +0000689 if (netsnmp_oid_equals(name, namelen,
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000690 i->varbind->name,
691 i->varbind->name_length) == 0) {
692 for (j = i; j != NULL; j = j->next_idx) {
693 if (j->allocated || include_unallocated) {
694 n++;
695 }
696 }
697 }
John Naylona5f53ae2001-06-20 13:44:18 +0000698 }
699 return n;
700}
701
702
Dave Shielde42fbdf2000-05-12 15:15:37 +0000703#ifdef TESTING
Wes Hardaker73925b82002-03-09 00:28:07 +0000704netsnmp_variable_list varbind;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000705netsnmp_session main_sess, *main_session = &main_sess;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000706
707void
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000708test_string_register(int n, char *cp)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000709{
710 varbind->name[4] = n;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000711 if (register_string_index(varbind->name, varbind.name_length, cp) ==
712 NULL)
713 printf("allocating %s failed\n", cp);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000714}
715
716void
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000717test_int_register(int n, int val)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000718{
719 varbind->name[4] = n;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000720 if (register_int_index(varbind->name, varbind.name_length, val) == -1)
721 printf("allocating %d/%d failed\n", n, val);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000722}
723
724void
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000725test_oid_register(int n, int subid)
Dave Shielde42fbdf2000-05-12 15:15:37 +0000726{
Wes Hardaker73925b82002-03-09 00:28:07 +0000727 netsnmp_variable_list *res;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000728
729 varbind->name[4] = n;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000730 if (subid != -1) {
Dave Shielde42fbdf2000-05-12 15:15:37 +0000731 varbind->val.objid[5] = subid;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000732 res = register_oid_index(varbind->name, varbind.name_length,
733 varbind->val.objid,
734 varbind->val_len / sizeof(oid));
735 } else
736 res =
737 register_oid_index(varbind->name, varbind.name_length, NULL,
738 0);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000739
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000740 if (res == NULL)
741 printf("allocating %d/%d failed\n", n, subid);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000742}
743
744void
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000745main(int argc, char argv[])
Dave Shielde42fbdf2000-05-12 15:15:37 +0000746{
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000747 oid name[] = { 1, 2, 3, 4, 0 };
748 int i;
749
750 memset(&varbind, 0, sizeof(netsnmp_variable_list));
751 snmp_set_var_objid(&varbind, name, 5);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000752 varbind->type = ASN_OCTET_STR;
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000753 /*
754 * Test index structure linking:
755 * a) sorted by OID
756 */
757 test_string_register(20, "empty OID");
758 test_string_register(10, "first OID");
759 test_string_register(40, "last OID");
760 test_string_register(30, "middle OID");
Dave Shielde42fbdf2000-05-12 15:15:37 +0000761
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000762 /*
763 * b) sorted by index value
764 */
765 test_string_register(25, "eee: empty IDX");
766 test_string_register(25, "aaa: first IDX");
767 test_string_register(25, "zzz: last IDX");
768 test_string_register(25, "mmm: middle IDX");
Dave Shielde42fbdf2000-05-12 15:15:37 +0000769 printf("This next one should fail....\n");
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000770 test_string_register(25, "eee: empty IDX"); /* duplicate */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000771 printf("done\n");
772
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000773 /*
774 * c) test initial index linking
775 */
776 test_string_register(5, "eee: empty initial IDX");
777 test_string_register(5, "aaa: replace initial IDX");
Dave Shielde42fbdf2000-05-12 15:15:37 +0000778
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000779 /*
780 * Did it all work?
781 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000782 dump_idx_registry();
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000783 unregister_index_by_session(main_session);
784 /*
785 * Now test index allocation
786 * a) integer values
787 */
788 test_int_register(110, -1); /* empty */
789 test_int_register(110, -1); /* append */
790 test_int_register(110, 10); /* append exact */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000791 printf("This next one should fail....\n");
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000792 test_int_register(110, 10); /* exact duplicate */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000793 printf("done\n");
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000794 test_int_register(110, -1); /* append */
795 test_int_register(110, 5); /* insert exact */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000796
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000797 /*
798 * b) string values
799 */
800 test_string_register(120, NULL); /* empty */
801 test_string_register(120, NULL); /* append */
802 test_string_register(120, "aaaz");
803 test_string_register(120, NULL); /* minor rollover */
804 test_string_register(120, "zzzz");
805 test_string_register(120, NULL); /* major rollover */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000806
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000807 /*
808 * c) OID values
809 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000810
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000811 test_oid_register(130, -1); /* empty */
812 test_oid_register(130, -1); /* append */
813
814 varbind->val_len = varbind.name_length * sizeof(oid);
815 memcpy(varbind->buf, varbind.name, varbind.val_len);
816 varbind->val.objid = (oid *) varbind.buf;
Dave Shielde42fbdf2000-05-12 15:15:37 +0000817 varbind->val_len += sizeof(oid);
818
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000819 test_oid_register(130, 255); /* append exact */
820 test_oid_register(130, -1); /* minor rollover */
821 test_oid_register(130, 100); /* insert exact */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000822 printf("This next one should fail....\n");
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000823 test_oid_register(130, 100); /* exact duplicate */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000824 printf("done\n");
825
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000826 varbind->val.objid = (oid *) varbind.buf;
827 for (i = 0; i < 6; i++)
828 varbind->val.objid[i] = 255;
829 varbind->val.objid[0] = 1;
830 test_oid_register(130, 255); /* set up rollover */
831 test_oid_register(130, -1); /* medium rollover */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000832
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000833 for (i = 0; i < 6; i++)
834 varbind->val.objid[i] = 255;
835 varbind->val.objid[0] = 2;
836 test_oid_register(130, 255); /* set up rollover */
837 test_oid_register(130, -1); /* major rollover */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000838
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000839 /*
840 * Did it all work?
841 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000842 dump_idx_registry();
843
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000844 /*
845 * Test the various "invalid" requests
846 * (unsupported types, mis-matched types, etc)
847 */
Dave Shielde42fbdf2000-05-12 15:15:37 +0000848 printf("The rest of these should fail....\n");
Wes Hardaker6d1f6022002-04-20 07:08:20 +0000849 test_oid_register(110, -1);
850 test_oid_register(110, 100);
851 test_oid_register(120, -1);
852 test_oid_register(120, 100);
853 test_string_register(110, NULL);
854 test_string_register(110, "aaaa");
855 test_string_register(130, NULL);
856 test_string_register(130, "aaaa");
857 test_int_register(120, -1);
858 test_int_register(120, 1);
859 test_int_register(130, -1);
860 test_int_register(130, 1);
Dave Shielde42fbdf2000-05-12 15:15:37 +0000861 printf("done - this dump should be the same as before\n");
862 dump_idx_registry();
863}
864#endif