net-snmp/agent/agent_index.c

892 lines
28 KiB
C

/*
* agent_index.c
*
* Maintain a registry of index allocations
* (Primarily required for AgentX support,
* but it could be more widely useable).
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#include <signal.h>
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/agent_callbacks.h>
#include <net-snmp/agent/agent_index.h>
#include "snmpd.h"
#include "agent_global_vars.h"
#include "mibgroup/struct.h"
#include <net-snmp/agent/table.h>
#include <net-snmp/agent/table_iterator.h>
#ifdef USING_AGENTX_SUBAGENT_MODULE
#include "agentx/subagent.h"
#include "agentx/client.h"
#endif
netsnmp_feature_child_of(agent_index_all, libnetsnmpagent)
netsnmp_feature_child_of(remove_index, agent_index_all)
/*
* Initial support for index allocation
*/
struct snmp_index {
netsnmp_variable_list *varbind; /* or pointer to var_list ? */
int allocated;
netsnmp_session *session;
struct snmp_index *next_oid;
struct snmp_index *prev_oid;
struct snmp_index *next_idx;
} *snmp_index_head = NULL;
/*
* The caller is responsible for free()ing the memory returned by
* this function.
*/
char *
register_string_index(oid * name, size_t name_len, char *cp)
{
netsnmp_variable_list varbind, *res;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_OCTET_STR;
snmp_set_var_objid(&varbind, name, name_len);
if (cp != ANY_STRING_INDEX) {
snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
} else {
res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
}
if (res == NULL) {
return NULL;
} else {
char *rv = (char *)malloc(res->val_len + 1);
if (rv) {
memcpy(rv, res->val.string, res->val_len);
rv[res->val_len] = 0;
}
free(res);
return rv;
}
}
int
register_int_index(oid * name, size_t name_len, int val)
{
netsnmp_variable_list varbind, *res;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_INTEGER;
snmp_set_var_objid(&varbind, name, name_len);
varbind.val.string = varbind.buf;
if (val != ANY_INTEGER_INDEX) {
varbind.val_len = sizeof(long);
*varbind.val.integer = val;
res = register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
} else {
res = register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
}
if (res == NULL) {
return -1;
} else {
int rv = *(res->val.integer);
free(res);
return rv;
}
}
/*
* The caller is responsible for free()ing the memory returned by
* this function.
*/
netsnmp_variable_list *
register_oid_index(oid * name, size_t name_len,
oid * value, size_t value_len)
{
netsnmp_variable_list varbind;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_OBJECT_ID;
snmp_set_var_objid(&varbind, name, name_len);
if (value != ANY_OID_INDEX) {
snmp_set_var_value(&varbind, (u_char *) value,
value_len * sizeof(oid));
return register_index(&varbind, ALLOCATE_THIS_INDEX, main_session);
} else {
return register_index(&varbind, ALLOCATE_ANY_INDEX, main_session);
}
}
/*
* The caller is responsible for free()ing the memory returned by
* this function.
*/
netsnmp_variable_list *
register_index(netsnmp_variable_list * varbind, int flags,
netsnmp_session * ss)
{
netsnmp_variable_list *rv = NULL;
struct snmp_index *new_index, *idxptr, *idxptr2;
struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
int res, res2, i;
DEBUGMSGTL(("register_index", "register "));
DEBUGMSGVAR(("register_index", varbind));
DEBUGMSG(("register_index", "for session %8p\n", ss));
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
return (agentx_register_index(ss, varbind, flags));
}
#endif
/*
* Look for the requested OID entry
*/
prev_oid_ptr = NULL;
prev_idx_ptr = NULL;
res = 1;
res2 = 1;
for (idxptr = snmp_index_head; idxptr != NULL;
prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
idxptr->varbind->name,
idxptr->varbind->name_length)) <= 0)
break;
}
/*
* Found the OID - now look at the registered indices
*/
if (res == 0 && idxptr) {
if (varbind->type != idxptr->varbind->type)
return NULL; /* wrong type */
/*
* If we've been asked for an arbitrary new value,
* then find the end of the list.
* If we've been asked for any arbitrary value,
* then look for an unused entry, and use that.
* If there aren't any, continue as for new.
* Otherwise, locate the given value in the (sorted)
* list of already allocated values
*/
if (flags & ALLOCATE_ANY_INDEX) {
for (idxptr2 = idxptr; idxptr2 != NULL;
prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
if (flags == ALLOCATE_ANY_INDEX && !(idxptr2->allocated)) {
if ((rv =
snmp_clone_varbind(idxptr2->varbind)) != NULL) {
idxptr2->session = ss;
idxptr2->allocated = 1;
}
return rv;
}
}
} else {
for (idxptr2 = idxptr; idxptr2 != NULL;
prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
switch (varbind->type) {
case ASN_INTEGER:
res2 =
(*varbind->val.integer -
*idxptr2->varbind->val.integer);
break;
case ASN_OCTET_STR:
i = SNMP_MIN(varbind->val_len,
idxptr2->varbind->val_len);
res2 =
memcmp(varbind->val.string,
idxptr2->varbind->val.string, i);
break;
case ASN_OBJECT_ID:
res2 =
snmp_oid_compare(varbind->val.objid,
varbind->val_len / sizeof(oid),
idxptr2->varbind->val.objid,
idxptr2->varbind->val_len /
sizeof(oid));
break;
default:
return NULL; /* wrong type */
}
if (res2 <= 0)
break;
}
if (res2 == 0) {
if (idxptr2->allocated) {
/*
* No good: the index is in use.
*/
return NULL;
} else {
/*
* Okay, it's unallocated, we can just claim ownership
* here.
*/
if ((rv =
snmp_clone_varbind(idxptr2->varbind)) != NULL) {
idxptr2->session = ss;
idxptr2->allocated = 1;
}
return rv;
}
}
}
}
/*
* OK - we've now located where the new entry needs to
* be fitted into the index registry tree
* To recap:
* 'prev_oid_ptr' points to the head of the OID index
* list prior to this one. If this is null, then
* it means that this is the first OID in the list.
* 'idxptr' points either to the head of this OID list,
* or the next OID (if this is a new OID request)
* These can be distinguished by the value of 'res'.
*
* 'prev_idx_ptr' points to the index entry that sorts
* immediately prior to the requested value (if any).
* If an arbitrary value is required, then this will
* point to the last allocated index.
* If this pointer is null, then either this is a new
* OID request, or the requested value is the first
* in the list.
* 'idxptr2' points to the next sorted index (if any)
* but is not actually needed any more.
*
* Clear? Good!
* I hope you've been paying attention.
* There'll be a test later :-)
*/
/*
* We proceed by creating the new entry
* (by copying the entry provided)
*/
new_index = (struct snmp_index *) calloc(1, sizeof(struct snmp_index));
if (new_index == NULL)
return NULL;
if (NULL == snmp_varlist_add_variable(&new_index->varbind,
varbind->name,
varbind->name_length,
varbind->type,
varbind->val.string,
varbind->val_len)) {
/*
* if (snmp_clone_var( varbind, new_index->varbind ) != 0 )
*/
free(new_index);
return NULL;
}
new_index->session = ss;
new_index->allocated = 1;
if (varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX)
new_index->varbind->val.string[new_index->varbind->val_len] = 0;
/*
* If we've been given a value, then we can use that, but
* otherwise, we need to create a new value for this entry.
* Note that ANY_INDEX and NEW_INDEX are both covered by this
* test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
*/
if (flags & ALLOCATE_ANY_INDEX) {
if (prev_idx_ptr) {
if (snmp_clone_var(prev_idx_ptr->varbind, new_index->varbind)
!= 0) {
free(new_index);
return NULL;
}
} else
new_index->varbind->val.string = new_index->varbind->buf;
switch (varbind->type) {
case ASN_INTEGER:
if (prev_idx_ptr) {
(*new_index->varbind->val.integer)++;
} else
*(new_index->varbind->val.integer) = 1;
new_index->varbind->val_len = sizeof(long);
break;
case ASN_OCTET_STR:
if (prev_idx_ptr) {
i = new_index->varbind->val_len - 1;
while (new_index->varbind->buf[i] == 'z') {
new_index->varbind->buf[i] = 'a';
i--;
if (i < 0) {
i = new_index->varbind->val_len;
new_index->varbind->buf[i] = 'a';
new_index->varbind->buf[i + 1] = 0;
}
}
new_index->varbind->buf[i]++;
} else
strcpy((char *) new_index->varbind->buf, "aaaa");
new_index->varbind->val_len =
strlen((char *) new_index->varbind->buf);
break;
case ASN_OBJECT_ID:
if (prev_idx_ptr) {
i = prev_idx_ptr->varbind->val_len / sizeof(oid) - 1;
while (new_index->varbind->val.objid[i] == 255) {
new_index->varbind->val.objid[i] = 1;
i--;
if (i == 0 && new_index->varbind->val.objid[0] == 2) {
new_index->varbind->val.objid[0] = 1;
i = new_index->varbind->val_len / sizeof(oid);
new_index->varbind->val.objid[i] = 0;
new_index->varbind->val_len += sizeof(oid);
}
}
new_index->varbind->val.objid[i]++;
} else {
/*
* If the requested OID name is small enough,
* * append another OID (1) and use this as the
* * default starting value for new indexes.
*/
if ((varbind->name_length + 1) * sizeof(oid) <= 40) {
for (i = 0; i < (int) varbind->name_length; i++)
new_index->varbind->val.objid[i] =
varbind->name[i];
new_index->varbind->val.objid[varbind->name_length] =
1;
new_index->varbind->val_len =
(varbind->name_length + 1) * sizeof(oid);
} else {
/*
* Otherwise use '.1.1.1.1...'
*/
i = 40 / sizeof(oid);
if (i > 4)
i = 4;
new_index->varbind->val_len = i * (sizeof(oid));
for (i--; i >= 0; i--)
new_index->varbind->val.objid[i] = 1;
}
}
break;
default:
snmp_free_var(new_index->varbind);
free(new_index);
return NULL; /* Index type not supported */
}
}
/*
* Try to duplicate the new varbind for return.
*/
if ((rv = snmp_clone_varbind(new_index->varbind)) == NULL) {
snmp_free_var(new_index->varbind);
free(new_index);
return NULL;
}
/*
* Right - we've set up the new entry.
* All that remains is to link it into the tree.
* There are a number of possible cases here,
* so watch carefully.
*/
if (prev_idx_ptr) {
new_index->next_idx = prev_idx_ptr->next_idx;
new_index->next_oid = prev_idx_ptr->next_oid;
prev_idx_ptr->next_idx = new_index;
} else {
if (res == 0 && idxptr) {
new_index->next_idx = idxptr;
new_index->next_oid = idxptr->next_oid;
} else {
new_index->next_idx = NULL;
new_index->next_oid = idxptr;
}
if (prev_oid_ptr) {
while (prev_oid_ptr) {
prev_oid_ptr->next_oid = new_index;
prev_oid_ptr = prev_oid_ptr->next_idx;
}
} else
snmp_index_head = new_index;
}
return rv;
}
/*
* Release an allocated index,
* to allow it to be used elsewhere
*/
netsnmp_feature_child_of(release_index,netsnmp_unused)
#ifndef NETSNMP_FEATURE_REMOVE_RELEASE_INDEX
int
release_index(netsnmp_variable_list * varbind)
{
return (unregister_index(varbind, TRUE, NULL));
}
#endif /* NETSNMP_FEATURE_REMOVE_RELEASE_INDEX */
#ifndef NETSNMP_FEATURE_REMOVE_REMOVE_INDEX
/*
* Completely remove an allocated index,
* due to errors in the registration process.
*/
int
remove_index(netsnmp_variable_list * varbind, netsnmp_session * ss)
{
return (unregister_index(varbind, FALSE, ss));
}
#endif /* NETSNMP_FEATURE_REMOVE_REMOVE_INDEX */
void
unregister_index_by_session(netsnmp_session * ss)
{
struct snmp_index *idxptr, *idxptr2;
for (idxptr = snmp_index_head; idxptr != NULL;
idxptr = idxptr->next_oid)
for (idxptr2 = idxptr; idxptr2 != NULL;
idxptr2 = idxptr2->next_idx)
if (idxptr2->session == ss) {
idxptr2->allocated = 0;
idxptr2->session = NULL;
}
}
int
unregister_index(netsnmp_variable_list * varbind, int remember,
netsnmp_session * ss)
{
struct snmp_index *idxptr, *idxptr2;
struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
int res, res2, i;
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
NETSNMP_DS_AGENT_ROLE) == SUB_AGENT) {
return (agentx_unregister_index(ss, varbind));
}
#endif
/*
* Look for the requested OID entry
*/
prev_oid_ptr = NULL;
prev_idx_ptr = NULL;
res = 1;
res2 = 1;
for (idxptr = snmp_index_head; idxptr != NULL;
prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
idxptr->varbind->name,
idxptr->varbind->name_length)) <= 0)
break;
}
if (res != 0)
return INDEX_ERR_NOT_ALLOCATED;
if (varbind->type != idxptr->varbind->type)
return INDEX_ERR_WRONG_TYPE;
for (idxptr2 = idxptr; idxptr2 != NULL;
prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
switch (varbind->type) {
case ASN_INTEGER:
res2 =
(*varbind->val.integer -
*idxptr2->varbind->val.integer);
break;
case ASN_OCTET_STR:
i = SNMP_MIN(varbind->val_len,
idxptr2->varbind->val_len);
res2 =
memcmp(varbind->val.string,
idxptr2->varbind->val.string, i);
break;
case ASN_OBJECT_ID:
res2 =
snmp_oid_compare(varbind->val.objid,
varbind->val_len / sizeof(oid),
idxptr2->varbind->val.objid,
idxptr2->varbind->val_len /
sizeof(oid));
break;
default:
return INDEX_ERR_WRONG_TYPE; /* wrong type */
}
if (res2 <= 0)
break;
}
if (res2 != 0 || (res2 == 0 && !idxptr2->allocated)) {
return INDEX_ERR_NOT_ALLOCATED;
}
if (ss != idxptr2->session)
return INDEX_ERR_WRONG_SESSION;
/*
* If this is a "normal" index unregistration,
* mark the index entry as unused, but leave
* it in situ. This allows differentiation
* between ANY_INDEX and NEW_INDEX
*/
if (remember) {
idxptr2->allocated = 0; /* Unused index */
idxptr2->session = NULL;
return SNMP_ERR_NOERROR;
}
/*
* If this is a failed attempt to register a
* number of indexes, the successful ones
* must be removed completely.
*/
if (prev_idx_ptr) {
prev_idx_ptr->next_idx = idxptr2->next_idx;
} else if (prev_oid_ptr) {
if (idxptr2->next_idx) /* Use p_idx_ptr as a temp variable */
prev_idx_ptr = idxptr2->next_idx;
else
prev_idx_ptr = idxptr2->next_oid;
while (prev_oid_ptr) {
prev_oid_ptr->next_oid = prev_idx_ptr;
prev_oid_ptr = prev_oid_ptr->next_idx;
}
} else {
if (idxptr2->next_idx)
snmp_index_head = idxptr2->next_idx;
else
snmp_index_head = idxptr2->next_oid;
}
snmp_free_var(idxptr2->varbind);
free(idxptr2);
return SNMP_ERR_NOERROR;
}
netsnmp_feature_child_of(unregister_indexes,netsnmp_unused)
#ifndef NETSNMP_FEATURE_REMOVE_UNREGISTER_INDEXES
int
unregister_string_index(oid * name, size_t name_len, char *cp)
{
netsnmp_variable_list varbind;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_OCTET_STR;
snmp_set_var_objid(&varbind, name, name_len);
snmp_set_var_value(&varbind, (u_char *) cp, strlen(cp));
return (unregister_index(&varbind, FALSE, main_session));
}
int
unregister_int_index(oid * name, size_t name_len, int val)
{
netsnmp_variable_list varbind;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_INTEGER;
snmp_set_var_objid(&varbind, name, name_len);
varbind.val.string = varbind.buf;
varbind.val_len = sizeof(long);
*varbind.val.integer = val;
return (unregister_index(&varbind, FALSE, main_session));
}
int
unregister_oid_index(oid * name, size_t name_len,
oid * value, size_t value_len)
{
netsnmp_variable_list varbind;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
varbind.type = ASN_OBJECT_ID;
snmp_set_var_objid(&varbind, name, name_len);
snmp_set_var_value(&varbind, (u_char *) value,
value_len * sizeof(oid));
return (unregister_index(&varbind, FALSE, main_session));
}
#endif /* NETSNMP_FEATURE_REMOVE_UNREGISTER_INDEXES */
void
dump_idx_registry(void)
{
struct snmp_index *idxptr, *idxptr2;
u_char *sbuf = NULL, *ebuf = NULL;
size_t sbuf_len = 0, sout_len = 0, ebuf_len = 0, eout_len = 0;
if (snmp_index_head != NULL) {
printf("\nIndex Allocations:\n");
}
for (idxptr = snmp_index_head; idxptr != NULL;
idxptr = idxptr->next_oid) {
sout_len = 0;
if (sprint_realloc_objid(&sbuf, &sbuf_len, &sout_len, 1,
idxptr->varbind->name,
idxptr->varbind->name_length)) {
printf("%s indexes:\n", sbuf);
} else {
printf("%s [TRUNCATED] indexes:\n", sbuf);
}
for (idxptr2 = idxptr; idxptr2 != NULL;
idxptr2 = idxptr2->next_idx) {
switch (idxptr2->varbind->type) {
case ASN_INTEGER:
printf(" %ld for session %8p, allocated %d\n",
*idxptr2->varbind->val.integer, idxptr2->session,
idxptr2->allocated);
break;
case ASN_OCTET_STR:
printf(" \"%s\" for session %8p, allocated %d\n",
idxptr2->varbind->val.string, idxptr2->session,
idxptr2->allocated);
break;
case ASN_OBJECT_ID:
eout_len = 0;
if (sprint_realloc_objid(&ebuf, &ebuf_len, &eout_len, 1,
idxptr2->varbind->val.objid,
idxptr2->varbind->val_len /
sizeof(oid))) {
printf(" %s for session %8p, allocated %d\n", ebuf,
idxptr2->session, idxptr2->allocated);
} else {
printf
(" %s [TRUNCATED] for sess %8p, allocated %d\n",
ebuf, idxptr2->session, idxptr2->allocated);
}
break;
default:
printf("unsupported type (%d/0x%02x)\n",
idxptr2->varbind->type, idxptr2->varbind->type);
}
}
}
if (sbuf != NULL) {
free(sbuf);
}
if (ebuf != NULL) {
free(ebuf);
}
}
netsnmp_feature_child_of(count_indexes, netsnmp_unused)
#ifndef NETSNMP_FEATURE_REMOVE_UNUSED
unsigned long
count_indexes(oid * name, size_t namelen, int include_unallocated)
{
struct snmp_index *i = NULL, *j = NULL;
unsigned long n = 0;
for (i = snmp_index_head; i != NULL; i = i->next_oid) {
if (netsnmp_oid_equals(name, namelen,
i->varbind->name,
i->varbind->name_length) == 0) {
for (j = i; j != NULL; j = j->next_idx) {
if (j->allocated || include_unallocated) {
n++;
}
}
}
}
return n;
}
#endif /* NETSNMP_FEATURE_REMOVE_UNUSED */
#ifdef TESTING
netsnmp_variable_list varbind;
netsnmp_session main_sess, *main_session = &main_sess;
void
test_string_register(int n, char *cp)
{
varbind->name[4] = n;
if (register_string_index(varbind->name, varbind.name_length, cp) ==
NULL)
printf("allocating %s failed\n", cp);
}
void
test_int_register(int n, int val)
{
varbind->name[4] = n;
if (register_int_index(varbind->name, varbind.name_length, val) == -1)
printf("allocating %d/%d failed\n", n, val);
}
void
test_oid_register(int n, int subid)
{
netsnmp_variable_list *res;
varbind->name[4] = n;
if (subid != -1) {
varbind->val.objid[5] = subid;
res = register_oid_index(varbind->name, varbind.name_length,
varbind->val.objid,
varbind->val_len / sizeof(oid));
} else
res =
register_oid_index(varbind->name, varbind.name_length, NULL,
0);
if (res == NULL)
printf("allocating %d/%d failed\n", n, subid);
}
void
main(int argc, char argv[])
{
oid name[] = { 1, 2, 3, 4, 0 };
int i;
memset(&varbind, 0, sizeof(netsnmp_variable_list));
snmp_set_var_objid(&varbind, name, 5);
varbind->type = ASN_OCTET_STR;
/*
* Test index structure linking:
* a) sorted by OID
*/
test_string_register(20, "empty OID");
test_string_register(10, "first OID");
test_string_register(40, "last OID");
test_string_register(30, "middle OID");
/*
* b) sorted by index value
*/
test_string_register(25, "eee: empty IDX");
test_string_register(25, "aaa: first IDX");
test_string_register(25, "zzz: last IDX");
test_string_register(25, "mmm: middle IDX");
printf("This next one should fail....\n");
test_string_register(25, "eee: empty IDX"); /* duplicate */
printf("done\n");
/*
* c) test initial index linking
*/
test_string_register(5, "eee: empty initial IDX");
test_string_register(5, "aaa: replace initial IDX");
/*
* Did it all work?
*/
dump_idx_registry();
unregister_index_by_session(main_session);
/*
* Now test index allocation
* a) integer values
*/
test_int_register(110, -1); /* empty */
test_int_register(110, -1); /* append */
test_int_register(110, 10); /* append exact */
printf("This next one should fail....\n");
test_int_register(110, 10); /* exact duplicate */
printf("done\n");
test_int_register(110, -1); /* append */
test_int_register(110, 5); /* insert exact */
/*
* b) string values
*/
test_string_register(120, NULL); /* empty */
test_string_register(120, NULL); /* append */
test_string_register(120, "aaaz");
test_string_register(120, NULL); /* minor rollover */
test_string_register(120, "zzzz");
test_string_register(120, NULL); /* major rollover */
/*
* c) OID values
*/
test_oid_register(130, -1); /* empty */
test_oid_register(130, -1); /* append */
varbind->val_len = varbind.name_length * sizeof(oid);
memcpy(varbind->buf, varbind.name, varbind.val_len);
varbind->val.objid = (oid *) varbind.buf;
varbind->val_len += sizeof(oid);
test_oid_register(130, 255); /* append exact */
test_oid_register(130, -1); /* minor rollover */
test_oid_register(130, 100); /* insert exact */
printf("This next one should fail....\n");
test_oid_register(130, 100); /* exact duplicate */
printf("done\n");
varbind->val.objid = (oid *) varbind.buf;
for (i = 0; i < 6; i++)
varbind->val.objid[i] = 255;
varbind->val.objid[0] = 1;
test_oid_register(130, 255); /* set up rollover */
test_oid_register(130, -1); /* medium rollover */
for (i = 0; i < 6; i++)
varbind->val.objid[i] = 255;
varbind->val.objid[0] = 2;
test_oid_register(130, 255); /* set up rollover */
test_oid_register(130, -1); /* major rollover */
/*
* Did it all work?
*/
dump_idx_registry();
/*
* Test the various "invalid" requests
* (unsupported types, mis-matched types, etc)
*/
printf("The rest of these should fail....\n");
test_oid_register(110, -1);
test_oid_register(110, 100);
test_oid_register(120, -1);
test_oid_register(120, 100);
test_string_register(110, NULL);
test_string_register(110, "aaaa");
test_string_register(130, NULL);
test_string_register(130, "aaaa");
test_int_register(120, -1);
test_int_register(120, 1);
test_int_register(130, -1);
test_int_register(130, 1);
printf("done - this dump should be the same as before\n");
dump_idx_registry();
}
#endif