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

SNMP: tmp

This commit is contained in:
Vojtech Vilimek 2024-07-09 16:30:04 +02:00
parent a67b00a0cf
commit 5ef5b19dae
5 changed files with 146 additions and 26 deletions

View File

@ -603,7 +603,7 @@ populate_bgp4(struct snmp_data *d, ip4_addr *addr, const struct bgp_proto **prot
**conn, const struct bgp_stats **stats, const struct bgp_config **config)
{
const struct oid * const oid = &d->c->sr_vb_start->name;
if (snmp_bgp_valid_ip4(oid))
if (snmp_bgp_valid_ip4(oid) && LOAD_U8(oid->n_subid) == 9)
*addr = ip4_from_oid(oid);
else
{
@ -649,6 +649,8 @@ static enum snmp_search_res
fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_data *d)
{
snmp_log("fill ver");
if (LOAD_U8(d->c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE;
d->c->size -= snmp_str_size_from_len(1);
snmp_varbind_nstr(d->c, BGP4_VERSIONS, 1);
return SNMP_SEARCH_OK;
@ -658,6 +660,8 @@ static enum snmp_search_res
fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_data *d)
{
snmp_log("fill as");
if (LOAD_U8(d->c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_int(d->c, d->p->bgp_local_as);
return SNMP_SEARCH_OK;
}
@ -1040,6 +1044,8 @@ static enum snmp_search_res
fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_data *d)
{
snmp_log("fill local id");
if (LOAD_U8(d->c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_ip4(d->c, d->p->bgp_local_id);
return SNMP_SEARCH_OK;
}
@ -1695,8 +1701,6 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data)
//struct agentx_varbind *vb = data->c->sr_vb_start;
struct oid *oid = &data->c->sr_vb_start->name;
ip4_addr ip4 = ip4_from_oid(oid);
/* BGP4-MIB::bgpPeerIdentifier */
STATIC_OID(9) bgp4_peer_id = {
.n_subid = 9,
@ -1708,12 +1712,16 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data)
/* IP4_NONE */ 0, 0, 0, 0 }
};
ip4_addr ip4 = ip4_from_oid(oid);
const struct oid *peer_oid = (const struct oid *) &bgp4_peer_id;
if (snmp_oid_compare(oid, peer_oid) < 0 || LOAD_U8(oid->n_subid) < 9)
{
die("unreachable?");
int precise = 1;
if (LOAD_U8(oid->n_subid) > 9)
precise = 0;
if (LOAD_U8(oid->n_subid) != 9 || snmp_oid_compare(oid, peer_oid) < 0)
{
int old = snmp_oid_size(oid);
int new = snmp_oid_size(peer_oid);
@ -1721,18 +1729,21 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data)
{
snmp_log("bgp4_next_peer small buffer");
snmp_manage_tbuf(data->p, data->c);
oid = &data->c->sr_vb_start->name; // TODO fix sr_vb_start in manage_tbuf
}
if (new > old)
data->c->buffer += (new - old);
data->c->buffer += (new - old);
snmp_oid_copy(oid, peer_oid);
STORE_U8(oid->include, 1);
}
ASSUME(oid->n_subid == 9);
/* +1 includes empty prefix */
/* full path BGP4-MIB::bgpPeerEntry.x: .1.3.6.1.2.1.15.3.1.x
* index offset = ARRAY_SIZE(snmp_internet) + 1 <prefix> + 4 + 1 <identifier x> */
ASSUME(state->stack_pos > 10);
oid->ids[4] = state->stack[10]->empty.id;
net_addr net;
net_fill_ip4(&net, ip4, IP4_MAX_PREFIX_LENGTH);
@ -1740,7 +1751,7 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data)
int match = trie_walk_init(&ws, data->p->bgp_trie, &net, 1);
if (match && LOAD_U8(oid->include))
if (match && LOAD_U8(oid->include) && precise)
{
STORE_U8(oid->include, 0);
ip4_to_oid(oid, ip4);
@ -1860,7 +1871,7 @@ snmp_bgp4_start(struct snmp_proto *p)
leaf = &node->leaf;
leaf->filler = leafs[i].filler;
leaf->call_next = NULL; // TODO
leaf->call_next = NULL;
leaf->type = leafs[i].type;
leaf->size = leafs[i].size;
}

View File

@ -623,6 +623,68 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32
return 0;
}
/*
* return -1 if walk_oid < oid
* return 0 if walk_oid == oid
* return +1 if walk_oid > oid
*
*/
// TODO tests
int
mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *oid)
{
/* code is very similar to snmp_oid_compare() */
if (!walk->stack_pos)
return -1;
uint walk_idx = 1;
u8 walk_subids = walk->stack_pos; /* left_subids */
u8 oid_subids = LOAD_U8(oid->n_subid); /* right_subids */
const u8 oid_prefix = LOAD_U8(oid->prefix);
if (oid_prefix != 0)
{
for (; walk_idx < walk_subids && walk_idx < ARRAY_SIZE(snmp_internet) + 1; walk_idx++)
{
u32 id = walk->stack[walk_idx]->empty.id;
if (id < snmp_internet[walk_idx - 1])
return -1;
else if (id > snmp_internet[walk_idx - 1])
return 1;
}
if (walk_idx == walk_subids)
return 1;
const u8 walk_prefix = walk->stack[walk_idx++]->empty.id;
if (walk_prefix < oid_prefix)
return -1;
else if (walk_prefix > oid_prefix)
return 1;
}
uint i = 0;
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]);
if (walk_id < oid_id)
return -1;
else if (walk_id > oid_id)
return 1;
}
if (walk_idx == walk_subids && i == oid_subids)
return 0;
else if (walk_idx == walk_subids)
return -1;
else /* if (i == oid_subids) */
return 1;
}
/**
* mib_tree_walk_is_oid_descendant - check if OID is in walk subtree
* @walk: MIB tree walk state
@ -727,7 +789,7 @@ mib_tree_walk_next(const struct mib_tree *t, struct mib_walk_state *walk)
}
struct mib_leaf *
mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk)
mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk, u32 skip)
{
(void)t;
@ -737,7 +799,7 @@ mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk)
return NULL;
}
u32 next_id = 0;
u32 next_id = skip;
mib_node_u *node = walk->stack[walk->stack_pos - 1];
if (mib_node_is_leaf(node) && walk->stack_pos > 1)

View File

@ -102,13 +102,14 @@ void mib_tree_init(pool *p, struct mib_tree *t);
// TODO: remove need for argument include_root
void mib_tree_walk_init(struct mib_walk_state *state, const struct mib_tree *t);
int mib_tree_walk_to_oid(const struct mib_walk_state *state, struct oid *result, u32 subids);
int mib_tree_walk_oid_compare(const struct mib_walk_state *state, const struct oid *oid);
mib_node_u *mib_tree_add(pool *p, struct mib_tree *tree, const struct oid *oid, int is_leaf);
int mib_tree_remove(struct mib_tree *t, const struct oid *oid);
int mib_tree_delete(struct mib_tree *t, struct mib_walk_state *state);
mib_node_u *mib_tree_find(const struct mib_tree *tree, struct mib_walk_state *walk, const struct oid *oid);
mib_node_u *mib_tree_walk_next(const struct mib_tree *t, struct mib_walk_state *walk);
struct mib_leaf *mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk);
struct mib_leaf *mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk, u32 skip);
int mib_tree_hint(pool *p, struct mib_tree *t, const struct oid *oid, uint size);
int mib_tree_walk_is_oid_descendant(const struct mib_walk_state *walk, const struct oid *oid);

View File

@ -178,6 +178,19 @@ snmp_oid_copy2(struct oid *dest, const struct oid *src)
memcpy(dest->ids, src->ids, LOAD_U8(src->n_subid) * sizeof(u32));
}
/*
* snmp_oid_update
*
*/
void
snmp_oid_update(struct oid *dest, const struct oid *src)
{
dest->prefix = src->prefix;
dest->include = src->include;
dest->reserved = 0;
memcpy(dest->ids, src->ids, MIN(dest->n_subid, src->n_subid) * sizeof(u32));
}
/*
* snmp_oid_duplicate - duplicate an OID from memory pool
* @pool: pool to use
@ -675,8 +688,8 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
if (left_prefix == 0)
{
size_t bound = MIN((size_t) left_subids, ARRAY_SIZE(snmp_internet));
for (size_t idx = 0; idx < bound; idx++)
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]);
if (id < snmp_internet[idx])
@ -1102,18 +1115,40 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_d
int found = 0;
struct mib_leaf *leaf = &node->leaf;
if (mib_node_is_leaf(node) && LOAD_U8(data->c->sr_vb_start->name.include))
if (mib_node_is_leaf(node) && leaf->call_next)
{
const struct oid *oid = &data->c->sr_vb_start->name;
if (mib_tree_walk_oid_compare(walk, oid) > 0)
{
int old = snmp_oid_size(&data->c->sr_vb_start->name);
if (mib_tree_walk_to_oid(walk,
&data->c->sr_vb_start->name, 20 * sizeof(u32)))
{
snmp_log("walk_next copy failed");
return NULL;
}
int new = snmp_oid_size(&data->c->sr_vb_start->name);
data->c->buffer += (new - old);
}
found = !leaf->call_next(walk, data);
}
else if (mib_node_is_leaf(node) && LOAD_U8(data->c->sr_vb_start->name.include))
{
found = 1;
STORE_U8(data->c->sr_vb_start->name.include, 0);
}
if (!found && mib_node_is_leaf(node) && leaf->call_next && !leaf->call_next(walk, data))
found = 1;
while (!found && (leaf = mib_tree_walk_next_leaf(tree, walk)) != NULL)
const struct oid *oid = &data->c->sr_vb_start->name;
u32 skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
LOAD_U32(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 */
int old = snmp_oid_size(&data->c->sr_vb_start->name);
// TODO autogrow
if (mib_tree_walk_to_oid(walk, &data->c->sr_vb_start->name, 20 * sizeof(u32)))
{
snmp_log("walk_next copy failed");
@ -1127,12 +1162,15 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_d
found = 1;
else if (!leaf->call_next)
found = 1;
oid = &data->c->sr_vb_start->name;
skip = (walk->id_pos < LOAD_U8(oid->n_subid)) ?
LOAD_U32(oid->ids[walk->id_pos]) : 0;
}
if (!found)
return NULL;
return leaf;
}
@ -1179,7 +1217,6 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_d
snmp_set_varbind_type(vb, snmp_search_res_to_type(res));
u16 type = snmp_load_varbind_type(vb);
/* Test that hook() did not overwrite the VarBind type to non-matching type */
ASSUME(type == leaf->type || type == AGENTX_END_OF_MIB_VIEW || type == AGENTX_NO_SUCH_OBJECT ||
type == AGENTX_NO_SUCH_INSTANCE);

View File

@ -1498,7 +1498,7 @@ snmp_get_next_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_
.c = c,
};
snmp_walk_init(p->mib_tree, walk, o_start, &d);
(void) snmp_walk_init(p->mib_tree, walk, o_start, &d);
struct mib_leaf *leaf = snmp_walk_next(p->mib_tree, walk, &d);
enum snmp_search_res res;
@ -2137,6 +2137,15 @@ snmp_manage_tbuf2(struct snmp_proto *p, void **ptr, struct snmp_pdu *c)
*ptr = sk->tbuf + diff;
}
void
snmp_tbuf_reserve(struct snmp_data *data, size_t size)
{
if (size > data->c->size)
{
snmp_manage_tbuf(data->p, data->c);
}
}
/*
* prepare_response - fill buffer with AgentX PDU header
* @p: SNMP protocol instance