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

SNMP: tmp -- fix byte order handling

This commit is contained in:
Vojtech Vilimek 2024-08-10 00:07:49 +02:00
parent a70ab3051f
commit dd8d706e1b
8 changed files with 294 additions and 308 deletions

View File

@ -245,6 +245,7 @@ snmp_bgp4_register(struct snmp_proto *p)
struct oid *oid = mb_allocz(p->pool,
snmp_oid_size_from_len(ARRAY_SIZE(bgp_mib_prefix)));
print(;
STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix));
STORE_U8(oid->prefix, SNMP_MGMT);
@ -284,10 +285,10 @@ ip4_to_oid(struct oid *o, ip4_addr addr)
{
u32 tmp = ip4_to_u32(addr);
ASSUME(o->n_subid >= 9);
STORE_U32(o->ids[5], (tmp & 0xFF000000) >> 24);
STORE_U32(o->ids[6], (tmp & 0x00FF0000) >> 16);
STORE_U32(o->ids[7], (tmp & 0x0000FF00) >> 8);
STORE_U32(o->ids[8], (tmp & 0x000000FF) >> 0);
o->ids[5] = (tmp & 0xFF000000) >> 24;
o->ids[6] = (tmp & 0x00FF0000) >> 16;
o->ids[7] = (tmp & 0x0000FF00) >> 8;
o->ids[8] = (tmp & 0x000000FF) >> 0;
}
static void UNUSED
@ -337,7 +338,7 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
**conn, const struct bgp_stats **stats, const struct bgp_config **config)
{
const struct oid * const oid = &c->sr_vb_start->name;
if (snmp_bgp_valid_ip4(oid) && LOAD_U8(oid->n_subid) == 9)
if (snmp_bgp_valid_ip4(oid) && oid->n_subid == 9)
*addr = ip4_from_oid(oid);
else
return SNMP_SEARCH_NO_INSTANCE;
@ -378,7 +379,7 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
static enum snmp_search_res
fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
if (c->sr_vb_start->name.n_subid != 3)
return SNMP_SEARCH_NO_INSTANCE;
c->size -= snmp_str_size_from_len(1);
snmp_varbind_nstr(c, BGP4_VERSIONS, 1);
@ -388,7 +389,7 @@ fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res
fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
if (c->sr_vb_start->name.n_subid != 3)
return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_int(c, c->p->bgp_local_as);
return SNMP_SEARCH_OK;
@ -743,7 +744,7 @@ fill_in_update_elapsed_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu
static enum snmp_search_res
fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
if (c->sr_vb_start->name.n_subid != 3)
return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_ip4(c, c->p->bgp_local_id);
return SNMP_SEARCH_OK;
@ -771,10 +772,10 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
const struct oid *peer_oid = (const struct oid *) &bgp4_peer_id;
int precise = 1;
if (LOAD_U8(oid->n_subid) > 9)
if (oid->n_subid > 9)
precise = 0;
if (LOAD_U8(oid->n_subid) != 9 || snmp_oid_compare(oid, peer_oid) < 0)
if (oid->n_subid != 9 || snmp_oid_compare(oid, peer_oid) < 0)
{
int old = snmp_oid_size(oid);
int new = snmp_oid_size(peer_oid);
@ -785,7 +786,7 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
c->buffer += (new - old);
snmp_oid_copy(oid, peer_oid);
STORE_U8(oid->include, 1);
oid->include = 1;
}
ASSUME(oid->n_subid == 9);
@ -799,9 +800,9 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
int match = trie_walk_init(&ws, c->p->bgp_trie, &net, 1);
if (match && LOAD_U8(oid->include) && precise)
if (match && oid->include && precise)
{
STORE_U8(oid->include, 0);
oid->include = 0;
ip4_to_oid(oid, ip4);
return 0;
}

View File

@ -46,13 +46,13 @@ mib_tree_init(pool *p, struct mib_tree *t)
struct oid *oid = tmp_alloc(
snmp_oid_size_from_len((uint) ARRAY_SIZE(snmp_internet)));
STORE_U8(oid->n_subid, ARRAY_SIZE(snmp_internet));
STORE_U8(oid->prefix, 0);
STORE_U8(oid->include, 0);
STORE_U8(oid->reserved, 0);
oid->n_subid = ARRAY_SIZE(snmp_internet);
oid->prefix = 0;
oid->include = 0;
oid->reserved = 0;
for (size_t i = 0; i < ARRAY_SIZE(snmp_internet); i++)
STORE_U32(oid->ids[i], snmp_internet[i]);
oid->ids[i] = snmp_internet[i];
(void) mib_tree_add(p, t, oid, 0);
}
@ -110,7 +110,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
mib_tree_walk_init(&walk, t);
node = mib_tree_find(t, &walk, oid);
ASSERT(walk.id_pos <= LOAD_U8(oid->n_subid) + 1);
ASSERT(walk.id_pos <= oid->n_subid + 1);
if (node)
{
@ -122,7 +122,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
return NULL;
}
ASSERT(walk.id_pos < LOAD_U8(oid->n_subid) + 1);
ASSERT(walk.id_pos < oid->n_subid + 1);
node = walk.stack[walk.stack_pos - 1];
/* we encounter leaf node before end of OID's id path */
@ -161,14 +161,14 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
if (walk.stack_pos == ARRAY_SIZE(snmp_internet) + 1)
{
u32 old_len = node_inner->child_len;
node_inner->child_len = MAX(old_len, (u32) LOAD_U8(oid->prefix) + 1);
node_inner->child_len = MAX(old_len, (u32) oid->prefix + 1);
node_inner->children = realloc(node_inner->children,
node_inner->child_len * sizeof(mib_node_u *));
for (u32 i = old_len; i < node_inner->child_len; i++)
node_inner->children[i] = NULL;
if (is_leaf && !LOAD_U8(oid->n_subid))
if (is_leaf && !oid->n_subid)
{
node = allocz(sizeof(struct mib_leaf));
node->empty.flags = MIB_TREE_LEAF;
@ -179,9 +179,9 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
node->empty.flags = 0;
}
node->empty.id = LOAD_U8(oid->prefix);
node->empty.id = oid->prefix;
/* add node into the parent's children array */
node_inner->children[LOAD_U8(oid->prefix)] = node;
node_inner->children[oid->prefix] = node;
node_inner = &node->inner;
walk.stack[walk.stack_pos++] = node;
}
@ -190,17 +190,17 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
/* snmp_internet + 2 = empty + snmp_internet + prefix */
if (snmp_oid_is_prefixed(oid) &&
walk.stack_pos == ARRAY_SIZE(snmp_internet) + 2 &&
LOAD_U8(oid->n_subid) == 0 &&
oid->n_subid == 0 &&
mib_node_is_leaf(node) == is_leaf)
return node;
if (mib_node_is_leaf(node))
return node;
u8 subids = LOAD_U8(oid->n_subid);
u8 subids = oid->n_subid;
u32 old_len = node_inner->child_len;
u32 child_id = oid->ids[walk.id_pos];
node_inner->child_len = MAX(old_len, LOAD_U32(child_id) + 1);
node_inner->child_len = MAX(old_len, child_id + 1);
node_inner->children = realloc(node_inner->children,
node_inner->child_len * sizeof(mib_node_u *));
@ -217,7 +217,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
parent->children[child_id] = (mib_node_u *) node_inner;
node_inner->c.id = child_id;
child_id = LOAD_U32(oid->ids[++walk.id_pos]);
child_id = oid->ids[++walk.id_pos];
node_inner->child_len = child_id + 1;
node_inner->children = allocz(node_inner->child_len * sizeof(mib_node_u *));
@ -430,14 +430,14 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc
/* In any of cases below we did not move in the tree therefore the
* walk->id_pos is left untouched. */
if (snmp_oid_is_prefixed(oid) &&
LOAD_U8(oid->n_subid) + ARRAY_SIZE(snmp_internet) + 1 == walk->id_pos)
oid->n_subid + ARRAY_SIZE(snmp_internet) + 1 == walk->id_pos)
return node;
else if (snmp_oid_is_prefixed(oid) &&
LOAD_U8(oid->n_subid) + ARRAY_SIZE(snmp_internet) + 1 > walk->id_pos)
oid->n_subid + ARRAY_SIZE(snmp_internet) + 1 > walk->id_pos)
return NULL;
else if (!snmp_oid_is_prefixed(oid) && LOAD_U8(oid->n_subid) + 1 == walk->id_pos)
else if (!snmp_oid_is_prefixed(oid) && oid->n_subid + 1 == walk->id_pos)
return node;
}
@ -470,7 +470,7 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc
}
/* walking the prefix continuation (OID field oid->prefix) */
u8 prefix = LOAD_U8(oid->prefix);
u8 prefix = oid->prefix;
if (node_inner->child_len <= prefix)
return NULL;
@ -483,18 +483,18 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc
ASSERT(node->empty.id == prefix);
walk->stack[walk->stack_pos++] = node;
if (mib_node_is_leaf(node) && LOAD_U8(oid->n_subid) > 0)
if (mib_node_is_leaf(node) && oid->n_subid > 0)
return NULL;
}
u8 subids = LOAD_U8(oid->n_subid);
u8 subids = oid->n_subid;
if (subids == 0)
return (node == (mib_node_u *) &t->root) ? NULL : node;
/* loop for all OID's ids except the last one */
for (; oid_pos < subids - 1 && walk->stack_pos < MIB_WALK_STACK_SIZE + 1; oid_pos++)
{
u32 id = LOAD_U32(oid->ids[oid_pos]);
u32 id = oid->ids[oid_pos];
if (node_inner->child_len <= id)
{
/* The walk->id_pos points after the last accepted OID id.
@ -527,7 +527,7 @@ mib_tree_find(const struct mib_tree *t, struct mib_walk_state *walk, const struc
}
walk->id_pos = oid_pos;
u32 last_id = LOAD_U32(oid->ids[oid_pos]);
u32 last_id = oid->ids[oid_pos];
if (node_inner->child_len <= last_id ||
walk->stack_pos >= MIB_WALK_STACK_SIZE + 1)
return NULL;
@ -598,9 +598,9 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32
/* skip empty prefix, whole snmp_internet .1.3.6.1 and oid->prefix */
index = 2 + ARRAY_SIZE(snmp_internet);
STORE_U8(result->n_subid, walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2));
STORE_U8(result->prefix,
walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id);
result->n_subid = walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2);
result->prefix = \
walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id;
}
else
{
@ -608,17 +608,17 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32
return 1;
index = 1; /* skip empty prefix */
STORE_U8(result->n_subid, walk->stack_pos - 1);
STORE_U8(result->prefix, 0);
result->n_subid = walk->stack_pos - 1;
result->prefix = 0;
}
STORE_U8(result->include, 0);
STORE_U8(result->reserved, 0);
result->include = 0;
result->reserved = 0;
u32 i = 0;
/* the index could point after last stack array element */
for (; index < walk->stack_pos && index < MIB_WALK_STACK_SIZE; index++)
STORE_U32(result->ids[i++], walk->stack[index]->empty.id);
result->ids[i++] = walk->stack[index]->empty.id;
return 0;
}
@ -639,9 +639,9 @@ mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *o
uint walk_idx = 1;
u8 walk_subids = walk->stack_pos; /* left_subids */
u8 oid_subids = LOAD_U8(oid->n_subid); /* right_subids */
u8 oid_subids = oid->n_subid; /* right_subids */
const u8 oid_prefix = LOAD_U8(oid->prefix);
const u8 oid_prefix = oid->prefix;
if (oid_prefix != 0)
{
@ -668,7 +668,7 @@ mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *o
for (; i < oid_subids && walk_idx < walk_subids; i++, walk_idx++)
{
u32 walk_id = walk->stack[walk_idx]->empty.id;
u32 oid_id = LOAD_U32(oid->ids[i]);
u32 oid_id = oid->ids[i];
if (walk_id < oid_id)
return -1;
else if (walk_id > oid_id)
@ -714,16 +714,16 @@ mib_tree_walk_is_oid_descendant(const struct mib_walk_state *walk, const struct
return +1;
if (i < walk->stack_pos &&
walk->stack[i]->empty.id != (u32)LOAD_U8(oid->prefix))
walk->stack[i]->empty.id != (u32) oid->prefix)
return -1;
i++;
}
u32 ids = LOAD_U8(oid->n_subid);
u32 ids = oid->n_subid;
for (; i < walk->stack_pos && j < ids; i++, j++)
{
if (walk->stack[i]->empty.id != LOAD_U32(oid->ids[j]))
if (walk->stack[i]->empty.id != oid->ids[j])
return -1;
}

View File

@ -140,10 +140,10 @@ void agentx_get_mib_init(pool *p)
struct oid *dest = mb_alloc(p, size);
memcpy(dest, src, size);
u8 ids = LOAD_U8(src->n_subid);
u8 ids = src->n_subid;
if (ids > 0)
STORE_U32(dest->ids[ids - 1], LOAD_U32(src->ids[ids - 1]) + 1);
dest->ids[ids - 1] = src->ids[ids - 1] + 1;
agentx_available_mibs[AGENTX_MIB_COUNT] = dest;
}

View File

@ -783,17 +783,17 @@ t_walk_oid_desc(void)
case 1:
{
/* oid is longer than walk or has same length */
u8 ids = LOAD_U8(oid->n_subid);
u8 ids = oid->n_subid;
u32 upto = MIN(OID_MAX_LEN - ids, 16);
if (!upto)
continue;
u32 new = xrandom(upto) + 1;
STORE_U8(oid->n_subid, ids + new);
oid->n_subid = ids + new;
for (u32 i = 0; i < new; i++)
STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID));
oid->ids[ids + i] = xrandom(OID_MAX_ID);
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oid) > 0);
@ -803,7 +803,7 @@ t_walk_oid_desc(void)
case 3:
{
/* oid is shorter than walk */
u8 ids = LOAD_U8(oid->n_subid);
u8 ids = oid->n_subid;
if (ids == 0 || ids == OID_MAX_LEN)
continue;
@ -811,14 +811,14 @@ t_walk_oid_desc(void)
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0;
STORE_U16(oid->n_subid, split + ext);
oid->n_subid = split + ext;
for (u32 i = 0; i < ext; i++)
STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID));
oid->ids[split + i] = xrandom(OID_MAX_ID);
int no_change = 1;
for (u32 j = 0; j < MIN(ids - split, ext); j++)
{
if (LOAD_U32(oid->ids[split + j]) != LOAD_U32(oids[i]->ids[split + j]))
if (oid->ids[split + j] != oids[i]->ids[split + j])
no_change = 0;
}
@ -897,18 +897,18 @@ t_walk_oid_compare(void)
case 1:
{
/* oid is longer than walk or has same length */
u8 ids = LOAD_U8(oid->n_subid);
u8 ids = oid->n_subid;
u32 upto = MIN(OID_MAX_LEN - ids, 16);
if (!upto)
continue;
u32 new = xrandom(upto) + 1;
STORE_U8(oid->n_subid, ids + new);
oid->n_subid = ids + new;
ASSERT(snmp_oid_size(oid) < 1024);
for (u32 i = 0; i < new; i++)
STORE_U32(oid->ids[ids + i], xrandom(OID_MAX_ID));
oid->ids[ids + i] = xrandom(OID_MAX_ID);
bt_assert(mib_tree_walk_oid_compare(&walk, oid) < 0);
@ -918,7 +918,7 @@ t_walk_oid_compare(void)
case 3:
{
/* oid is shorter than walk */
u8 ids = LOAD_U8(oid->n_subid);
u8 ids = oid->n_subid;
if (ids == 0 || ids == OID_MAX_LEN)
continue;
@ -926,13 +926,13 @@ t_walk_oid_compare(void)
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 0;
STORE_U16(oid->n_subid, split + ext);
oid->n_subid = split + ext;
for (u32 i = 0; i < ext; i++)
STORE_U32(oid->ids[split + i], xrandom(OID_MAX_ID));
oid->ids[split + i] = xrandom(OID_MAX_ID);
int cmp_res = 0;
for (u32 j = 0; j < MIN(ids - split, ext) && !cmp_res; j++)
cmp_res = LOAD_U32(oids[i]->ids[split + j]) - LOAD_U32(oid->ids[split + j]);
cmp_res = oids[i]->ids[split + j] - oid->ids[split + j];
if (!cmp_res && split + ext == ids)
continue;
@ -1256,16 +1256,16 @@ gen_test_find(struct oid *(*generator)(void))
}
else
{
for (uint j = 0; j < MIN(LOAD_U8(oids[i]->n_subid),
for (uint j = 0; j < MIN(oids[i]->n_subid,
ARRAY_SIZE(snmp_internet)); j++)
{
if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j] &&
if (oids[i]->ids[j] == snmp_internet[j] &&
j >= longest_inet_pref_len)
{
longest_inet_pref->ids[j] = snmp_internet[j];
longest_inet_pref_len = j + 1;
}
else if (LOAD_U32(oids[i]->ids[j]) == snmp_internet[j])
else if (oids[i]->ids[j] == snmp_internet[j])
;
else
break;
@ -1360,19 +1360,19 @@ gen_test_find(struct oid *(*generator)(void))
last = found;
/* test finding with walk state not pointing at the root of the tree */
u8 subids = LOAD_U8(oids[i]->n_subid);
u8 subids = oids[i]->n_subid;
if (subids > 0)
{
found = NULL;
u32 new_ids = xrandom(subids);
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
STORE_U8(oids[i]->n_subid, new_ids);
oids[i]->n_subid = new_ids;
mib_node_u *ignored UNUSED;
ignored = mib_tree_find(tree, &walk, oids[i]);
STORE_U8(oids[i]->n_subid, subids);
oids[i]->n_subid = subids;
found = mib_tree_find(tree, &walk, oids[i]);
@ -1410,7 +1410,7 @@ gen_test_find(struct oid *(*generator)(void))
if (!has_node && !snmp_oid_is_prefixed(oid))
{
for (uint i = 0; i < MIN(ARRAY_SIZE(snmp_internet),
LOAD_U8(oid->n_subid)); i++)
oid->n_subid); i++)
{
if (longest_inet_pref->ids[i] != 0 &&
longest_inet_pref->ids[i] == oid->ids[i])
@ -1422,7 +1422,7 @@ gen_test_find(struct oid *(*generator)(void))
}
}
if (has_node && LOAD_U8(oid->n_subid) > ARRAY_SIZE(snmp_internet))
if (has_node && oid->n_subid > ARRAY_SIZE(snmp_internet))
has_node = 0;
}
@ -1437,19 +1437,19 @@ gen_test_find(struct oid *(*generator)(void))
last = found;
u8 subids = LOAD_U8(searched[search]->n_subid);
u8 subids = searched[search]->n_subid;
if (subids > 0)
{
found = NULL;
u32 new_ids = xrandom(subids);
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
STORE_U8(searched[search]->n_subid, new_ids);
searched[search]->n_subid = new_ids;
mib_node_u *ignored UNUSED;
ignored = mib_tree_find(tree, &walk, searched[search]);
STORE_U8(searched[search]->n_subid, subids);
searched[search]->n_subid = subids;
found = mib_tree_find(tree, &walk, searched[search]);
@ -1725,7 +1725,7 @@ gen_test_traverse(struct oid *(*generator)(void))
{
if (snmp_oid_is_prefixed(sorted[d]))
bound += 5;
bound += (int)LOAD_U8(sorted[d]->n_subid);
bound += (int) sorted[d]->n_subid;
}
if (!no_inet_prefix)

View File

@ -46,7 +46,7 @@ inline void *
snmp_varbind_data(const struct agentx_varbind *vb)
{
uint name_size = snmp_oid_size(&vb->name);
return (void *)&vb->name + name_size;
return (void *) &vb->name + name_size;
}
struct oid *
@ -54,23 +54,23 @@ snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len
{
struct oid *oid = &(*vb)->name;
if (LOAD_U8(oid->n_subid) >= len)
if (oid->n_subid >= len)
{
c->size += (LOAD_U8(oid->n_subid) - len) * sizeof(u32);
STORE_U8(oid->n_subid, len);
c->size += (oid->n_subid - len) * sizeof(u32);
oid->n_subid = len;
return oid;
}
/* We need more space */
ASSUME(len >= LOAD_U8(oid->n_subid));
uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32);
ASSUME(len >= oid->n_subid);
uint diff_size = (len - oid->n_subid) * sizeof(u32);
if (snmp_tbuf_reserve(c, diff_size))
oid = &(*vb)->name;
ASSERT(c->size >= diff_size);
c->size -= diff_size;
STORE_U8(oid->n_subid, len);
oid->n_subid = len;
return &(*vb)->name;
}
@ -78,7 +78,7 @@ void
snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb)
{
ASSUME(vb != NULL && *vb != NULL);
uint hdr_size = snmp_varbind_header_size(*vb);
uint hdr_size = snmp_varbind_header_size(*vb->name);
(void) snmp_tbuf_reserve(c, hdr_size);
ASSERT(c->size >= hdr_size);
@ -100,7 +100,7 @@ snmp_is_oid_empty(const struct oid *oid)
{
/* We intentionaly ignore padding that should be zeroed */
if (oid != NULL)
return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0;
return oid->n_subid == 0 && oid->prefix == 0;
else
return 0;
}
@ -119,10 +119,10 @@ snmp_oid_is_prefixable(const struct oid *oid)
return 0;
for (int i = 0; i < 4; i++)
if (LOAD_U32(oid->ids[i]) != snmp_internet[i])
if (oid->ids[i] != snmp_internet[i])
return 0;
if (LOAD_U32(oid->ids[4]) >= 256)
if (oid->ids[4] >= 256)
return 0;
return 1;
@ -148,27 +148,12 @@ snmp_pkt_len(const byte *start, const byte *end)
void
snmp_oid_copy(struct oid *dest, const struct oid *src)
{
STORE_U8(dest->n_subid, src->n_subid);
STORE_U8(dest->prefix, src->prefix);
STORE_U8(dest->include, src->include ? 1 : 0);
STORE_U8(dest->reserved, 0);
for (int i = 0; i < LOAD_U8(src->n_subid); i++)
STORE_U32(dest->ids[i], src->ids[i]);
}
/* this function assumes enougth space inside dest is allocated */
void
snmp_oid_copy2(struct oid *dest, const struct oid *src)
{
/* The STORE_U8() and LOAD_U8() cancel out */
dest->n_subid = src->n_subid;
dest->prefix = src->prefix;
dest->include = src->include ? 1 : 0;
dest->reserved = 0;
/* The STORE_U32() and LOAD_U32 cancel out */
memcpy(dest->ids, src->ids, LOAD_U8(src->n_subid) * sizeof(u32));
memcpy(dest->ids, src->ids, src->n_subid * sizeof(u32));
}
/*
@ -235,18 +220,21 @@ snmp_str_size(const char *str)
}
/**
* snmp_oid_size - measure size of oid in bytes
* snmp_oid_size - measure size of OID in bytes
* @o: object identifier to use
*
* Work for both packet and cpu native byte orders.
*/
uint
snmp_oid_size(const struct oid *o)
{
/* LOAD_U8() is in both cases basic mem read */
return 4 + (LOAD_U8(o->n_subid) * 4);
}
/**
* snmp_get_size - calculate size for allocation
* @n_subid: number of ids in oid
/*
* snmp_oid_size_from_len - return size of OID with @n_subid subids in bytes
* @n_subid: number of subids in ids array
*/
inline size_t
snmp_oid_size_from_len(uint n_subid)
@ -254,19 +242,6 @@ snmp_oid_size_from_len(uint n_subid)
return sizeof(struct oid) + n_subid * sizeof(u32);
}
/*
* snmp_varbind_hdr_size_from_oid - return in-buffer size of VarBind
* @oid: OID used as VarBind's name
*
* This function assume @oid to be not NULL.
*/
uint
snmp_varbind_hdr_size_from_oid(const struct oid *oid)
{
ASSUME(oid);
return snmp_oid_size(oid) + OFFSETOF(struct agentx_varbind, name);
}
/*
* snmp_set_varbind_type - set VarBind's type field
* @vb: Varbind inside TX buffer
@ -308,54 +283,40 @@ snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t)
}
}
/* Internal wrapper */
static inline u16
snmp_load_varbind_type(const struct agentx_varbind *vb)
{
return LOAD_U16(vb->type);
}
/*
* snmp_get_varbind_type - loads a VarBind type
* @vb: VarBind pointer to TX buffer
*
* This function assumes VarBind with valid type, always call snmp_test_varbind
* for in TX buffer VarBinds.
*/
inline enum agentx_type
snmp_get_varbind_type(const struct agentx_varbind *vb)
{
ASSUME(snmp_test_varbind(vb));
return (enum agentx_type) snmp_load_varbind_type(vb);
}
static inline uint
snmp_get_octet_size(const struct agentx_octet_str *str)
{
return LOAD_U32(str->length);
return str->length;
}
/**
* snmp_varbind_header_size - measure size of VarBind without data in bytes
* @vb: VarBind to use
* @vb_name: VarBind OID name
*
* Return size including whole OID as well as the VarBind header.
*/
uint
snmp_varbind_header_size(const struct agentx_varbind *vb)
snmp_varbind_header_size(const struct oid *vb_name)
{
return snmp_varbind_hdr_size_from_oid(&vb->name);
ASSUME(vb_name);
return snmp_oid_size(vb_name) + OFFSETOF(struct agentx_varbind, name);
}
/*
* Beware that for octet string, using this function may be a bit tricky due to
* the different byte orders cpu native/packet
*
*
*/
uint
snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
snmp_varbind_size_unsafe(const struct agentx_varbind *vb, int is_pkt_bo)
{
ASSUME(snmp_test_varbind(vb));
enum agentx_type type = snmp_get_varbind_type(vb);
enum agentx_type type = (is_pkt_bo) ? LOAD_U16(vb->type) : vb->type;
int value_size = agentx_type_size(type);
uint vb_header = snmp_varbind_header_size(vb);
uint vb_header = snmp_varbind_header_size(&vb->name);
if (value_size == 0)
return vb_header;
@ -377,6 +338,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
default:
/* Shouldn't happen */
die("getting size of VarBind with unknown type (%u)", type);
return 0;
}
}
@ -392,7 +354,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
uint
snmp_varbind_size(const struct agentx_varbind *vb, uint limit)
{
ASSUME(snmp_test_varbind(vb));
//ASSUME(snmp_test_varbind(vb));
if (limit < sizeof(struct agentx_varbind))
return 0;
@ -457,15 +419,12 @@ snmp_varbind_size_from_len(uint n_subid, enum agentx_type type, uint len)
}
/*
* snmp_test_varbind - test validity of VarBind's type
* @vb: VarBind to test
* snmp_test_varbind - test validity of VarBind type
* @type: Type of VarBind
*/
int
snmp_test_varbind(const struct agentx_varbind *vb)
snmp_test_varbind(u16 type)
{
ASSUME(vb);
u16 type = snmp_load_varbind_type(vb);
if (type == AGENTX_INTEGER ||
type == AGENTX_OCTET_STRING ||
type == AGENTX_NULL ||
@ -506,7 +465,6 @@ struct agentx_varbind *
snmp_create_varbind(byte *buf, struct oid *oid)
{
struct agentx_varbind *vb = (void *) buf;
STORE_U16(vb->reserved, 0);
snmp_oid_copy(&vb->name, oid);
return vb;
}
@ -519,7 +477,7 @@ snmp_create_varbind(byte *buf, struct oid *oid)
int
snmp_valid_ip4_index(const struct oid *o, uint start)
{
if (start + 3 < LOAD_U8(o->n_subid))
if (start + 3 < o->n_subid)
return snmp_valid_ip4_index_unsafe(o, start);
else
return 0;
@ -537,7 +495,7 @@ int
snmp_valid_ip4_index_unsafe(const struct oid *o, uint start)
{
for (int i = 0; i < 4; i++)
if (LOAD_U32(o->ids[start + i]) >= 256)
if (o->ids[start + i] >= 256)
return 0;
return 1;
@ -561,7 +519,7 @@ snmp_put_nstr(byte *buf, const char *str, uint len)
/* Insert zero padding in the gap at the end */
for (uint i = 0; i < alen - len; i++)
STORE_U8(buf[i], '\0');
buf[i] = '\0';
return buf + (alen - len);
}
@ -602,19 +560,6 @@ snmp_put_blank(byte *buf)
return buf + 4;
}
/**
* snmp_put_oid - put oid into SNMP PDU transcieve buffer
* @buf: pointer to first free buffer byte
* @oid: object identifier to use
*/
byte *
snmp_put_oid(byte *buf, struct oid *oid)
{
struct oid *oid_buf = (void *) buf;
snmp_oid_copy(oid_buf, oid);
return buf + snmp_oid_size(oid);
}
/**
* snmp_put_fbyte - put one padded byte to SNMP PDU transcieve buffer
* @buf: pointer to free buffer byte
@ -642,10 +587,10 @@ void
snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
{
u32 temp = ip4_to_u32(addr);
STORE_U32(o->ids[start], temp >> 24);
STORE_U32(o->ids[start + 1], (temp >> 16) & 0xFF);
STORE_U32(o->ids[start + 2], (temp >> 8) & 0xFF);
STORE_U32(o->ids[start + 3], temp & 0xFF);
o->ids[start] = temp >> 24;
o->ids[start + 1] = (temp >> 16) & 0xFF;
o->ids[start + 2] = (temp >> 8) & 0xFF;
o->ids[start + 3] = temp & 0xFF;
}
@ -662,11 +607,11 @@ snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
int
snmp_oid_compare(const struct oid *left, const struct oid *right)
{
const u8 left_subids = LOAD_U8(left->n_subid);
u8 right_subids = LOAD_U8(right->n_subid); /* see hack for more info */
const u8 left_subids = left->n_subid;
u8 right_subids = right->n_subid; /* see hack for more info */
const u8 left_prefix = LOAD_U8(left->prefix);
const u8 right_prefix = LOAD_U8(right->prefix);
const u8 left_prefix = left->prefix;
const u8 right_prefix = right->prefix;
if (left_prefix == 0 && right_prefix == 0)
goto test_ids;
@ -679,7 +624,7 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
uint bound = MIN((uint) left_subids, (uint) ARRAY_SIZE(snmp_internet));
for (uint idx = 0; idx < bound; idx++)
{
u32 id = LOAD_U32(left->ids[idx]);
u32 id = left->ids[idx];
if (id < snmp_internet[idx])
return -1;
else if (id > snmp_internet[idx])
@ -690,9 +635,9 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
return -1;
/* check prefix */
if (LOAD_U32(left->ids[4]) < (u32) right_prefix)
if (left->ids[4] < (u32) right_prefix)
return -1;
else if (LOAD_U32(left->ids[4]) > (u32) right_prefix)
else if (left->ids[4] > (u32) right_prefix)
return 1;
/* the right prefix is already checked (+1) */
@ -700,8 +645,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
(int) right_subids);
for (int i = 0; i < limit; i++)
{
u32 left_id = LOAD_U32(left->ids[i + ARRAY_SIZE(snmp_internet) + 1]);
u32 right_id = LOAD_U32(right->ids[i]);
u32 left_id = left->ids[i + ARRAY_SIZE(snmp_internet + 1)];
u32 right_id = right->ids[i];
if (left_id < right_id)
return -1;
else if (left_id > right_id)
@ -723,8 +668,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
test_ids:
for (int i = 0; i < MIN(left->n_subid, right->n_subid); i++)
{
u32 left_id = LOAD_U32(left->ids[i]);
u32 right_id = LOAD_U32(right->ids[i]);
u32 left_id = left->ids[i];
u32 right_id = right->ids[i];
if (left_id < right_id)
return -1;
else if (left_id > right_id)
@ -857,6 +802,7 @@ snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr)
c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
}
#if 0
inline byte *
snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
{
@ -866,6 +812,7 @@ snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
}
#endif
/*
* snmp_varbind_nstr - fill varbind context with octet string
@ -885,6 +832,19 @@ snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len)
c->buffer = snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
}
/*
* snmp_varbind_oid - fill VarBind data with OID @oid_val
* @oid_val - Object Identifier in cpu native byte order
*
* Function puts the @oid_val to the packet byte order.
*/
void
snmp_varbind_oid(struct snmp_pdu *c, const struct oid *oid_val)
{
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OBJECT_IDENTIFIER);
snmp_oid_to_buf(snmp_varbind_data(c->sr_vb_start), oid_val);
}
inline enum agentx_type
snmp_search_res_to_type(enum snmp_search_res r)
{
@ -983,65 +943,65 @@ snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct
{
ASSERT(left && right && out);
STORE_U8(out->include, 0);
STORE_U8(out->reserved, 0);
STORE_U8(out->prefix, 0);
out->include, 0;
out->reserved = 0;
out->prefix = 0;
u32 offset = 0;
u8 left_ids = LOAD_U8(left->n_subid), right_ids = LOAD_U8(right->n_subid);
u8 left_ids = left->n_subid, right_ids = right->n_subid;
int l = snmp_oid_is_prefixed(left), r = snmp_oid_is_prefixed(right);
if (l && r)
{
if (LOAD_U8(left->prefix) != LOAD_U8(right->prefix))
if (left->prefix != right->prefix)
{
STORE_U8(out->n_subid, 4);
out->n_subid = 4;
for (uint id = 0; id < ARRAY_SIZE(snmp_internet); id++)
STORE_U32(out->ids[id], snmp_internet[id]);
out->ids[id] = snmp_internet[id];
return;
}
STORE_U8(out->prefix, LOAD_U8(left->prefix));
out->prefix = left->prefix;
}
else if (!l && r)
{
if (left_ids == 0)
{
/* finish creating NULL OID */
STORE_U8(out->n_subid, 0);
out->n_subid = 0;
return;
}
for (uint id = 0; id < MIN(ARRAY_SIZE(snmp_internet), left_ids); id++)
{
if (LOAD_U32(left->ids[id]) != snmp_internet[id])
if (left->ids[id] != snmp_internet[id])
{
STORE_U8(out->n_subid, id);
out->n_subid = id;
return;
}
STORE_U32(out->ids[id], snmp_internet[id]);
out->ids[id] = snmp_internet[id];
}
if (left_ids <= ARRAY_SIZE(snmp_internet))
{
STORE_U8(out->n_subid, left_ids);
out->n_subid = left_ids;
return;
}
/* index 4 is conresponding to the prefix in prefixed OID */
if (LOAD_U32(left->ids[4]) != (u32) LOAD_U8(right->prefix))
if (left->ids[4] != (u32) right->prefix)
{
STORE_U8(out->n_subid, ARRAY_SIZE(snmp_internet));
out->n_subid = ARRAY_SIZE(snmp_internet);
return;
}
/* delete snmp_internet from out->ids and store OID prefix */
offset = ARRAY_SIZE(snmp_internet) + 1;
STORE_U8(out->n_subid, LOAD_U8(out->n_subid) - ARRAY_SIZE(snmp_internet));
STORE_U8(out->prefix, LOAD_U8(right->prefix));
out->n_subid = out->n_subid - ARRAY_SIZE(snmp_internet);
out->prefix = right->prefix;
}
else if (l && !r)
{
@ -1057,12 +1017,12 @@ snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct
if (left->ids[offset + id] == right->ids[id])
{
subids++;
STORE_U32(out->ids[id], LOAD_U32(right->ids[id]));
out->ids[id] = right->ids[id];
}
else
break;
}
STORE_U8(out->n_subid, subids);
out->n_subid = subids;
}
/*
@ -1115,15 +1075,15 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p
found = !leaf->call_next(walk, c);
}
else if (mib_node_is_leaf(node) && LOAD_U8(c->sr_vb_start->name.include))
else if (mib_node_is_leaf(node) && c->sr_vb_start->name.include)
{
found = 1;
STORE_U8(c->sr_vb_start->name.include, 0);
c->sr_vb_start->name.include = 0;
}
const struct oid *oid = &c->sr_vb_start->name;
u32 skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
LOAD_U32(oid->ids[walk->id_pos]) : 0;
u32 skip = (walk->id_pos < oid->n_subid) ?
oid->ids[walk->id_pos] : 0;
while (!found && (leaf = mib_tree_walk_next_leaf(tree, walk, skip)) != NULL)
{
/* mib_tree_walk_next() forces VarBind's name OID overwriting */
@ -1141,8 +1101,8 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p
found = 1;
oid = &c->sr_vb_start->name;
skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
LOAD_U32(oid->ids[walk->id_pos]) : 0;
skip = (walk->id_pos < oid->n_subid) ?
oid->ids[walk->id_pos] : 0;
}
if (!found)
@ -1186,10 +1146,9 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_p
if (res != SNMP_SEARCH_OK)
snmp_set_varbind_type(vb, snmp_search_res_to_type(res));
u16 type = snmp_load_varbind_type(vb);
u16 type = vb->type;
ASSUME(type == leaf->type || type == AGENTX_END_OF_MIB_VIEW || type == AGENTX_NO_SUCH_OBJECT ||
type == AGENTX_NO_SUCH_INSTANCE);
return res;
}

View File

@ -16,7 +16,6 @@ uint snmp_pkt_len(const byte *start, const byte *end);
* AgentX - Variable Binding (VarBind) type utils
*/
enum snmp_search_res snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t);
enum agentx_type snmp_get_varbind_type(const struct agentx_varbind *vb);
int agentx_type_size(enum agentx_type t);
/* type Octet String */
@ -32,6 +31,8 @@ void snmp_oid_copy(struct oid *dest, const struct oid *src);
void snmp_oid_copy2(struct oid *dest, const struct oid *src);
int snmp_oid_compare(const struct oid *first, const struct oid *second);
void snmp_oid_common_ancestor(const struct oid *left, const struct oid *right, struct oid *result);
void snmp_oid_from_buf(struct oid *dest, const struct oid *src);
void snmp_oid_to_buf(struct oid *dest, const struct oid *src);
static inline int
snmp_oid_is_prefixed(const struct oid *oid)
@ -47,8 +48,7 @@ void snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr);
/*
* AgentX - Variable Binding (VarBind) manupulation
*/
uint snmp_varbind_hdr_size_from_oid(const struct oid *oid);
uint snmp_varbind_header_size(const struct agentx_varbind *vb);
uint snmp_varbind_header_size(const struct oid *vb_name);
uint snmp_varbind_size(const struct agentx_varbind *vb, uint limit);
uint snmp_varbind_size_unsafe(const struct agentx_varbind *vb);
size_t snmp_varbind_size_from_len(uint n_subid, enum agentx_type t, uint len);
@ -81,6 +81,7 @@ void snmp_varbind_gauge32(struct snmp_pdu *c, s64 time);
void snmp_varbind_ticks(struct snmp_pdu *c, u32 val);
void snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr);
void snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len);
void snmp_varbind_oid(struct snmp_pdu *c, const struct oid *oid_val);
/* Raw */
byte *snmp_no_such_object(byte *buf, struct agentx_varbind *vb, struct oid *oid);
@ -88,7 +89,6 @@ byte *snmp_no_such_instance(byte *buf, struct agentx_varbind *vb, struct oid *oi
byte *snmp_put_str(byte *buf, const char *str);
byte *snmp_put_nstr(byte *buf, const char *str, uint len);
byte *snmp_put_blank(byte *buf);
byte *snmp_put_oid(byte *buf, struct oid *oid);
byte *snmp_put_ip4(byte *buf, ip4_addr ip4);
byte *snmp_put_fbyte(byte *buf, u8 data);

View File

@ -77,7 +77,7 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
* snmp_register_ack - handle registration response
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @oid: MIB subtree Object Identifier
* @oid: MIB subtree Object Identifier in cpu native byte order
*/
void
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid)
@ -93,9 +93,9 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struc
p->registrations_to_ack--;
if (res->error == AGENTX_RES_NO_ERROR)
reg->reg_hook_ok(p, (const struct agentx_response *) res, reg);
reg->reg_hook_ok(p, res, reg);
else
reg->reg_hook_fail(p, (const struct agentx_response *) res, reg);
reg->reg_hook_fail(p, res, reg);
mb_free(reg->oid);
mb_free(reg);
@ -172,7 +172,8 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
else /* p->timeout > 255 TO_US */
c.buffer = snmp_put_fbyte(c.buffer, (u8) 255);
c.buffer = snmp_put_oid(c.buffer, oid);
snmp_oid_to_buf((struct oid *) c.buffer, oid);
c.buffer += snmp_oid_size(oid);
c.buffer = snmp_put_str(c.buffer, cf->description);
s = update_packet_size(h, c.buffer);
@ -184,12 +185,12 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
* send_notify_pdu - send an agentx-Notify-PDU
* @p: SNMP protocol instance
* @oid: PDU notification Varbind name (OID)
* @data: PDU Varbind payload
* @size: PDU Varbind payload size
* @include_uptime: flag enabling inclusion of sysUpTime.0 OID
* @data: PDU VarBind payload in packet byte order
* @size: PDU VarBind payload size
* @include_up_time: flag enabling inclusion of sysUpTime.0 OID
*/
void
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime)
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_up_time)
{
if (!snmp_is_active(p))
return;
@ -205,7 +206,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \
+ size;
if (include_uptime)
if (include_up_time)
sz += UPTIME_SIZE;
/* Make sure that we have enough space in TX buffer */
@ -217,7 +218,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
p->packet_id++; /* New packet id */
snmp_session(p, h);
if (include_uptime)
if (include_up_time)
{
/* sysUpTime.0 oid */
STATIC_OID(4) sys_up_time_0 = {
@ -227,17 +228,19 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
.reserved = 0,
.ids = { SNMP_MIB_2, SNMP_SYSTEM, SNMP_SYS_UP_TIME, 0 },
};
struct oid *uptime_0 = (struct oid *) &sys_up_time_0;
struct oid *up_time_0 = (struct oid *) &sys_up_time_0;
struct agentx_varbind *vb = snmp_create_varbind(c.buffer, uptime_0);
for (uint i = 0; i < uptime_0->n_subid; i++)
STORE_U32(vb->name.ids[i], uptime_0->ids[i]);
struct agentx_varbind *vb = (struct agentx_varbind *) c.buffer;
snmp_oid_to_buf(&vb->name, up_time_0);
/* TODO use time from last reconfiguration instead? [config->load_time] */
btime uptime = current_time() - boot_time;
snmp_varbind_ticks(&c, (uptime TO_S) / 100);
ASSUME(snmp_test_varbind(vb));
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(vb));
STORE_U16(vb->type, vb->type);
/* We do not need to call the snmp_varbind_leave() because we used
* the packet byte order in the first place.
*/
}
/* snmpTrapOID.0 oid */
@ -250,12 +253,15 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
};
struct oid *trap_0 = (struct oid *) &snmp_trap_oid_0;
struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, trap_0);
for (uint i = 0; i < trap_0->n_subid; i++)
STORE_U32(trap_vb->name.ids[i], trap_0->ids[i]);
trap_vb->type = AGENTX_OBJECT_ID;
snmp_put_oid(snmp_varbind_data(trap_vb), oid);
struct agentx_varbind *trap_vb = (struct agentx_varbind *) c.buffer;
snmp_oid_to_buf(&trap_vb->name, trap_0);
/* snmp_oid_size() works for both byte orders same */
snmp_varbind_oid(trap_vb, oid);
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb));
STORE_U16(trap_vb, trap_vb);
/* We do not need to call the snmp_varbind_leave() because we used the packet
* byte order in the first place.
*/
memcpy(c.buffer, data, size);
ADVANCE(c.buffer, c.size, size);
@ -298,7 +304,6 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
snmp_pdu_context(&c, p, sk);
#define BOUND_SIZE sizeof(u32)
/* conditional +4 for upper-bound (optinal field) */
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
((bound > 1) ? BOUND_SIZE : 0);
@ -321,7 +326,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
STORE_U8(ur->reserved, 0);
ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr));
(void) snmp_put_oid(c.buffer, oid);
snmp_oid_to_buf((struct oid *) c.buffer, oid);
ADVANCE(c.buffer, c.size, snmp_oid_size(oid));
/* place upper-bound if needed */
@ -389,8 +394,8 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
p->packet_id++;
snmp_session(p, h);
snmp_put_fbyte(c.buffer, (u8) reason);
ADVANCE(c.buffer, c.size, 4);
(void) snmp_put_fbyte(c.buffer, (u8) reason);
ADVANCE(c.buffer, c.size, REASON_SIZE);
uint s = update_packet_size(h, c.buffer);
sk_send(sk, s);
@ -466,6 +471,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
uint s; /* final packat size */
struct agentx_response *res; /* pointer to reponse in TX buffer */
/* Presence of full header is guaranteed by parse_pkt() caller */
struct agentx_header *h = (void *) pkt;
pkt += AGENTX_HEADER_SIZE;
@ -492,11 +498,13 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
}
else if (all_possible)
{
/* All values in the agentx-TestSet-PDU are OK, realy to commit them */
response_err_ind(p, res, AGENTX_RES_NO_ERROR, 0);
}
else
{
TRACE(D_PACKETS, "SNMP SET action failed (not writable)");
// Currently the only reachable branch
//TRACE(D_PACKETS, "SNMP SET action failed (not writable)");
/* This is a recoverable error, we do not need to reset the connection */
response_err_ind(p, res, AGENTX_RES_NOT_WRITABLE, c.index + 1);
}
@ -517,6 +525,7 @@ static uint
parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err)
{
byte *pkt = pkt_start;
/* Presence of full header is guaranteed by parse_pkt() caller */
struct agentx_header *h = (void *) pkt;
pkt += AGENTX_HEADER_SIZE;
uint pkt_size = LOAD_U32(h->payload);
@ -525,8 +534,8 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
{
TRACE(D_PACKETS, "SNMP received malformed set PDU (size)");
snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
// TODO best solution for possibly malicious pkt_size
return AGENTX_HEADER_SIZE;
snmp_reset(p);
return 0;
}
struct snmp_pdu c;
@ -546,7 +555,10 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
/* Reset the connection on unrecoverable error */
if (c.error != AGENTX_RES_NO_ERROR && c.error != err)
{
snmp_reset(p); /* error */
return 0;
}
return pkt - pkt_start;
}
@ -593,11 +605,6 @@ parse_undo_set_pdu(struct snmp_proto *p, byte *pkt)
static uint
parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
{
TRACE(D_PACKETS, "SNMP received agentx-CleanupSet-PDU");
(void)p;
// TODO don't forget to free resources allocated by parse_test_set_pdu()
//mb_free(p->tr);
byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt;
uint pkt_size = LOAD_U32(h->payload);
@ -605,11 +612,16 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
/* errors are dropped silently, we must not send any agentx-Response-PDU */
if (pkt_size != 0)
{
// TODO should we free even for malformed packets ??
// TODO -> check that data is not freed
return AGENTX_HEADER_SIZE;
TRACE(D_PACKET, "SNMP received malformed agentx-CleanupSet-PDU");
snmp_reset(p);
return 0;
}
TRACE(D_PACKETS, "SNMP received agentx-CleanupSet-PDU");
(void)p;
// TODO don't forget to free resources allocated by parse_test_set_pdu()
//mb_free(p->tr);
/* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */
return pkt_size;
}
@ -734,7 +746,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
default:
/* We reset the connection for malformed packet (Unknown packet type) */
TRACE(D_PACKETS, "SNMP received unknown packet with type %u", LOAD_U8(h->type));
TRACE(D_PACKETS, "SNMP received unknown packet type (%u)", LOAD_U8(h->type));
snmp_reset(p);
return 0;
}
@ -770,7 +782,10 @@ parse_response(struct snmp_proto *p, byte *res)
// TODO more direct path to mib-specific code
TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error);
byte *pkt = res + sizeof(struct agentx_response);
struct oid *failed = (struct oid *) pkt;
const struct oid *failed_buf = (struct oid *) pkt;
uint failed_size = snmp_oid_size(failed_buf);
struct oid *failed = tmp_alloc(failed_size);
snmp_oid_from_buf(failed, failed_buf);
snmp_register_ack(p, r, failed);
break;
@ -841,7 +856,10 @@ do_response(struct snmp_proto *p, byte *pkt)
case SNMP_REGISTER:;
pkt += AGENTX_HEADER_SIZE;
const struct oid *oid = (struct oid *) pkt;
const struct oid *oid_buf = (struct oid *) pkt;
uint oid_size = snmp_oid_size(oid_buf);
struct oid *oid = tmp_alloc(oid_size);
snmp_oid_from_buf(oid, oid_buf);
snmp_register_ack(p, r, oid);
if (p->registrations_to_ack == 0)
@ -859,33 +877,44 @@ do_response(struct snmp_proto *p, byte *pkt)
}
}
static inline struct oid *
/*
* snmp_oid_prefixize_unsafe - normalize OID to prefixed form
* @dest: destination for normalized OID in native byte order
* @src: source OID in packet byte order
*
* Note that again, snmp_oid_prefixize_unsafe is intended to copy Object
* Identifier from RX buffer to TX buffer but also optionally swap the byte
* order from packet b.o. to cpu native b.o. This is done to simplify the code
* dealing with OIDs.
*/
static inline void
snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
{
u8 subids = LOAD_U8(src->n_subid) - 5;
dest->n_subid = subids;
STORE_U8(dest->prefix, (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]));
STORE_U8(dest->include, (LOAD_U8(src->include)) ? 1 : 0);
STORE_U8(dest->reserved, 0);
dest->n_subid = LOAD_U8(src->n_subid) - 5;
dest->prefix = (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]);
dest->include = (LOAD_U8(src->include)) ? 1 : 0;
dest->reserved = 0;
/* The LOAD_U32() and STORE_U32() cancel out */
memcpy(&dest->ids[0], &src->ids[5], subids * sizeof(u32));
for (i = 0; i < dest->n_subid; i++)
dest->ids[i] = LOAD_U32(src->ids[i + 5]);
return dest;
}
/*
* snmp_vb_to_tx - create varbind from RX buffer OID
* snmp_vb_to_tx - create VarBind in TX buffer from RX buffer OID
* @c: PDU context
* @oid: object identifier located in RX buffer
* @oid: Object Identifier located in RX buffer with packet byte order
*
* Create NULL initialized VarBind inside TX buffer (from @c) whose vb->name is
* @oid. The @oid prefixed if possible. The result is stored in @c->sr_vb_start.
* Create a NULL initialized VarBind inside TX buffer (from @c) whose name
* is @oid. Because we want to simplify code dealing with OIDs, the byte order
* of the name is optionally swapped to match cpu native byte order.
*/
void
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
{
uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid);
uint vb_hdr_size = snmp_varbind_header_size(oid);
(void) snmp_tbuf_reserve(c, vb_hdr_size);
ASSERT(c->size >= vb_hdr_size);
@ -898,32 +927,43 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
{
u8 subids = LOAD_U8(oid->n_subid) - 5;
ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
(void) snmp_oid_prefixize_unsafe(&vb->name, oid);
snmp_oid_prefixize_unsafe(&vb->name, oid);
c->sr_vb_start = vb;
return;
}
ADVANCE(c->buffer, c->size, snmp_oid_size(oid));
snmp_oid_copy2(&vb->name, oid);
snmp_oid_from_buf(&vb->name, oid);
c->sr_vb_start = vb;
}
/*
* snmp_fix_vb - fix VarBind's name OID byte order
* @vb: VarBind to use
* snmp_varbind_leave - transform VarBind to packet byte order
* @vb: prepared VarBind in cpu native byte order
*/
void
snmp_fix_vb(struct agentx_varbind *vb)
snmp_varbind_leave(struct agentx_varbind *vb)
{
snmp_oid_copy(&vb->name, &vb->name);
STORE_U16(vb->type, vb->type);
/* Does nothing */
STORE_U16(vb->reserved, 0);
struct oid *oid = &vb->name;
STORE_U8(oid->n_subid, oid->n_subid);
STORE_U8(oid->prefix, oid->prefix);
STORE_U8(oid->include, oid->include);
STORE_U8(oid->reserved, 0);
for (u8 i = 0; i < oid->n_subid; i++)
STORE_U32(oid->ids[i], oid->ids[i]);
}
/*
* update_packet_size - set PDU size
* @start - pointer to PDU data start (excluding header size)
* @end - pointer after the last PDU byte
* @start: pointer to PDU data start (excluding header size)
* @end: pointer after the last PDU byte
*
* Return number of bytes in TX buffer (including header size).
*/
@ -952,17 +992,17 @@ response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_
// TODO deal with auto-incrementing of snmp_pdu context c.ind
if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_GEN_ERROR)
{
TRACE(D_PACKETS, "Last PDU resulted in error %u", err);
//TRACE(D_PACKETS, "Last PDU resulted in error %u", err);
STORE_U16(res->index, ind);
TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload));
/* Reset VarBindList to null */
STORE_U32(res->h.payload,
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
}
else if (err == AGENTX_RES_GEN_ERROR)
{
TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err);
//TRACE(D_PACKETS, "Last PDU resulted in error %u genErr", err);
STORE_U16(res->index, 0);
TRACE(D_PACKETS, "Storing packet size %u (was %u)", sizeof(struct agentx_response) - AGENTX_HEADER_SIZE, LOAD_U32(res->h.payload));
/* Reset VarBindList to null */
STORE_U32(res->h.payload,
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
}

View File

@ -138,26 +138,6 @@ enum agentx_flags {
#define LOAD_PTR(src) get_u32(ptr)
#endif
#define LOAD_STR(/* byte * */buf, str, length) ({ \
length = LOAD_PTR(buf); \
length > 0 ? (str = buf + 4) : (str = NULL); })
#define COPY_STR(proto, buf, str, length) ({ \
length = LOAD_PTR(buf); \
str = mb_alloc(proto->pool, length + 1); \
memcpy(str, buf+4, length); \
str[length] = '\0'; /* set term. char */ \
buf += 4 + snmp_str_size_from_len(length); })
#define SNMP_PUT_OID(buf, size, oid) \
({ \
struct agentx_varbind *vb = (void *) buf; \
SNMP_FILL_VARBIND(vb, oid); \
})
#define SNMP_FILL_VARBIND(vb, oid) \
snmp_oid_copy(&(vb)->name, (oid)), snmp_oid_size((oid))
struct agentx_header {
u8 version;
u8 type;
@ -189,25 +169,31 @@ struct oid {
u32 ids[sbids]; \
}
#define VALUE_U32_HELPER(x) VALUE_U32(x),
#define STATIC_OID_INITIALIZER(sbids, pref, ...) \
{ \
.n_subid = VALUE_U8(sbids), \
.prefix = VALUE_U8(pref), \
.include = VALUE_U8(0), \
.reserved = VALUE_U8(0), \
.ids = { MACRO_FOREACH(VALUE_U32_HELPER, __VA_ARGS__) }, \
.n_subid = sbids, \
.prefix = pref, \
.include = 0, \
.reserved = 0, \
.ids = { __VA_ARGS__ }, \
}
/* enforced by MIB tree, see mib_tree.h for more info */
#define OID_MAX_LEN 32
/*
* AgentX VarBind -- Variable Binding
* During the processing of the VarBind, the fields @type and @name are in cpu
* native byte order. This should be fixed by running snmp_varbind_leave()
* before VarBind control pointer abondonment or before packet transmission.
* The data following the structure should always follow the packet byte order.
*/
struct agentx_varbind {
u16 type;
u16 reserved; /* always zero filled */
/* oid part */
struct oid name;
/* AgentX variable binding data optionaly here */
/* AgentX variable binding data optionally here */
};
struct agentx_search_range {