0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: Fix snmp_test.c

This commit is contained in:
Vojtech Vilimek 2024-08-15 18:23:41 +02:00
parent f871700239
commit 3c6d50c240
5 changed files with 89 additions and 62 deletions

View File

@ -18,21 +18,9 @@
#include "snmp_utils.h"
#include "mib_tree.h"
/*************************************************************************
*
* TODO: reject OIDs longer than OID_MAX_LEN in subagent.c/snmp_utils.c
*
*************************************************************************/
// TODO: limit for prefixed OID used for walking is 27 ids (32 - 4inet -1prefix
// resp. 33 - 4inet-1prefix-1empty)
// TODO test walk state stack overflow
// TODO hint for child len alloc size
static int t_oid_empty(void);
static int t_oid_compare(void);
static int t_oid_prefixize(void);
static int t_varbind_name_to_tx(void);
static int t_walk_oid_desc(void);
static int t_walk_oid_compare(void);
static int t_tree_find(void);
@ -398,49 +386,76 @@ t_oid_compare(void)
return 1;
}
static struct oid *
snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
static inline void
fix_byteorder(u32 *ids, u32 len)
{
snmp_vb_to_tx(c, oid);
struct agentx_varbind *vb = c->sr_vb_start;
bt_assert(vb->reserved == 0);
return &vb->name;
for (u32 i = 0; i < len; i++)
STORE_U32(ids[i], ids[i]);
}
/*
* t_oid_prefixize - test prefixing aspect of function snmp_vb_to_tx()
*/
static int
t_oid_prefixize(void)
int
u32cmp_bo(const u32 *cpu_native, const u32 *net_bo, u32 len)
{
lp_state tmps = { };
struct snmp_proto *snmp_proto = NULL;
for (u32 i = 0; i < len; i++)
{
if (cpu_native[i] != LOAD_U32(net_bo[i]))
return LOAD_U32(net_bo[i]) - cpu_native[i];
}
byte *buffer = tmp_alloc(SNMP_BUFFER_SIZE);
const struct snmp_pdu copy = {
return 0;
}
#define CREATE_RANDOM(gen) \
({ \
struct oid *_o = gen(); \
fix_byteorder(_o->ids, _o->n_subid); \
_o; \
})
static int
t_varbind_name_to_tx(void)
{
/* Test snmp_vb_name_to_tx() */
lp_state tmps = { };
struct snmp_proto *snmp_proto = tmp_alloc(sizeof(struct snmp_proto));
memset(snmp_proto, 0, sizeof(struct snmp_proto));
sock *s = sk_new(&root_pool);
snmp_proto->sock = s;
/* dirty hack sk_alloc_bufs() */
s->tbsize = SNMP_BUFFER_SIZE;
s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
void *buffer = s->tbuf;
struct snmp_pdu copy = {
.p = snmp_proto,
.sr_vb_start = (void *) buffer,
.buffer = buffer,
.size = SNMP_BUFFER_SIZE,
.error = AGENTX_RES_NO_ERROR,
.index = 0,
};
struct snmp_pdu c;
struct snmp_pdu c = copy;
struct oid *new;
struct agentx_varbind *vb;
lp_save(tmp_linpool, &tmps);
/* testing prefixable OIDs */
for (int test = 0; test < TESTS_NUM; test++)
{
const struct oid *oid = random_prefixable_oid();
const struct oid *oid = CREATE_RANDOM(random_prefixable_oid);
/* both LOAD_U8() and STORE_U8() are pointless as it byteorder does not
* influence single byte values.
*/
u8 subids = oid->n_subid;
u8 include = oid->include;
u32 pid = oid->ids[ARRAY_SIZE(snmp_internet)];
u32 pid = LOAD_U32(oid->ids[ARRAY_SIZE(snmp_internet)]);
/* reset to the default snmp_pdu */
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
vb = snmp_vb_name_to_tx(&c, oid);
new = &vb->name;
bt_assert(new->n_subid == subids - (ARRAY_SIZE(snmp_internet) + 1));
bt_assert(new->prefix == pid);
@ -449,11 +464,11 @@ t_oid_prefixize(void)
for (u32 i = 0; i < new->n_subid; i++)
{
bt_assert(new->ids[i] == oid->ids[i + ARRAY_SIZE(snmp_internet) + 1]);
bt_assert(new->ids[i] == LOAD_U32(oid->ids[i + ARRAY_SIZE(snmp_internet) + 1]));
}
for (u32 j = 0; j < ARRAY_SIZE(snmp_internet); j++)
bt_assert(oid->ids[j] == snmp_internet[j]);
bt_assert(LOAD_U32(oid->ids[j]) == snmp_internet[j]);
lp_restore(tmp_linpool, &tmps);
}
@ -461,18 +476,19 @@ t_oid_prefixize(void)
/* testing already prefixed OIDs */
for (int test = 0; test < TESTS_NUM; test++)
{
const struct oid *prefixed = random_prefixed_oid();
const struct oid *prefixed = CREATE_RANDOM(random_prefixed_oid);
/* reset to the default snmp_pdu */
c = copy; memset(buffer, 0, snmp_oid_size(prefixed) + 8);
struct oid *new = snmp_oid_prefixize(snmp_proto, prefixed, &c);
vb = snmp_vb_name_to_tx(&c, prefixed);
new = &vb->name;
bt_assert(new->n_subid == prefixed->n_subid);
bt_assert(new->prefix == prefixed->prefix);
bt_assert(!!new->include == !!prefixed->include);
bt_assert(new->reserved == 0);
bt_assert(!memcmp(&new->ids[0], &prefixed->ids[0], new->n_subid * sizeof(u32)));
bt_assert(!u32cmp_bo(&new->ids[0], &prefixed->ids[0], new->n_subid));
lp_restore(tmp_linpool, &tmps);
}
@ -482,14 +498,14 @@ t_oid_prefixize(void)
/* testing non-prefixable OIDs */
for (int test = 0; test < TESTS_NUM; test++)
{
const struct oid *oid = random_no_prefix_oid();
const struct oid *oid = CREATE_RANDOM(random_no_prefix_oid);
/* test that the OID is _really_ not prefixable */
if (oid->n_subid > ARRAY_SIZE(snmp_internet) &&
oid->ids[ARRAY_SIZE(snmp_internet) + 1] <= UINT8_MAX)
LOAD_U32(oid->ids[ARRAY_SIZE(snmp_internet) + 1]) <= UINT8_MAX)
{
for (u32 i = 0; i < ARRAY_SIZE(snmp_internet); i++)
if (oid->ids[i] != snmp_internet[i]) goto continue_testing;
if (LOAD_U32(oid->ids[i]) != snmp_internet[i]) goto continue_testing;
break; /* outer for loop */
}
@ -499,13 +515,14 @@ continue_testing:
/* reset to the default snmp_pdu */
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
vb = snmp_vb_name_to_tx(&c, oid);
new = &vb->name;
bt_assert(new->n_subid == oid->n_subid);
bt_assert(new->prefix == oid->prefix);
bt_assert(!!new->include == !!oid->include);
bt_assert(new->reserved == 0);
bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
bt_assert(!u32cmp_bo(&new->ids[0], &oid->ids[0], new->n_subid));
lp_restore(tmp_linpool, &tmps);
}
@ -515,15 +532,16 @@ continue_testing:
const struct oid *oid;
{
struct oid *work = random_prefixable_oid();
fix_byteorder(work->ids, work->n_subid);
/* include also the prefix ID (at index 4) */
u32 index = xrandom(ARRAY_SIZE(snmp_internet) + 1);
/* change randomly picked id at index from 0..5 (included) */
u32 random = bt_random();
if (index == ARRAY_SIZE(snmp_internet) && random > 255)
work->ids[index] = random;
work->ids[index] = VALUE_U32(random);
else if (index != ARRAY_SIZE(snmp_internet) && work->ids[index] != random)
work->ids[index] = random;
work->ids[index] = VALUE_U32(random);
else
continue;
oid = work;
@ -532,17 +550,19 @@ continue_testing:
/* reset to the default snmp_pdu */
c = copy; memset(buffer, 0, snmp_oid_size(oid) + 8);
struct oid *new = snmp_oid_prefixize(snmp_proto, oid, &c);
vb = snmp_vb_name_to_tx(&c, oid);
new = &vb->name;
bt_assert(new->n_subid == oid->n_subid);
bt_assert(new->prefix == oid->prefix);
bt_assert(!!new->include == !!oid->include);
bt_assert(new->reserved == 0);
bt_assert(!memcmp(&new->ids[0], &oid->ids[0], new->n_subid * sizeof(u32)));
bt_assert(!u32cmp_bo(&new->ids[0], &oid->ids[0], new->n_subid));
lp_restore(tmp_linpool, &tmps);
}
rfree(snmp_proto->sock);
tmp_flush();
return 1;
}
@ -1934,7 +1954,7 @@ int main(int argc, char **argv)
bt_test_suite(t_oid_empty, "Function that determines if the OID is empty");
bt_test_suite(t_oid_compare, "Function defining lexicographical order on OIDs");
bt_test_suite(t_oid_prefixize, "Function transforming OID to prefixed form");
bt_test_suite(t_varbind_name_to_tx, "Function loading OID from RX buffer with prefixation");
bt_test_suite(t_oid_ancestor, "Function finding common ancestor of two OIDs");
bt_test_suite(t_walk_to_oid, "Function transforming MIB tree walk state to OID");
bt_test_suite(t_walk_oid_desc, "Function testing relation being subtree between MIB tree walk and OID");

View File

@ -62,22 +62,22 @@ snmp_is_oid_empty(const struct oid *oid)
/*
* snmp_oid_is_prefixable - check for prefixed form conversion possibility
* @oid: object identfier to check
* @oid: Object Identifier in packet byte order to check
*
* Check if it is possible to convert @oid to prefixed form. The condition of
* that is standart .1.3.6.1 internet prefix and 5-th id that fits in one byte.
*/
inline int
snmp_oid_is_prefixable(const struct oid *oid)
snmp_pkt_oid_is_prefixable(const struct oid *oid)
{
if (oid->n_subid < 5)
if (LOAD_U8(oid->n_subid) < 5)
return 0;
for (int i = 0; i < 4; i++)
if (oid->ids[i] != snmp_internet[i])
if (LOAD_U32(oid->ids[i]) != snmp_internet[i])
return 0;
if (oid->ids[4] >= 256)
if (LOAD_U32(oid->ids[4]) >= 256)
return 0;
return 1;

View File

@ -21,7 +21,7 @@ size_t snmp_str_size(const char *str);
/* type OID - Object Identifier */
int snmp_is_oid_empty(const struct oid *oid);
int snmp_oid_is_prefixable(const struct oid *oid);
int snmp_pkt_oid_is_prefixable(const struct oid *oid);
uint snmp_oid_size(const struct oid *o);
size_t snmp_oid_size_from_len(uint n_subid);
void snmp_oid_copy(struct oid *dest, const struct oid *src);
@ -37,9 +37,16 @@ snmp_check_search_limit(const struct oid *search, const struct oid *limit)
return snmp_is_oid_empty(limit) || snmp_oid_compare(search, limit) < 0;
}
/*
* snmp_oid_is_prefixed - test if OID is prefixed
* @oid: OID to use
*
* Works for both cpu native and packet byte order.
*/
static inline int
snmp_oid_is_prefixed(const struct oid *oid)
{
/* LOAD_U8() is in both cases basic mem load */
return LOAD_U8(oid->prefix) != 0;
}

View File

@ -233,7 +233,7 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
}
/*
* snmp_vb_to_tx - create VarBind in TX buffer from RX buffer OID
* snmp_vb_name_to_tx - create VarBind in TX buffer from RX buffer OID
* @c: PDU context
* @oid: Object Identifier located in RX buffer with packet byte order
*
@ -242,7 +242,7 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
* of the name is optionally swapped to match cpu native byte order.
*/
struct agentx_varbind *
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
snmp_vb_name_to_tx(struct snmp_pdu *c, const struct oid *oid)
{
uint vb_hdr_size = snmp_varbind_header_size(oid);
(void) snmp_tbuf_reserve(c, vb_hdr_size);
@ -253,7 +253,7 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
/* Move the c->buffer so that is points at &vb->name */
vb->type = AGENTX_NULL;
if (snmp_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
if (snmp_pkt_oid_is_prefixable(oid) && !snmp_oid_is_prefixed(oid))
{
u8 subids = LOAD_U8(oid->n_subid) - 5;
ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
@ -301,7 +301,7 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
}
/* in cpu native byte order */
struct agentx_varbind *start_vb = snmp_vb_to_tx(c, start_buf);
struct agentx_varbind *start_vb = snmp_vb_name_to_tx(c, start_buf);
/* in cpu native byte order */
struct oid *end_oid = tmp_alloc(sz);

View File

@ -344,7 +344,7 @@ void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len,
void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len);
void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime);
void snmp_register_mibs(struct snmp_proto *p);
struct agentx_varbind *snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid);
struct agentx_varbind *snmp_vb_name_to_tx(struct snmp_pdu *c, const struct oid *oid);
int snmp_tbuf_reserve(struct snmp_pdu *c, size_t bytes);
static inline int