mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
SNMP: tmp -- fix byte order handling
This commit is contained in:
parent
a70ab3051f
commit
dd8d706e1b
@ -245,6 +245,7 @@ snmp_bgp4_register(struct snmp_proto *p)
|
|||||||
|
|
||||||
struct oid *oid = mb_allocz(p->pool,
|
struct oid *oid = mb_allocz(p->pool,
|
||||||
snmp_oid_size_from_len(ARRAY_SIZE(bgp_mib_prefix)));
|
snmp_oid_size_from_len(ARRAY_SIZE(bgp_mib_prefix)));
|
||||||
|
print(;
|
||||||
STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix));
|
STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix));
|
||||||
STORE_U8(oid->prefix, SNMP_MGMT);
|
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);
|
u32 tmp = ip4_to_u32(addr);
|
||||||
ASSUME(o->n_subid >= 9);
|
ASSUME(o->n_subid >= 9);
|
||||||
STORE_U32(o->ids[5], (tmp & 0xFF000000) >> 24);
|
o->ids[5] = (tmp & 0xFF000000) >> 24;
|
||||||
STORE_U32(o->ids[6], (tmp & 0x00FF0000) >> 16);
|
o->ids[6] = (tmp & 0x00FF0000) >> 16;
|
||||||
STORE_U32(o->ids[7], (tmp & 0x0000FF00) >> 8);
|
o->ids[7] = (tmp & 0x0000FF00) >> 8;
|
||||||
STORE_U32(o->ids[8], (tmp & 0x000000FF) >> 0);
|
o->ids[8] = (tmp & 0x000000FF) >> 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UNUSED
|
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)
|
**conn, const struct bgp_stats **stats, const struct bgp_config **config)
|
||||||
{
|
{
|
||||||
const struct oid * const oid = &c->sr_vb_start->name;
|
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);
|
*addr = ip4_from_oid(oid);
|
||||||
else
|
else
|
||||||
return SNMP_SEARCH_NO_INSTANCE;
|
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
|
static enum snmp_search_res
|
||||||
fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
|
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;
|
return SNMP_SEARCH_NO_INSTANCE;
|
||||||
c->size -= snmp_str_size_from_len(1);
|
c->size -= snmp_str_size_from_len(1);
|
||||||
snmp_varbind_nstr(c, BGP4_VERSIONS, 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
|
static enum snmp_search_res
|
||||||
fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
|
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;
|
return SNMP_SEARCH_NO_INSTANCE;
|
||||||
snmp_varbind_int(c, c->p->bgp_local_as);
|
snmp_varbind_int(c, c->p->bgp_local_as);
|
||||||
return SNMP_SEARCH_OK;
|
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
|
static enum snmp_search_res
|
||||||
fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
|
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;
|
return SNMP_SEARCH_NO_INSTANCE;
|
||||||
snmp_varbind_ip4(c, c->p->bgp_local_id);
|
snmp_varbind_ip4(c, c->p->bgp_local_id);
|
||||||
return SNMP_SEARCH_OK;
|
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;
|
const struct oid *peer_oid = (const struct oid *) &bgp4_peer_id;
|
||||||
|
|
||||||
int precise = 1;
|
int precise = 1;
|
||||||
if (LOAD_U8(oid->n_subid) > 9)
|
if (oid->n_subid > 9)
|
||||||
precise = 0;
|
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 old = snmp_oid_size(oid);
|
||||||
int new = snmp_oid_size(peer_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);
|
c->buffer += (new - old);
|
||||||
|
|
||||||
snmp_oid_copy(oid, peer_oid);
|
snmp_oid_copy(oid, peer_oid);
|
||||||
STORE_U8(oid->include, 1);
|
oid->include = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSUME(oid->n_subid == 9);
|
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);
|
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);
|
ip4_to_oid(oid, ip4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ mib_tree_init(pool *p, struct mib_tree *t)
|
|||||||
|
|
||||||
struct oid *oid = tmp_alloc(
|
struct oid *oid = tmp_alloc(
|
||||||
snmp_oid_size_from_len((uint) ARRAY_SIZE(snmp_internet)));
|
snmp_oid_size_from_len((uint) ARRAY_SIZE(snmp_internet)));
|
||||||
STORE_U8(oid->n_subid, ARRAY_SIZE(snmp_internet));
|
oid->n_subid = ARRAY_SIZE(snmp_internet);
|
||||||
STORE_U8(oid->prefix, 0);
|
oid->prefix = 0;
|
||||||
STORE_U8(oid->include, 0);
|
oid->include = 0;
|
||||||
STORE_U8(oid->reserved, 0);
|
oid->reserved = 0;
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(snmp_internet); i++)
|
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);
|
(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);
|
mib_tree_walk_init(&walk, t);
|
||||||
node = mib_tree_find(t, &walk, oid);
|
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)
|
if (node)
|
||||||
{
|
{
|
||||||
@ -122,7 +122,7 @@ mib_tree_add(pool *p, struct mib_tree *t, const struct oid *oid, int is_leaf)
|
|||||||
return NULL;
|
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];
|
node = walk.stack[walk.stack_pos - 1];
|
||||||
/* we encounter leaf node before end of OID's id path */
|
/* 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)
|
if (walk.stack_pos == ARRAY_SIZE(snmp_internet) + 1)
|
||||||
{
|
{
|
||||||
u32 old_len = node_inner->child_len;
|
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->children = realloc(node_inner->children,
|
||||||
node_inner->child_len * sizeof(mib_node_u *));
|
node_inner->child_len * sizeof(mib_node_u *));
|
||||||
|
|
||||||
for (u32 i = old_len; i < node_inner->child_len; i++)
|
for (u32 i = old_len; i < node_inner->child_len; i++)
|
||||||
node_inner->children[i] = NULL;
|
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 = allocz(sizeof(struct mib_leaf));
|
||||||
node->empty.flags = MIB_TREE_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.flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->empty.id = LOAD_U8(oid->prefix);
|
node->empty.id = oid->prefix;
|
||||||
/* add node into the parent's children array */
|
/* 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;
|
node_inner = &node->inner;
|
||||||
walk.stack[walk.stack_pos++] = node;
|
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 */
|
/* snmp_internet + 2 = empty + snmp_internet + prefix */
|
||||||
if (snmp_oid_is_prefixed(oid) &&
|
if (snmp_oid_is_prefixed(oid) &&
|
||||||
walk.stack_pos == ARRAY_SIZE(snmp_internet) + 2 &&
|
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)
|
mib_node_is_leaf(node) == is_leaf)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
if (mib_node_is_leaf(node))
|
if (mib_node_is_leaf(node))
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
u8 subids = LOAD_U8(oid->n_subid);
|
u8 subids = oid->n_subid;
|
||||||
u32 old_len = node_inner->child_len;
|
u32 old_len = node_inner->child_len;
|
||||||
u32 child_id = oid->ids[walk.id_pos];
|
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->children = realloc(node_inner->children,
|
||||||
node_inner->child_len * sizeof(mib_node_u *));
|
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;
|
parent->children[child_id] = (mib_node_u *) node_inner;
|
||||||
node_inner->c.id = child_id;
|
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->child_len = child_id + 1;
|
||||||
node_inner->children = allocz(node_inner->child_len * sizeof(mib_node_u *));
|
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
|
/* In any of cases below we did not move in the tree therefore the
|
||||||
* walk->id_pos is left untouched. */
|
* walk->id_pos is left untouched. */
|
||||||
if (snmp_oid_is_prefixed(oid) &&
|
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;
|
return node;
|
||||||
|
|
||||||
else if (snmp_oid_is_prefixed(oid) &&
|
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;
|
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;
|
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) */
|
/* walking the prefix continuation (OID field oid->prefix) */
|
||||||
u8 prefix = LOAD_U8(oid->prefix);
|
u8 prefix = oid->prefix;
|
||||||
if (node_inner->child_len <= prefix)
|
if (node_inner->child_len <= prefix)
|
||||||
return NULL;
|
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);
|
ASSERT(node->empty.id == prefix);
|
||||||
walk->stack[walk->stack_pos++] = node;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 subids = LOAD_U8(oid->n_subid);
|
u8 subids = oid->n_subid;
|
||||||
if (subids == 0)
|
if (subids == 0)
|
||||||
return (node == (mib_node_u *) &t->root) ? NULL : node;
|
return (node == (mib_node_u *) &t->root) ? NULL : node;
|
||||||
|
|
||||||
/* loop for all OID's ids except the last one */
|
/* 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++)
|
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)
|
if (node_inner->child_len <= id)
|
||||||
{
|
{
|
||||||
/* The walk->id_pos points after the last accepted OID 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;
|
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 ||
|
if (node_inner->child_len <= last_id ||
|
||||||
walk->stack_pos >= MIB_WALK_STACK_SIZE + 1)
|
walk->stack_pos >= MIB_WALK_STACK_SIZE + 1)
|
||||||
return NULL;
|
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 */
|
/* skip empty prefix, whole snmp_internet .1.3.6.1 and oid->prefix */
|
||||||
index = 2 + ARRAY_SIZE(snmp_internet);
|
index = 2 + ARRAY_SIZE(snmp_internet);
|
||||||
STORE_U8(result->n_subid, walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2));
|
result->n_subid = walk->stack_pos - (ARRAY_SIZE(snmp_internet) + 2);
|
||||||
STORE_U8(result->prefix,
|
result->prefix = \
|
||||||
walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id);
|
walk->stack[ARRAY_SIZE(snmp_internet) + 1]->empty.id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -608,17 +608,17 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
index = 1; /* skip empty prefix */
|
index = 1; /* skip empty prefix */
|
||||||
STORE_U8(result->n_subid, walk->stack_pos - 1);
|
result->n_subid = walk->stack_pos - 1;
|
||||||
STORE_U8(result->prefix, 0);
|
result->prefix = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
STORE_U8(result->include, 0);
|
result->include = 0;
|
||||||
STORE_U8(result->reserved, 0);
|
result->reserved = 0;
|
||||||
|
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
/* the index could point after last stack array element */
|
/* the index could point after last stack array element */
|
||||||
for (; index < walk->stack_pos && index < MIB_WALK_STACK_SIZE; index++)
|
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;
|
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;
|
uint walk_idx = 1;
|
||||||
u8 walk_subids = walk->stack_pos; /* left_subids */
|
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)
|
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++)
|
for (; i < oid_subids && walk_idx < walk_subids; i++, walk_idx++)
|
||||||
{
|
{
|
||||||
u32 walk_id = walk->stack[walk_idx]->empty.id;
|
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)
|
if (walk_id < oid_id)
|
||||||
return -1;
|
return -1;
|
||||||
else if (walk_id > oid_id)
|
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;
|
return +1;
|
||||||
|
|
||||||
if (i < walk->stack_pos &&
|
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;
|
return -1;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ids = LOAD_U8(oid->n_subid);
|
u32 ids = oid->n_subid;
|
||||||
for (; i < walk->stack_pos && j < ids; i++, j++)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +140,10 @@ void agentx_get_mib_init(pool *p)
|
|||||||
struct oid *dest = mb_alloc(p, size);
|
struct oid *dest = mb_alloc(p, size);
|
||||||
|
|
||||||
memcpy(dest, src, size);
|
memcpy(dest, src, size);
|
||||||
u8 ids = LOAD_U8(src->n_subid);
|
u8 ids = src->n_subid;
|
||||||
|
|
||||||
if (ids > 0)
|
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;
|
agentx_available_mibs[AGENTX_MIB_COUNT] = dest;
|
||||||
}
|
}
|
||||||
|
@ -783,17 +783,17 @@ t_walk_oid_desc(void)
|
|||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
/* oid is longer than walk or has same length */
|
/* 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);
|
u32 upto = MIN(OID_MAX_LEN - ids, 16);
|
||||||
|
|
||||||
if (!upto)
|
if (!upto)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 new = xrandom(upto) + 1;
|
u32 new = xrandom(upto) + 1;
|
||||||
STORE_U8(oid->n_subid, ids + new);
|
oid->n_subid = ids + new;
|
||||||
|
|
||||||
for (u32 i = 0; i < new; i++)
|
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);
|
bt_assert(mib_tree_walk_is_oid_descendant(&walk, oid) > 0);
|
||||||
|
|
||||||
@ -803,7 +803,7 @@ t_walk_oid_desc(void)
|
|||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
/* oid is shorter than walk */
|
/* oid is shorter than walk */
|
||||||
u8 ids = LOAD_U8(oid->n_subid);
|
u8 ids = oid->n_subid;
|
||||||
|
|
||||||
if (ids == 0 || ids == OID_MAX_LEN)
|
if (ids == 0 || ids == OID_MAX_LEN)
|
||||||
continue;
|
continue;
|
||||||
@ -811,14 +811,14 @@ t_walk_oid_desc(void)
|
|||||||
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
||||||
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 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++)
|
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;
|
int no_change = 1;
|
||||||
for (u32 j = 0; j < MIN(ids - split, ext); j++)
|
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;
|
no_change = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,18 +897,18 @@ t_walk_oid_compare(void)
|
|||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
/* oid is longer than walk or has same length */
|
/* 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);
|
u32 upto = MIN(OID_MAX_LEN - ids, 16);
|
||||||
|
|
||||||
if (!upto)
|
if (!upto)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
u32 new = xrandom(upto) + 1;
|
u32 new = xrandom(upto) + 1;
|
||||||
STORE_U8(oid->n_subid, ids + new);
|
oid->n_subid = ids + new;
|
||||||
ASSERT(snmp_oid_size(oid) < 1024);
|
ASSERT(snmp_oid_size(oid) < 1024);
|
||||||
|
|
||||||
for (u32 i = 0; i < new; i++)
|
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);
|
bt_assert(mib_tree_walk_oid_compare(&walk, oid) < 0);
|
||||||
@ -918,7 +918,7 @@ t_walk_oid_compare(void)
|
|||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
/* oid is shorter than walk */
|
/* oid is shorter than walk */
|
||||||
u8 ids = LOAD_U8(oid->n_subid);
|
u8 ids = oid->n_subid;
|
||||||
|
|
||||||
if (ids == 0 || ids == OID_MAX_LEN)
|
if (ids == 0 || ids == OID_MAX_LEN)
|
||||||
continue;
|
continue;
|
||||||
@ -926,13 +926,13 @@ t_walk_oid_compare(void)
|
|||||||
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
u32 split = (ids > 1) ? xrandom(ids - 1) + 1 : 0;
|
||||||
u32 ext = (type == 3) ? xrandom(MIN(OID_MAX_LEN - ids, 16)) : 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++)
|
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;
|
int cmp_res = 0;
|
||||||
for (u32 j = 0; j < MIN(ids - split, ext) && !cmp_res; j++)
|
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)
|
if (!cmp_res && split + ext == ids)
|
||||||
continue;
|
continue;
|
||||||
@ -1256,16 +1256,16 @@ gen_test_find(struct oid *(*generator)(void))
|
|||||||
}
|
}
|
||||||
else
|
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++)
|
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)
|
j >= longest_inet_pref_len)
|
||||||
{
|
{
|
||||||
longest_inet_pref->ids[j] = snmp_internet[j];
|
longest_inet_pref->ids[j] = snmp_internet[j];
|
||||||
longest_inet_pref_len = j + 1;
|
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
|
else
|
||||||
break;
|
break;
|
||||||
@ -1360,19 +1360,19 @@ gen_test_find(struct oid *(*generator)(void))
|
|||||||
last = found;
|
last = found;
|
||||||
|
|
||||||
/* test finding with walk state not pointing at the root of the tree */
|
/* 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)
|
if (subids > 0)
|
||||||
{
|
{
|
||||||
found = NULL;
|
found = NULL;
|
||||||
u32 new_ids = xrandom(subids);
|
u32 new_ids = xrandom(subids);
|
||||||
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
|
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;
|
mib_node_u *ignored UNUSED;
|
||||||
ignored = mib_tree_find(tree, &walk, oids[i]);
|
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]);
|
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))
|
if (!has_node && !snmp_oid_is_prefixed(oid))
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < MIN(ARRAY_SIZE(snmp_internet),
|
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 &&
|
if (longest_inet_pref->ids[i] != 0 &&
|
||||||
longest_inet_pref->ids[i] == oid->ids[i])
|
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;
|
has_node = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1437,19 +1437,19 @@ gen_test_find(struct oid *(*generator)(void))
|
|||||||
|
|
||||||
last = found;
|
last = found;
|
||||||
|
|
||||||
u8 subids = LOAD_U8(searched[search]->n_subid);
|
u8 subids = searched[search]->n_subid;
|
||||||
if (subids > 0)
|
if (subids > 0)
|
||||||
{
|
{
|
||||||
found = NULL;
|
found = NULL;
|
||||||
u32 new_ids = xrandom(subids);
|
u32 new_ids = xrandom(subids);
|
||||||
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
|
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;
|
mib_node_u *ignored UNUSED;
|
||||||
ignored = mib_tree_find(tree, &walk, searched[search]);
|
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]);
|
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]))
|
if (snmp_oid_is_prefixed(sorted[d]))
|
||||||
bound += 5;
|
bound += 5;
|
||||||
bound += (int)LOAD_U8(sorted[d]->n_subid);
|
bound += (int) sorted[d]->n_subid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!no_inet_prefix)
|
if (!no_inet_prefix)
|
||||||
|
@ -54,23 +54,23 @@ snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len
|
|||||||
{
|
{
|
||||||
struct oid *oid = &(*vb)->name;
|
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);
|
c->size += (oid->n_subid - len) * sizeof(u32);
|
||||||
STORE_U8(oid->n_subid, len);
|
oid->n_subid = len;
|
||||||
return oid;
|
return oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need more space */
|
/* We need more space */
|
||||||
ASSUME(len >= LOAD_U8(oid->n_subid));
|
ASSUME(len >= oid->n_subid);
|
||||||
uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32);
|
uint diff_size = (len - oid->n_subid) * sizeof(u32);
|
||||||
|
|
||||||
if (snmp_tbuf_reserve(c, diff_size))
|
if (snmp_tbuf_reserve(c, diff_size))
|
||||||
oid = &(*vb)->name;
|
oid = &(*vb)->name;
|
||||||
|
|
||||||
ASSERT(c->size >= diff_size);
|
ASSERT(c->size >= diff_size);
|
||||||
c->size -= diff_size;
|
c->size -= diff_size;
|
||||||
STORE_U8(oid->n_subid, len);
|
oid->n_subid = len;
|
||||||
return &(*vb)->name;
|
return &(*vb)->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ void
|
|||||||
snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb)
|
snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb)
|
||||||
{
|
{
|
||||||
ASSUME(vb != NULL && *vb != NULL);
|
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);
|
(void) snmp_tbuf_reserve(c, hdr_size);
|
||||||
|
|
||||||
ASSERT(c->size >= 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 */
|
/* We intentionaly ignore padding that should be zeroed */
|
||||||
if (oid != NULL)
|
if (oid != NULL)
|
||||||
return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0;
|
return oid->n_subid == 0 && oid->prefix == 0;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -119,10 +119,10 @@ snmp_oid_is_prefixable(const struct oid *oid)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
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;
|
return 0;
|
||||||
|
|
||||||
if (LOAD_U32(oid->ids[4]) >= 256)
|
if (oid->ids[4] >= 256)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -148,27 +148,12 @@ snmp_pkt_len(const byte *start, const byte *end)
|
|||||||
void
|
void
|
||||||
snmp_oid_copy(struct oid *dest, const struct oid *src)
|
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->n_subid = src->n_subid;
|
||||||
dest->prefix = src->prefix;
|
dest->prefix = src->prefix;
|
||||||
dest->include = src->include ? 1 : 0;
|
dest->include = src->include ? 1 : 0;
|
||||||
dest->reserved = 0;
|
dest->reserved = 0;
|
||||||
|
|
||||||
/* The STORE_U32() and LOAD_U32 cancel out */
|
memcpy(dest->ids, src->ids, src->n_subid * sizeof(u32));
|
||||||
memcpy(dest->ids, src->ids, LOAD_U8(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
|
* @o: object identifier to use
|
||||||
|
*
|
||||||
|
* Work for both packet and cpu native byte orders.
|
||||||
*/
|
*/
|
||||||
uint
|
uint
|
||||||
snmp_oid_size(const struct oid *o)
|
snmp_oid_size(const struct oid *o)
|
||||||
{
|
{
|
||||||
|
/* LOAD_U8() is in both cases basic mem read */
|
||||||
return 4 + (LOAD_U8(o->n_subid) * 4);
|
return 4 + (LOAD_U8(o->n_subid) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* snmp_get_size - calculate size for allocation
|
* snmp_oid_size_from_len - return size of OID with @n_subid subids in bytes
|
||||||
* @n_subid: number of ids in oid
|
* @n_subid: number of subids in ids array
|
||||||
*/
|
*/
|
||||||
inline size_t
|
inline size_t
|
||||||
snmp_oid_size_from_len(uint n_subid)
|
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);
|
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
|
* snmp_set_varbind_type - set VarBind's type field
|
||||||
* @vb: Varbind inside TX buffer
|
* @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
|
static inline uint
|
||||||
snmp_get_octet_size(const struct agentx_octet_str *str)
|
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
|
* 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.
|
* Return size including whole OID as well as the VarBind header.
|
||||||
*/
|
*/
|
||||||
uint
|
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
|
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));
|
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);
|
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)
|
if (value_size == 0)
|
||||||
return vb_header;
|
return vb_header;
|
||||||
@ -377,6 +338,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* Shouldn't happen */
|
/* Shouldn't happen */
|
||||||
|
die("getting size of VarBind with unknown type (%u)", type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +354,7 @@ snmp_varbind_size_unsafe(const struct agentx_varbind *vb)
|
|||||||
uint
|
uint
|
||||||
snmp_varbind_size(const struct agentx_varbind *vb, uint limit)
|
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))
|
if (limit < sizeof(struct agentx_varbind))
|
||||||
return 0;
|
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
|
* snmp_test_varbind - test validity of VarBind type
|
||||||
* @vb: VarBind to test
|
* @type: Type of VarBind
|
||||||
*/
|
*/
|
||||||
int
|
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 ||
|
if (type == AGENTX_INTEGER ||
|
||||||
type == AGENTX_OCTET_STRING ||
|
type == AGENTX_OCTET_STRING ||
|
||||||
type == AGENTX_NULL ||
|
type == AGENTX_NULL ||
|
||||||
@ -506,7 +465,6 @@ struct agentx_varbind *
|
|||||||
snmp_create_varbind(byte *buf, struct oid *oid)
|
snmp_create_varbind(byte *buf, struct oid *oid)
|
||||||
{
|
{
|
||||||
struct agentx_varbind *vb = (void *) buf;
|
struct agentx_varbind *vb = (void *) buf;
|
||||||
STORE_U16(vb->reserved, 0);
|
|
||||||
snmp_oid_copy(&vb->name, oid);
|
snmp_oid_copy(&vb->name, oid);
|
||||||
return vb;
|
return vb;
|
||||||
}
|
}
|
||||||
@ -519,7 +477,7 @@ snmp_create_varbind(byte *buf, struct oid *oid)
|
|||||||
int
|
int
|
||||||
snmp_valid_ip4_index(const struct oid *o, uint start)
|
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);
|
return snmp_valid_ip4_index_unsafe(o, start);
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
@ -537,7 +495,7 @@ int
|
|||||||
snmp_valid_ip4_index_unsafe(const struct oid *o, uint start)
|
snmp_valid_ip4_index_unsafe(const struct oid *o, uint start)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
if (LOAD_U32(o->ids[start + i]) >= 256)
|
if (o->ids[start + i] >= 256)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
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 */
|
/* Insert zero padding in the gap at the end */
|
||||||
for (uint i = 0; i < alen - len; i++)
|
for (uint i = 0; i < alen - len; i++)
|
||||||
STORE_U8(buf[i], '\0');
|
buf[i] = '\0';
|
||||||
|
|
||||||
return buf + (alen - len);
|
return buf + (alen - len);
|
||||||
}
|
}
|
||||||
@ -602,19 +560,6 @@ snmp_put_blank(byte *buf)
|
|||||||
return buf + 4;
|
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
|
* snmp_put_fbyte - put one padded byte to SNMP PDU transcieve buffer
|
||||||
* @buf: pointer to free buffer byte
|
* @buf: pointer to free buffer byte
|
||||||
@ -642,10 +587,10 @@ void
|
|||||||
snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
|
snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
|
||||||
{
|
{
|
||||||
u32 temp = ip4_to_u32(addr);
|
u32 temp = ip4_to_u32(addr);
|
||||||
STORE_U32(o->ids[start], temp >> 24);
|
o->ids[start] = temp >> 24;
|
||||||
STORE_U32(o->ids[start + 1], (temp >> 16) & 0xFF);
|
o->ids[start + 1] = (temp >> 16) & 0xFF;
|
||||||
STORE_U32(o->ids[start + 2], (temp >> 8) & 0xFF);
|
o->ids[start + 2] = (temp >> 8) & 0xFF;
|
||||||
STORE_U32(o->ids[start + 3], temp & 0xFF);
|
o->ids[start + 3] = temp & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -662,11 +607,11 @@ snmp_oid_ip4_index(struct oid *o, uint start, ip4_addr addr)
|
|||||||
int
|
int
|
||||||
snmp_oid_compare(const struct oid *left, const struct oid *right)
|
snmp_oid_compare(const struct oid *left, const struct oid *right)
|
||||||
{
|
{
|
||||||
const u8 left_subids = LOAD_U8(left->n_subid);
|
const u8 left_subids = left->n_subid;
|
||||||
u8 right_subids = LOAD_U8(right->n_subid); /* see hack for more info */
|
u8 right_subids = right->n_subid; /* see hack for more info */
|
||||||
|
|
||||||
const u8 left_prefix = LOAD_U8(left->prefix);
|
const u8 left_prefix = left->prefix;
|
||||||
const u8 right_prefix = LOAD_U8(right->prefix);
|
const u8 right_prefix = right->prefix;
|
||||||
|
|
||||||
if (left_prefix == 0 && right_prefix == 0)
|
if (left_prefix == 0 && right_prefix == 0)
|
||||||
goto test_ids;
|
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));
|
uint bound = MIN((uint) left_subids, (uint) ARRAY_SIZE(snmp_internet));
|
||||||
for (uint idx = 0; idx < bound; idx++)
|
for (uint idx = 0; idx < bound; idx++)
|
||||||
{
|
{
|
||||||
u32 id = LOAD_U32(left->ids[idx]);
|
u32 id = left->ids[idx];
|
||||||
if (id < snmp_internet[idx])
|
if (id < snmp_internet[idx])
|
||||||
return -1;
|
return -1;
|
||||||
else if (id > snmp_internet[idx])
|
else if (id > snmp_internet[idx])
|
||||||
@ -690,9 +635,9 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* check prefix */
|
/* check prefix */
|
||||||
if (LOAD_U32(left->ids[4]) < (u32) right_prefix)
|
if (left->ids[4] < (u32) right_prefix)
|
||||||
return -1;
|
return -1;
|
||||||
else if (LOAD_U32(left->ids[4]) > (u32) right_prefix)
|
else if (left->ids[4] > (u32) right_prefix)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* the right prefix is already checked (+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);
|
(int) right_subids);
|
||||||
for (int i = 0; i < limit; i++)
|
for (int i = 0; i < limit; i++)
|
||||||
{
|
{
|
||||||
u32 left_id = LOAD_U32(left->ids[i + ARRAY_SIZE(snmp_internet) + 1]);
|
u32 left_id = left->ids[i + ARRAY_SIZE(snmp_internet + 1)];
|
||||||
u32 right_id = LOAD_U32(right->ids[i]);
|
u32 right_id = right->ids[i];
|
||||||
if (left_id < right_id)
|
if (left_id < right_id)
|
||||||
return -1;
|
return -1;
|
||||||
else if (left_id > right_id)
|
else if (left_id > right_id)
|
||||||
@ -723,8 +668,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
|
|||||||
test_ids:
|
test_ids:
|
||||||
for (int i = 0; i < MIN(left->n_subid, right->n_subid); i++)
|
for (int i = 0; i < MIN(left->n_subid, right->n_subid); i++)
|
||||||
{
|
{
|
||||||
u32 left_id = LOAD_U32(left->ids[i]);
|
u32 left_id = left->ids[i];
|
||||||
u32 right_id = LOAD_U32(right->ids[i]);
|
u32 right_id = right->ids[i];
|
||||||
if (left_id < right_id)
|
if (left_id < right_id)
|
||||||
return -1;
|
return -1;
|
||||||
else if (left_id > right_id)
|
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);
|
c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
inline byte *
|
inline byte *
|
||||||
snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
|
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);
|
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
|
||||||
return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
|
return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* snmp_varbind_nstr - fill varbind context with octet string
|
* 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);
|
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
|
inline enum agentx_type
|
||||||
snmp_search_res_to_type(enum snmp_search_res r)
|
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);
|
ASSERT(left && right && out);
|
||||||
|
|
||||||
STORE_U8(out->include, 0);
|
out->include, 0;
|
||||||
STORE_U8(out->reserved, 0);
|
out->reserved = 0;
|
||||||
STORE_U8(out->prefix, 0);
|
out->prefix = 0;
|
||||||
|
|
||||||
u32 offset = 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);
|
int l = snmp_oid_is_prefixed(left), r = snmp_oid_is_prefixed(right);
|
||||||
if (l && r)
|
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++)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
STORE_U8(out->prefix, LOAD_U8(left->prefix));
|
out->prefix = left->prefix;
|
||||||
}
|
}
|
||||||
else if (!l && r)
|
else if (!l && r)
|
||||||
{
|
{
|
||||||
if (left_ids == 0)
|
if (left_ids == 0)
|
||||||
{
|
{
|
||||||
/* finish creating NULL OID */
|
/* finish creating NULL OID */
|
||||||
STORE_U8(out->n_subid, 0);
|
out->n_subid = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint id = 0; id < MIN(ARRAY_SIZE(snmp_internet), left_ids); id++)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
STORE_U32(out->ids[id], snmp_internet[id]);
|
out->ids[id] = snmp_internet[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left_ids <= ARRAY_SIZE(snmp_internet))
|
if (left_ids <= ARRAY_SIZE(snmp_internet))
|
||||||
{
|
{
|
||||||
STORE_U8(out->n_subid, left_ids);
|
out->n_subid = left_ids;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* index 4 is conresponding to the prefix in prefixed OID */
|
/* 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delete snmp_internet from out->ids and store OID prefix */
|
/* delete snmp_internet from out->ids and store OID prefix */
|
||||||
offset = ARRAY_SIZE(snmp_internet) + 1;
|
offset = ARRAY_SIZE(snmp_internet) + 1;
|
||||||
STORE_U8(out->n_subid, LOAD_U8(out->n_subid) - ARRAY_SIZE(snmp_internet));
|
out->n_subid = out->n_subid - ARRAY_SIZE(snmp_internet);
|
||||||
STORE_U8(out->prefix, LOAD_U8(right->prefix));
|
out->prefix = right->prefix;
|
||||||
}
|
}
|
||||||
else if (l && !r)
|
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])
|
if (left->ids[offset + id] == right->ids[id])
|
||||||
{
|
{
|
||||||
subids++;
|
subids++;
|
||||||
STORE_U32(out->ids[id], LOAD_U32(right->ids[id]));
|
out->ids[id] = right->ids[id];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
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);
|
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;
|
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;
|
const struct oid *oid = &c->sr_vb_start->name;
|
||||||
u32 skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
|
u32 skip = (walk->id_pos < oid->n_subid) ?
|
||||||
LOAD_U32(oid->ids[walk->id_pos]) : 0;
|
oid->ids[walk->id_pos] : 0;
|
||||||
while (!found && (leaf = mib_tree_walk_next_leaf(tree, walk, skip)) != NULL)
|
while (!found && (leaf = mib_tree_walk_next_leaf(tree, walk, skip)) != NULL)
|
||||||
{
|
{
|
||||||
/* mib_tree_walk_next() forces VarBind's name OID overwriting */
|
/* 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;
|
found = 1;
|
||||||
|
|
||||||
oid = &c->sr_vb_start->name;
|
oid = &c->sr_vb_start->name;
|
||||||
skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
|
skip = (walk->id_pos < oid->n_subid) ?
|
||||||
LOAD_U32(oid->ids[walk->id_pos]) : 0;
|
oid->ids[walk->id_pos] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
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)
|
if (res != SNMP_SEARCH_OK)
|
||||||
snmp_set_varbind_type(vb, snmp_search_res_to_type(res));
|
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 ||
|
ASSUME(type == leaf->type || type == AGENTX_END_OF_MIB_VIEW || type == AGENTX_NO_SUCH_OBJECT ||
|
||||||
type == AGENTX_NO_SUCH_INSTANCE);
|
type == AGENTX_NO_SUCH_INSTANCE);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ uint snmp_pkt_len(const byte *start, const byte *end);
|
|||||||
* AgentX - Variable Binding (VarBind) type utils
|
* AgentX - Variable Binding (VarBind) type utils
|
||||||
*/
|
*/
|
||||||
enum snmp_search_res snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t);
|
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);
|
int agentx_type_size(enum agentx_type t);
|
||||||
|
|
||||||
/* type Octet String */
|
/* 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);
|
void snmp_oid_copy2(struct oid *dest, const struct oid *src);
|
||||||
int snmp_oid_compare(const struct oid *first, const struct oid *second);
|
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_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
|
static inline int
|
||||||
snmp_oid_is_prefixed(const struct oid *oid)
|
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
|
* AgentX - Variable Binding (VarBind) manupulation
|
||||||
*/
|
*/
|
||||||
uint snmp_varbind_hdr_size_from_oid(const struct oid *oid);
|
uint snmp_varbind_header_size(const struct oid *vb_name);
|
||||||
uint snmp_varbind_header_size(const struct agentx_varbind *vb);
|
|
||||||
uint snmp_varbind_size(const struct agentx_varbind *vb, uint limit);
|
uint snmp_varbind_size(const struct agentx_varbind *vb, uint limit);
|
||||||
uint snmp_varbind_size_unsafe(const struct agentx_varbind *vb);
|
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);
|
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_ticks(struct snmp_pdu *c, u32 val);
|
||||||
void snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr);
|
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_nstr(struct snmp_pdu *c, const char *str, uint len);
|
||||||
|
void snmp_varbind_oid(struct snmp_pdu *c, const struct oid *oid_val);
|
||||||
|
|
||||||
/* Raw */
|
/* Raw */
|
||||||
byte *snmp_no_such_object(byte *buf, struct agentx_varbind *vb, struct oid *oid);
|
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_str(byte *buf, const char *str);
|
||||||
byte *snmp_put_nstr(byte *buf, const char *str, uint len);
|
byte *snmp_put_nstr(byte *buf, const char *str, uint len);
|
||||||
byte *snmp_put_blank(byte *buf);
|
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_ip4(byte *buf, ip4_addr ip4);
|
||||||
byte *snmp_put_fbyte(byte *buf, u8 data);
|
byte *snmp_put_fbyte(byte *buf, u8 data);
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
|
|||||||
* snmp_register_ack - handle registration response
|
* snmp_register_ack - handle registration response
|
||||||
* @p: SNMP protocol instance
|
* @p: SNMP protocol instance
|
||||||
* @res: header of agentx-Response-PDU
|
* @res: header of agentx-Response-PDU
|
||||||
* @oid: MIB subtree Object Identifier
|
* @oid: MIB subtree Object Identifier in cpu native byte order
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid)
|
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--;
|
p->registrations_to_ack--;
|
||||||
|
|
||||||
if (res->error == AGENTX_RES_NO_ERROR)
|
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
|
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->oid);
|
||||||
mb_free(reg);
|
mb_free(reg);
|
||||||
@ -172,7 +172,8 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
|
|||||||
else /* p->timeout > 255 TO_US */
|
else /* p->timeout > 255 TO_US */
|
||||||
c.buffer = snmp_put_fbyte(c.buffer, (u8) 255);
|
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);
|
c.buffer = snmp_put_str(c.buffer, cf->description);
|
||||||
|
|
||||||
s = update_packet_size(h, c.buffer);
|
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
|
* send_notify_pdu - send an agentx-Notify-PDU
|
||||||
* @p: SNMP protocol instance
|
* @p: SNMP protocol instance
|
||||||
* @oid: PDU notification Varbind name (OID)
|
* @oid: PDU notification Varbind name (OID)
|
||||||
* @data: PDU Varbind payload
|
* @data: PDU VarBind payload in packet byte order
|
||||||
* @size: PDU Varbind payload size
|
* @size: PDU VarBind payload size
|
||||||
* @include_uptime: flag enabling inclusion of sysUpTime.0 OID
|
* @include_up_time: flag enabling inclusion of sysUpTime.0 OID
|
||||||
*/
|
*/
|
||||||
void
|
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))
|
if (!snmp_is_active(p))
|
||||||
return;
|
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) \
|
uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \
|
||||||
+ size;
|
+ size;
|
||||||
|
|
||||||
if (include_uptime)
|
if (include_up_time)
|
||||||
sz += UPTIME_SIZE;
|
sz += UPTIME_SIZE;
|
||||||
|
|
||||||
/* Make sure that we have enough space in TX buffer */
|
/* 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 */
|
p->packet_id++; /* New packet id */
|
||||||
snmp_session(p, h);
|
snmp_session(p, h);
|
||||||
|
|
||||||
if (include_uptime)
|
if (include_up_time)
|
||||||
{
|
{
|
||||||
/* sysUpTime.0 oid */
|
/* sysUpTime.0 oid */
|
||||||
STATIC_OID(4) sys_up_time_0 = {
|
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,
|
.reserved = 0,
|
||||||
.ids = { SNMP_MIB_2, SNMP_SYSTEM, SNMP_SYS_UP_TIME, 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);
|
struct agentx_varbind *vb = (struct agentx_varbind *) c.buffer;
|
||||||
for (uint i = 0; i < uptime_0->n_subid; i++)
|
snmp_oid_to_buf(&vb->name, up_time_0);
|
||||||
STORE_U32(vb->name.ids[i], uptime_0->ids[i]);
|
|
||||||
|
|
||||||
/* TODO use time from last reconfiguration instead? [config->load_time] */
|
/* TODO use time from last reconfiguration instead? [config->load_time] */
|
||||||
btime uptime = current_time() - boot_time;
|
btime uptime = current_time() - boot_time;
|
||||||
snmp_varbind_ticks(&c, (uptime TO_S) / 100);
|
snmp_varbind_ticks(&c, (uptime TO_S) / 100);
|
||||||
ASSUME(snmp_test_varbind(vb));
|
|
||||||
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(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 */
|
/* 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 oid *trap_0 = (struct oid *) &snmp_trap_oid_0;
|
||||||
|
|
||||||
struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, trap_0);
|
struct agentx_varbind *trap_vb = (struct agentx_varbind *) c.buffer;
|
||||||
for (uint i = 0; i < trap_0->n_subid; i++)
|
snmp_oid_to_buf(&trap_vb->name, trap_0);
|
||||||
STORE_U32(trap_vb->name.ids[i], trap_0->ids[i]);
|
/* snmp_oid_size() works for both byte orders same */
|
||||||
trap_vb->type = AGENTX_OBJECT_ID;
|
snmp_varbind_oid(trap_vb, oid);
|
||||||
snmp_put_oid(snmp_varbind_data(trap_vb), oid);
|
|
||||||
ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb));
|
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);
|
memcpy(c.buffer, data, size);
|
||||||
ADVANCE(c.buffer, c.size, 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);
|
snmp_pdu_context(&c, p, sk);
|
||||||
|
|
||||||
#define BOUND_SIZE sizeof(u32)
|
#define BOUND_SIZE sizeof(u32)
|
||||||
/* conditional +4 for upper-bound (optinal field) */
|
|
||||||
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
|
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
|
||||||
((bound > 1) ? BOUND_SIZE : 0);
|
((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);
|
STORE_U8(ur->reserved, 0);
|
||||||
ADVANCE(c.buffer, c.size, sizeof(struct agentx_un_register_hdr));
|
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));
|
ADVANCE(c.buffer, c.size, snmp_oid_size(oid));
|
||||||
|
|
||||||
/* place upper-bound if needed */
|
/* place upper-bound if needed */
|
||||||
@ -389,8 +394,8 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
|
|||||||
p->packet_id++;
|
p->packet_id++;
|
||||||
snmp_session(p, h);
|
snmp_session(p, h);
|
||||||
|
|
||||||
snmp_put_fbyte(c.buffer, (u8) reason);
|
(void) snmp_put_fbyte(c.buffer, (u8) reason);
|
||||||
ADVANCE(c.buffer, c.size, 4);
|
ADVANCE(c.buffer, c.size, REASON_SIZE);
|
||||||
|
|
||||||
uint s = update_packet_size(h, c.buffer);
|
uint s = update_packet_size(h, c.buffer);
|
||||||
sk_send(sk, s);
|
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 */
|
uint s; /* final packat size */
|
||||||
struct agentx_response *res; /* pointer to reponse in TX buffer */
|
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;
|
struct agentx_header *h = (void *) pkt;
|
||||||
pkt += AGENTX_HEADER_SIZE;
|
pkt += AGENTX_HEADER_SIZE;
|
||||||
|
|
||||||
@ -492,11 +498,13 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
|||||||
}
|
}
|
||||||
else if (all_possible)
|
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);
|
response_err_ind(p, res, AGENTX_RES_NO_ERROR, 0);
|
||||||
}
|
}
|
||||||
else
|
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 */
|
/* 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);
|
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)
|
parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err)
|
||||||
{
|
{
|
||||||
byte *pkt = pkt_start;
|
byte *pkt = pkt_start;
|
||||||
|
/* Presence of full header is guaranteed by parse_pkt() caller */
|
||||||
struct agentx_header *h = (void *) pkt;
|
struct agentx_header *h = (void *) pkt;
|
||||||
pkt += AGENTX_HEADER_SIZE;
|
pkt += AGENTX_HEADER_SIZE;
|
||||||
uint pkt_size = LOAD_U32(h->payload);
|
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)");
|
TRACE(D_PACKETS, "SNMP received malformed set PDU (size)");
|
||||||
snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
|
snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
|
||||||
// TODO best solution for possibly malicious pkt_size
|
snmp_reset(p);
|
||||||
return AGENTX_HEADER_SIZE;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct snmp_pdu c;
|
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 */
|
/* Reset the connection on unrecoverable error */
|
||||||
if (c.error != AGENTX_RES_NO_ERROR && c.error != err)
|
if (c.error != AGENTX_RES_NO_ERROR && c.error != err)
|
||||||
|
{
|
||||||
snmp_reset(p); /* error */
|
snmp_reset(p); /* error */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return pkt - pkt_start;
|
return pkt - pkt_start;
|
||||||
}
|
}
|
||||||
@ -593,11 +605,6 @@ parse_undo_set_pdu(struct snmp_proto *p, byte *pkt)
|
|||||||
static uint
|
static uint
|
||||||
parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
|
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;
|
byte *pkt = pkt_start;
|
||||||
struct agentx_header *h = (void *) pkt;
|
struct agentx_header *h = (void *) pkt;
|
||||||
uint pkt_size = LOAD_U32(h->payload);
|
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 */
|
/* errors are dropped silently, we must not send any agentx-Response-PDU */
|
||||||
if (pkt_size != 0)
|
if (pkt_size != 0)
|
||||||
{
|
{
|
||||||
// TODO should we free even for malformed packets ??
|
|
||||||
// TODO -> check that data is not freed
|
|
||||||
return AGENTX_HEADER_SIZE;
|
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 */
|
/* No agentx-Response-PDU is sent in response to agentx-CleanupSet-PDU */
|
||||||
return pkt_size;
|
return pkt_size;
|
||||||
}
|
}
|
||||||
@ -734,7 +746,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* We reset the connection for malformed packet (Unknown packet type) */
|
/* 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);
|
snmp_reset(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -770,7 +782,10 @@ parse_response(struct snmp_proto *p, byte *res)
|
|||||||
// TODO more direct path to mib-specific code
|
// TODO more direct path to mib-specific code
|
||||||
TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error);
|
TRACE(D_PACKETS, "SNMP received agentx-Response-PDU with error %u", r->error);
|
||||||
byte *pkt = res + sizeof(struct agentx_response);
|
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);
|
snmp_register_ack(p, r, failed);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -841,7 +856,10 @@ do_response(struct snmp_proto *p, byte *pkt)
|
|||||||
case SNMP_REGISTER:;
|
case SNMP_REGISTER:;
|
||||||
pkt += AGENTX_HEADER_SIZE;
|
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);
|
snmp_register_ack(p, r, oid);
|
||||||
|
|
||||||
if (p->registrations_to_ack == 0)
|
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)
|
snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
|
||||||
{
|
{
|
||||||
u8 subids = LOAD_U8(src->n_subid) - 5;
|
dest->n_subid = LOAD_U8(src->n_subid) - 5;
|
||||||
dest->n_subid = subids;
|
dest->prefix = (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]);
|
||||||
STORE_U8(dest->prefix, (u8) LOAD_U32(src->ids[ARRAY_SIZE(snmp_internet)]));
|
dest->include = (LOAD_U8(src->include)) ? 1 : 0;
|
||||||
STORE_U8(dest->include, (LOAD_U8(src->include)) ? 1 : 0);
|
dest->reserved = 0;
|
||||||
STORE_U8(dest->reserved, 0);
|
|
||||||
|
|
||||||
/* The LOAD_U32() and STORE_U32() cancel out */
|
/* 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;
|
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
|
* @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
|
* Create a NULL initialized VarBind inside TX buffer (from @c) whose name
|
||||||
* @oid. The @oid prefixed if possible. The result is stored in @c->sr_vb_start.
|
* 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
|
void
|
||||||
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
|
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);
|
(void) snmp_tbuf_reserve(c, vb_hdr_size);
|
||||||
|
|
||||||
ASSERT(c->size >= 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;
|
u8 subids = LOAD_U8(oid->n_subid) - 5;
|
||||||
ADVANCE(c->buffer, c->size, snmp_oid_size_from_len(subids));
|
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;
|
c->sr_vb_start = vb;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADVANCE(c->buffer, c->size, snmp_oid_size(oid));
|
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;
|
c->sr_vb_start = vb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* snmp_fix_vb - fix VarBind's name OID byte order
|
* snmp_varbind_leave - transform VarBind to packet byte order
|
||||||
* @vb: VarBind to use
|
* @vb: prepared VarBind in cpu native byte order
|
||||||
*/
|
*/
|
||||||
void
|
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
|
* update_packet_size - set PDU size
|
||||||
* @start - pointer to PDU data start (excluding header size)
|
* @start: pointer to PDU data start (excluding header size)
|
||||||
* @end - pointer after the last PDU byte
|
* @end: pointer after the last PDU byte
|
||||||
*
|
*
|
||||||
* Return number of bytes in TX buffer (including header size).
|
* 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
|
// TODO deal with auto-incrementing of snmp_pdu context c.ind
|
||||||
if (err != AGENTX_RES_NO_ERROR && err != AGENTX_RES_GEN_ERROR)
|
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);
|
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,
|
STORE_U32(res->h.payload,
|
||||||
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
||||||
}
|
}
|
||||||
else if (err == AGENTX_RES_GEN_ERROR)
|
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);
|
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,
|
STORE_U32(res->h.payload,
|
||||||
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
sizeof(struct agentx_response) - AGENTX_HEADER_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -138,26 +138,6 @@ enum agentx_flags {
|
|||||||
#define LOAD_PTR(src) get_u32(ptr)
|
#define LOAD_PTR(src) get_u32(ptr)
|
||||||
#endif
|
#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 {
|
struct agentx_header {
|
||||||
u8 version;
|
u8 version;
|
||||||
u8 type;
|
u8 type;
|
||||||
@ -189,25 +169,31 @@ struct oid {
|
|||||||
u32 ids[sbids]; \
|
u32 ids[sbids]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VALUE_U32_HELPER(x) VALUE_U32(x),
|
|
||||||
#define STATIC_OID_INITIALIZER(sbids, pref, ...) \
|
#define STATIC_OID_INITIALIZER(sbids, pref, ...) \
|
||||||
{ \
|
{ \
|
||||||
.n_subid = VALUE_U8(sbids), \
|
.n_subid = sbids, \
|
||||||
.prefix = VALUE_U8(pref), \
|
.prefix = pref, \
|
||||||
.include = VALUE_U8(0), \
|
.include = 0, \
|
||||||
.reserved = VALUE_U8(0), \
|
.reserved = 0, \
|
||||||
.ids = { MACRO_FOREACH(VALUE_U32_HELPER, __VA_ARGS__) }, \
|
.ids = { __VA_ARGS__ }, \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enforced by MIB tree, see mib_tree.h for more info */
|
/* enforced by MIB tree, see mib_tree.h for more info */
|
||||||
#define OID_MAX_LEN 32
|
#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 {
|
struct agentx_varbind {
|
||||||
u16 type;
|
u16 type;
|
||||||
u16 reserved; /* always zero filled */
|
u16 reserved; /* always zero filled */
|
||||||
/* oid part */
|
/* oid part */
|
||||||
struct oid name;
|
struct oid name;
|
||||||
/* AgentX variable binding data optionaly here */
|
/* AgentX variable binding data optionally here */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct agentx_search_range {
|
struct agentx_search_range {
|
||||||
|
Loading…
Reference in New Issue
Block a user