2024-04-22 10:55:33 +00:00
|
|
|
#ifndef _BIRD_SNMP_MIB_TREE_
|
|
|
|
#define _BIRD_SNMP_MIB_TREE_
|
|
|
|
|
|
|
|
#include "lib/resource.h"
|
|
|
|
#include "lib/lists.h"
|
|
|
|
#include "lib/birdlib.h"
|
|
|
|
|
|
|
|
#include "subagent.h"
|
|
|
|
|
|
|
|
#define MIB_TREE_NO_FLAGS 0x00
|
|
|
|
#define MIB_TREE_LEAF 0x01
|
|
|
|
#define MIB_TREE_HAS_HOOKS 0x02
|
|
|
|
|
|
|
|
typedef union mib_node_union mib_node_u;
|
|
|
|
|
|
|
|
struct mib_node_core {
|
|
|
|
u32 id;
|
|
|
|
u8 flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mib_node {
|
|
|
|
struct mib_node_core c;
|
|
|
|
mib_node_u **children;
|
|
|
|
u32 child_len;
|
|
|
|
};
|
|
|
|
|
2024-05-24 13:20:30 +00:00
|
|
|
struct mib_walk_state;
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
struct mib_leaf {
|
|
|
|
struct mib_node_core c;
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* filler - hook for filling VarBind data value
|
|
|
|
* @state: self referencing MIB tree walk state
|
|
|
|
* @data: box holding destiantion VarBind and SNMP protocol instance
|
|
|
|
*
|
|
|
|
* If corresponding leaf node has filled in AgentX type and/or size, it is
|
|
|
|
* guaranteed that PDU buffer have enough space. Hook mustn't be NULL.
|
|
|
|
* If the leaf node has set valid type, the varbind type will be automatically
|
|
|
|
* set by the snmp_walk_fill() servicing routine. If the field type is set to
|
|
|
|
* AGENTX_INVALID, it is expected that filler() hook will also fill
|
|
|
|
* the VarBind type.
|
|
|
|
*/
|
2024-07-17 11:03:26 +00:00
|
|
|
enum snmp_search_res (*filler)(struct mib_walk_state *state, struct snmp_pdu *context);
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* call_next - signal multileaf
|
|
|
|
* @state: self referencing MIB tree walk state
|
|
|
|
* @data: box holding destination VarBind and SNMP protocol insntace
|
|
|
|
*
|
|
|
|
* MIB modules can implement subtrees by a single leaf node in MIB node tree.
|
|
|
|
* When the tree is walked, the specific leaf node has to be returned multiple
|
|
|
|
* times. The @call_next hook determines if we should move to next leaf node.
|
|
|
|
* It is expected that call_next() hook may change the VarBind to be filled.
|
|
|
|
*
|
|
|
|
* Hook may be NULL meaning the leaf node is not multileaf/subtree.
|
|
|
|
*
|
|
|
|
*/
|
2024-07-17 11:03:26 +00:00
|
|
|
int (*call_next)(struct mib_walk_state *state, struct snmp_pdu *context);
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* type of produced VarBind, may be replaced in packet instanciation by
|
|
|
|
* AGENTX_NO_SUCH_OBJECT, AGENTX_NO_SUCH_INSTANCE or AGENTX_END_OF_MIB_VIEW
|
|
|
|
* The field is unspecified if equal to AGENTX_INVALID.
|
|
|
|
*/
|
2024-04-22 10:55:33 +00:00
|
|
|
enum agentx_type type;
|
2024-07-04 14:33:44 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Specify upper bound of VarBind data size. If set to -1, all handling must
|
|
|
|
* be done in filler() hook. In all other cases the filler() hook has
|
|
|
|
* guaranteed that the space is available.
|
|
|
|
*/
|
2024-04-22 10:55:33 +00:00
|
|
|
int size;
|
|
|
|
};
|
|
|
|
|
|
|
|
union mib_node_union {
|
|
|
|
struct mib_node_core empty;
|
|
|
|
struct mib_node inner;
|
|
|
|
struct mib_leaf leaf;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The stack size include empty prefix (mib tree root).
|
|
|
|
*/
|
|
|
|
#define MIB_WALK_STACK_SIZE 33
|
|
|
|
STATIC_ASSERT(OID_MAX_LEN < MIB_WALK_STACK_SIZE);
|
|
|
|
|
2024-05-21 13:43:41 +00:00
|
|
|
/* walk state for MIB tree */
|
2024-04-22 10:55:33 +00:00
|
|
|
struct mib_walk_state {
|
|
|
|
u8 id_pos; /* points after last matching subid in OID */
|
|
|
|
u32 stack_pos; /* points after last valid stack node */
|
|
|
|
mib_node_u *stack[MIB_WALK_STACK_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mib_tree {
|
|
|
|
struct mib_node root;
|
|
|
|
};
|
|
|
|
|
|
|
|
void mib_tree_init(pool *p, struct mib_tree *t);
|
2024-05-21 13:43:41 +00:00
|
|
|
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);
|
2024-07-09 14:30:04 +00:00
|
|
|
int mib_tree_walk_oid_compare(const struct mib_walk_state *state, const struct oid *oid);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
|
|
|
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);
|
2024-05-21 13:43:41 +00:00
|
|
|
mib_node_u *mib_tree_walk_next(const struct mib_tree *t, struct mib_walk_state *walk);
|
2024-07-09 14:30:04 +00:00
|
|
|
struct mib_leaf *mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk, u32 skip);
|
2024-04-22 10:55:33 +00:00
|
|
|
|
2024-07-04 14:33:44 +00:00
|
|
|
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);
|
|
|
|
|
2024-04-22 10:55:33 +00:00
|
|
|
static inline int
|
|
|
|
mib_node_is_leaf(const mib_node_u *node)
|
|
|
|
{
|
2024-05-21 13:43:41 +00:00
|
|
|
ASSUME(node);
|
2024-04-22 10:55:33 +00:00
|
|
|
return node->empty.flags & MIB_TREE_LEAF;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|