0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-11 17:08:46 +00:00

SNMP: Slow integraion of MIB tree in SNMP code

This commit is contained in:
Vojtech Vilimek 2024-05-24 15:20:30 +02:00
parent 2710221a4c
commit af9a2d4cd7
14 changed files with 937 additions and 233 deletions

View File

@ -1,4 +1,4 @@
S snmp.c S snmp.c
S subagent.c S subagent.c
S snmp_utils.c S snmp_utils.c
S bgp_mib.c S bgp4_mib.c

View File

@ -1,4 +1,4 @@
src := snmp.c snmp_utils.c subagent.c bgp_mib.c mib_tree.c src := snmp.c snmp_utils.c subagent.c bgp4_mib.c mib_tree.c
obj := $(src-o-files) obj := $(src-o-files)
$(all-daemon) $(all-daemon)
$(cf-local) $(cf-local)

View File

@ -8,10 +8,12 @@
* Can be freely distributed and used under the terms of the GNU GPL. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
/* need to be first header file included */
#include "bgp4_mib.h"
#include "snmp.h" #include "snmp.h"
#include "snmp_utils.h" #include "snmp_utils.h"
#include "subagent.h" #include "subagent.h"
#include "bgp_mib.h"
/* hash table macros */ /* hash table macros */
#define SNMP_HASH_KEY(n) n->peer_ip #define SNMP_HASH_KEY(n) n->peer_ip
@ -25,13 +27,21 @@
/* hash table only store ip4 addresses */ /* hash table only store ip4 addresses */
#define SNMP_HASH_LESS(ip1, ip2) SNMP_HASH_LESS4(ip1,ip2) #define SNMP_HASH_LESS(ip1, ip2) SNMP_HASH_LESS4(ip1,ip2)
// TODO delete me
#define SNMP_MANAGE_TBUF(...) (void)0
#define DECLARE_BGP4(addr, proto, conn, stats, config) \
ip4_addr addr; \
const struct bgp_proto *proto; \
const struct bgp_conn *conn; \
const struct bgp_stats *stats; \
const struct bgp_config *config
#define POPULATE_BGP4(addr, proto, conn, stats, config) populate_bgp4(p, c, &(addr), &(proto), &(conn), &(stats), &(config))
/* Simply discard type */
#define SNMP_MANAGE_TBUF(p, vb, c) snmp_manage_tbuf(p, (void **) vb, c)
static inline void ip4_to_oid(struct oid *oid, ip4_addr addr); static inline void ip4_to_oid(struct oid *oid, ip4_addr addr);
static inline void static inline void
snmp_hash_add_peer(struct snmp_proto *p, struct snmp_bgp_peer *peer) snmp_hash_add_peer(struct snmp_proto *p, struct snmp_bgp_peer *peer)
{ {
@ -83,7 +93,7 @@ bgp_get_candidate(u32 field)
/* /*
* First value is in secord cell of array translation_table, as the * First value is in secord cell of array translation_table, as the
* SNMP_BPG_IDENTIFIER == 1 * SNMP_BGP_IDENTIFIER == 1
*/ */
if (field > 0 && field <= ARRAY_SIZE(translation_table)- 1) if (field > 0 && field <= ARRAY_SIZE(translation_table)- 1)
return translation_table[field]; return translation_table[field];
@ -193,25 +203,22 @@ snmp_bgp_state(const struct oid *oid)
return state; return state;
} }
void static void
snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid) snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{ {
(void)p; const struct oid * const oid = reg->oid;
(void)r;
(void)oid; (void)oid;
/* TODO: EXPENSIVE_CHECK() that (void)p;
const struct oid *in_buf = ((void *) r) + sizeof(r); (void) res;
struct oid *dup = snmp_prefixize(p, in_buf);
ASSUME(snmp_bgp_state(oid) == snmp_bgp_state(dup));
mb_free(dup);
*/
} }
void static void
snmp_bgp_reg_failed(struct snmp_proto *p, struct agentx_response UNUSED *r, struct oid UNUSED *oid) snmp_bgp_reg_failed(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{ {
// TODO add more sensible action const struct oid * const oid = reg->oid;
snmp_stop_subagent(p); (void) res;
(void)oid;
(void)p;
} }
/* /*
@ -280,8 +287,9 @@ snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_
ip4_to_oid(addr, ip4); ip4_to_oid(addr, ip4);
} }
/* We have enough space inside the TX-buffer prepared */ /* We have enough space inside the TX-buffer prepared */
struct snmp_pdu sink = { 0 }; struct snmp_pdu dummy = { 0 };
snmp_varbind_ip4(addr_vb, &sink, ip4); dummy.sr_vb_start = addr_vb;
snmp_varbind_ip4(&dummy, ip4);
{ /* BGP4-MIB::bgpPeerLastError */ { /* BGP4-MIB::bgpPeerLastError */
struct oid *error = &error_vb->name; struct oid *error = &error_vb->name;
@ -294,7 +302,9 @@ snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_
error->ids[ENTRY_TYPE] = BGP4_MIB_LAST_ERROR; error->ids[ENTRY_TYPE] = BGP4_MIB_LAST_ERROR;
ip4_to_oid(error, ip4); ip4_to_oid(error, ip4);
} }
snmp_varbind_nstr(error_vb, &sink, last_error, 2);
dummy.sr_vb_start = error_vb;
snmp_varbind_nstr(&dummy, last_error, 2);
{ /* BGP4-MIB::bgpPeerState */ { /* BGP4-MIB::bgpPeerState */
struct oid *state = &state_vb->name; struct oid *state = &state_vb->name;
@ -307,7 +317,9 @@ snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_
state->ids[ENTRY_TYPE] = BGP4_MIB_STATE; state->ids[ENTRY_TYPE] = BGP4_MIB_STATE;
ip4_to_oid(state, ip4); ip4_to_oid(state, ip4);
} }
snmp_varbind_int(state_vb, &sink, state_val);
dummy.sr_vb_start = state_vb;
snmp_varbind_int(&dummy, state_val);
/* We do not send the systemUpTime.0 */ /* We do not send the systemUpTime.0 */
snmp_notify_pdu(p, head, data, sz, 0); snmp_notify_pdu(p, head, data, sz, 0);
@ -364,9 +376,10 @@ snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp)
} }
void void
snmp_bgp_register(struct snmp_proto *p) snmp_bgp4_register(struct snmp_proto *p)
{ {
u32 bgp_mib_prefix[] = { 1, 15 }; u32 bgp_mib_prefix[] = { 1, 15 };
// TODO
{ {
/* Register the whole BGP4-MIB::bgp root tree node */ /* Register the whole BGP4-MIB::bgp root tree node */
@ -380,6 +393,8 @@ snmp_bgp_register(struct snmp_proto *p)
memcpy(oid->ids, bgp_mib_prefix, sizeof(bgp_mib_prefix)); memcpy(oid->ids, bgp_mib_prefix, sizeof(bgp_mib_prefix));
reg->oid = oid; reg->oid = oid;
reg->reg_hook_ok = snmp_bgp_reg_ok;
reg->reg_hook_fail = snmp_bgp_reg_failed;
/* /*
* We set both upper bound and index to zero, therefore only single OID * We set both upper bound and index to zero, therefore only single OID
@ -390,7 +405,7 @@ snmp_bgp_register(struct snmp_proto *p)
} }
static int static int
snmp_bgp_valid_ip4(struct oid *o) snmp_bgp_valid_ip4(const struct oid *o)
{ {
return snmp_valid_ip4_index(o, 5); return snmp_valid_ip4_index(o, 5);
} }
@ -586,6 +601,565 @@ oid_state_compare(const struct oid *oid, u8 state)
return -1; return -1;
} }
static inline enum snmp_search_res
populate_bgp4(struct snmp_proto *p, struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto, const struct bgp_conn
**conn, const struct bgp_stats **stats, const struct bgp_config **config)
{
const struct oid * const oid = &c->sr_vb_start->name;
if (snmp_bgp_valid_ip4(oid))
*addr = ip4_from_oid(oid);
else
return SNMP_SEARCH_NO_INSTANCE;
struct snmp_bgp_peer *pe = snmp_hash_find(p, *addr);
if (!pe)
return SNMP_SEARCH_NO_INSTANCE;
const struct bgp_proto *bgp_proto;
*proto = bgp_proto = pe->bgp_proto;
if (ipa_is_ip4(bgp_proto->remote_ip))
{
log(L_ERR, "%s: Found BGP protocol instance with IPv6 address", bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR;
return SNMP_SEARCH_NO_INSTANCE;
}
ip4_addr proto_ip = ipa_to_ip4(bgp_proto->remote_ip);
if (!ip4_equal(proto_ip, pe->peer_ip))
{
/* Here, we could be in problem as the bgp_proto IP address could be changed */
log(L_ERR, "%s: Stored hash key IP address and peer remote address differ.",
bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR;
return SNMP_SEARCH_NO_INSTANCE;
}
*conn = bgp_proto->conn;
*stats = &bgp_proto->stats;
*config = bgp_proto->cf;
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_bgp_version(struct snmp_proto *p, struct snmp_pdu *c)
{
if (c->sr_vb_start->name.n_subid != 4)
{
snmp_set_varbind_type(c->sr_vb_start, AGENTX_NO_SUCH_INSTANCE);
return SNMP_SEARCH_NO_INSTANCE;
}
uint sz = snmp_str_size_from_len(1);
if (c->size < sz)
snmp_manage_tbuf(p, c);
c->size -= sz;
snmp_varbind_nstr(c, BGP4_VERSIONS, 1);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_local_as(struct snmp_proto *p, struct snmp_pdu *c)
{
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, p->bgp_local_as);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_peer_id(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
if (c->size < AGENTX_TYPE_IP4_SIZE)
snmp_manage_tbuf(p, c);
if (fsm_state == BGP4_MIB_OPENCONFIRM || fsm_state == BGP4_MIB_ESTABLISHED)
// TODO last
snmp_varbind_ip4(c, ip4_from_u32(bgp_proto->remote_id));
else
snmp_varbind_ip4(c, IP4_NONE);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_peer_state(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, fsm_state);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_admin_status(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
if (bgp_proto->p.disabled)
snmp_varbind_int(c, AGENTX_ADMIN_STOP);
else
snmp_varbind_int(c, AGENTX_ADMIN_START);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_neg_version(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
if (fsm_state == BGP4_MIB_ESTABLISHED || fsm_state == BGP4_MIB_ESTABLISHED)
snmp_varbind_int(c, BGP4_MIB_NEGOTIATED_VER_VALUE);
else
snmp_varbind_int(c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_local_addr(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_IP4_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_ip4(c, ipa_to_ip4(bgp_proto->local_ip));
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_local_port(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, bgp_conf->local_port);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_remove_addr(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_IP4_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_ip4(c, ipa_to_ip4(bgp_proto->remote_ip));
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_remote_port(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, bgp_conf->remote_port);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_remote_as(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, bgp_proto->remote_as);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_in_updates(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_counter32(c, bgp_stats->rx_updates);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_out_update(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_counter32(c, bgp_stats->tx_updates);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_in_total_msg(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_counter32(c, bgp_stats->rx_messages);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_out_total_msg(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_counter32(c, bgp_stats->tx_messages);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_last_err(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < snmp_str_size_from_len(2))
snmp_manage_tbuf(p, c);
char last_error[2];
snmp_bgp_last_error(bgp_proto, last_error);
snmp_varbind_nstr(c, last_error, 2);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_established_trans(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_counter32(c,
bgp_stats->fsm_established_transitions);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_established_time(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_gauge32(c,
(current_time() - bgp_proto->last_established) TO_S);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_retry_interval(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, bgp_conf->connect_retry_time);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_hold_time(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, (bgp_conn) ? bgp_conn->hold_time : 0);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_keep_alive(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
if (!bgp_conf->hold_time)
snmp_varbind_int(c, 0);
else
snmp_varbind_int(c,
(bgp_conn) ? bgp_conn->keepalive_time : 0);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_hold_time_conf(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, bgp_conf->hold_time);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_keep_alive_conf(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
if (!bgp_conf->keepalive_time)
snmp_varbind_int(c, 0);
else
snmp_varbind_int(c,
(bgp_conn) ? bgp_conn->keepalive_time : 0);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_min_as_org_interval(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
/* value should be in 1..65535 but is not supported by bird */
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, 0);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_route_adv_interval(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
/* value should be in 1..65535 but is not supported by bird */
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_int(c, 0);
return SNMP_SEARCH_OK;
}
static enum snmp_search_res
fill_in_update_elapsed_time(struct snmp_proto *p, struct snmp_pdu *c)
{
enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
if (res != SNMP_SEARCH_OK)
{
(void) snmp_set_varbind_type(c->sr_vb_start, res);
return res;
}
if (c->size < AGENTX_TYPE_INT_SIZE)
snmp_manage_tbuf(p, c);
snmp_varbind_gauge32(c,
(current_time() - bgp_proto->last_rx_update) TO_S
);
return SNMP_SEARCH_OK;
}
static struct oid * static struct oid *
update_bgp_vb(struct snmp_proto *p, struct agentx_varbind **vb, u8 state, struct snmp_pdu *c) update_bgp_vb(struct snmp_proto *p, struct agentx_varbind **vb, u8 state, struct snmp_pdu *c)
{ {
@ -892,19 +1466,26 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (oid_state_compare(oid, state) == 0 && snmp_bgp_valid_ip4(oid)) if (oid_state_compare(oid, state) == 0 && snmp_bgp_valid_ip4(oid))
addr = ip4_from_oid(oid); addr = ip4_from_oid(oid);
else else
return snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE); {
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
struct snmp_bgp_peer *pe = snmp_hash_find(p, addr); struct snmp_bgp_peer *pe = snmp_hash_find(p, addr);
if (!pe) if (!pe)
return snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE); {
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
const struct bgp_proto *bgp_proto = pe->bgp_proto; const struct bgp_proto *bgp_proto = pe->bgp_proto;
if (!ipa_is_ip4(bgp_proto->remote_ip)) if (!ipa_is_ip4(bgp_proto->remote_ip))
{ {
log(L_ERR, "%s: Found BGP protocol instance with IPv6 address", bgp_proto->p.name); log(L_ERR, "%s: Found BGP protocol instance with IPv6 address", bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR; c->error = AGENTX_RES_GEN_ERROR;
return snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE); snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
} }
ip4_addr proto_ip = ipa_to_ip4(bgp_proto->remote_ip); ip4_addr proto_ip = ipa_to_ip4(bgp_proto->remote_ip);
@ -914,7 +1495,8 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
log(L_ERR, "%s: Stored hash key IP address and peer remote address differ.", log(L_ERR, "%s: Stored hash key IP address and peer remote address differ.",
bgp_proto->p.name); bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR; c->error = AGENTX_RES_GEN_ERROR;
return snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE); snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
} }
const struct bgp_conn *bgp_conn = bgp_proto->conn; const struct bgp_conn *bgp_conn = bgp_proto->conn;
@ -931,20 +1513,20 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
{ {
case BGP4_MIB_S_PEER_IDENTIFIER: case BGP4_MIB_S_PEER_IDENTIFIER:
if (c->size < AGENTX_TYPE_IP4_SIZE) if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); snmp_manage_tbuf(p, c);
if (fsm_state == BGP4_MIB_OPENCONFIRM || fsm_state == BGP4_MIB_ESTABLISHED) if (fsm_state == BGP4_MIB_OPENCONFIRM || fsm_state == BGP4_MIB_ESTABLISHED)
// TODO last // TODO last
snmp_varbind_ip4(*vb, c, ip4_from_u32(bgp_proto->remote_id)); ; //snmp_varbind_ip4(*vb, c, ip4_from_u32(bgp_proto->remote_id));
else else
snmp_varbind_ip4(*vb, c, IP4_NONE); ; //snmp_varbind_ip4(*vb, c, IP4_NONE);
break; break;
case BGP4_MIB_S_STATE: case BGP4_MIB_S_STATE:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); snmp_manage_tbuf(p, c);
snmp_varbind_int(*vb, c, fsm_state); //snmp_varbind_int(*vb, c, fsm_state);
break; break;
case BGP4_MIB_S_ADMIN_STATUS: case BGP4_MIB_S_ADMIN_STATUS:
@ -952,9 +1534,9 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
if (bgp_proto->p.disabled) if (bgp_proto->p.disabled)
snmp_varbind_int(*vb, c, AGENTX_ADMIN_STOP); ; //snmp_varbind_int(*vb, c, AGENTX_ADMIN_STOP);
else else
snmp_varbind_int(*vb, c, AGENTX_ADMIN_START); ; //snmp_varbind_int(*vb, c, AGENTX_ADMIN_START);
break; break;
@ -962,10 +1544,12 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
if (fsm_state == BGP4_MIB_ESTABLISHED || fsm_state == BGP4_MIB_ESTABLISHED) if (fsm_state == BGP4_MIB_ESTABLISHED || fsm_state == BGP4_MIB_ESTABLISHED)
snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_VALUE); ; //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_VALUE);
else else
snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE); ; //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE);
break; break;
@ -973,78 +1557,78 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (c->size < AGENTX_TYPE_IP4_SIZE) if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->local_ip)); ; //snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->local_ip));
break; break;
case BGP4_MIB_S_LOCAL_PORT: case BGP4_MIB_S_LOCAL_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, bgp_conf->local_port); ; //snmp_varbind_int(*vb, c, bgp_conf->local_port);
break; break;
case BGP4_MIB_S_REMOTE_ADDR: case BGP4_MIB_S_REMOTE_ADDR:
if (c->size < AGENTX_TYPE_IP4_SIZE) if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->remote_ip)); ; //snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->remote_ip));
break; break;
case BGP4_MIB_S_REMOTE_PORT: case BGP4_MIB_S_REMOTE_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, bgp_conf->remote_port); ; //snmp_varbind_int(*vb, c, bgp_conf->remote_port);
break; break;
case BGP4_MIB_S_REMOTE_AS: case BGP4_MIB_S_REMOTE_AS:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, bgp_proto->remote_as); ; //snmp_varbind_int(*vb, c, bgp_proto->remote_as);
break; break;
case BGP4_MIB_S_RX_UPDATES: /* bgpPeerInUpdates */ case BGP4_MIB_S_RX_UPDATES: /* bgpPeerInUpdates */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE) if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c, bgp_stats->rx_updates); ; //snmp_varbind_counter32(*vb, c, bgp_stats->rx_updates);
break; break;
case BGP4_MIB_S_TX_UPDATES: /* bgpPeerOutUpdate */ case BGP4_MIB_S_TX_UPDATES: /* bgpPeerOutUpdate */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE) if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c, bgp_stats->tx_updates); ; //snmp_varbind_counter32(*vb, c, bgp_stats->tx_updates);
break; break;
case BGP4_MIB_S_RX_MESSAGES: /* bgpPeerInTotalMessages */ case BGP4_MIB_S_RX_MESSAGES: /* bgpPeerInTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE) if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c, bgp_stats->rx_messages); ; //snmp_varbind_counter32(*vb, c, bgp_stats->rx_messages);
break; break;
case BGP4_MIB_S_TX_MESSAGES: /* bgpPeerOutTotalMessages */ case BGP4_MIB_S_TX_MESSAGES: /* bgpPeerOutTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE) if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c, bgp_stats->tx_messages); ; //snmp_varbind_counter32(*vb, c, bgp_stats->tx_messages);
break; break;
case BGP4_MIB_S_LAST_ERROR: case BGP4_MIB_S_LAST_ERROR:
if (c->size < snmp_str_size_from_len(2)) if (c->size < snmp_str_size_from_len(2))
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_nstr(*vb, c, last_error, 2); ; //snmp_varbind_nstr(*vb, c, last_error, 2);
break; break;
case BGP4_MIB_S_FSM_TRANSITIONS: case BGP4_MIB_S_FSM_TRANSITIONS:
if (c->size < AGENTX_TYPE_COUNTER32_SIZE) if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c, //snmp_varbind_counter32(*vb, c,
bgp_stats->fsm_established_transitions); // bgp_stats->fsm_established_transitions);
break; break;
case BGP4_MIB_S_FSM_ESTABLISHED_TIME: case BGP4_MIB_S_FSM_ESTABLISHED_TIME:
@ -1052,22 +1636,22 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_gauge32(*vb, c, //snmp_varbind_gauge32(*vb, c,
(current_time() - bgp_proto->last_established) TO_S); // (current_time() - bgp_proto->last_established) TO_S);
break; break;
case BGP4_MIB_S_RETRY_INTERVAL: /* retry inverval value should be != 0 */ case BGP4_MIB_S_RETRY_INTERVAL: /* retry inverval value should be != 0 */
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, bgp_conf->connect_retry_time); //snmp_varbind_int(*vb, c, bgp_conf->connect_retry_time);
break; break;
case BGP4_MIB_S_HOLD_TIME: /* hold time should be == 0 or in 3..65535 */ case BGP4_MIB_S_HOLD_TIME: /* hold time should be == 0 or in 3..65535 */
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, (bgp_conn) ? bgp_conn->hold_time : 0); //snmp_varbind_int(*vb, c, (bgp_conn) ? bgp_conn->hold_time : 0);
break; break;
case BGP4_MIB_S_KEEPALIVE: case BGP4_MIB_S_KEEPALIVE:
@ -1075,17 +1659,17 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
if (!bgp_conf->hold_time) if (!bgp_conf->hold_time)
snmp_varbind_int(*vb, c, 0); ; //snmp_varbind_int(*vb, c, 0);
else else
snmp_varbind_int(*vb, c, ; //snmp_varbind_int(*vb, c,
(bgp_conn) ? bgp_conn->keepalive_time : 0); // (bgp_conn) ? bgp_conn->keepalive_time : 0);
break; break;
case BGP4_MIB_S_HOLD_TIME_CONFIGURED: case BGP4_MIB_S_HOLD_TIME_CONFIGURED:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, bgp_conf->hold_time); //snmp_varbind_int(*vb, c, bgp_conf->hold_time);
break; break;
case BGP4_MIB_S_KEEPALIVE_CONFIGURED: case BGP4_MIB_S_KEEPALIVE_CONFIGURED:
@ -1094,10 +1678,10 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (!bgp_conf->keepalive_time) if (!bgp_conf->keepalive_time)
snmp_varbind_int(*vb, c, 0); ; //snmp_varbind_int(*vb, c, 0);
else else
snmp_varbind_int(*vb, c, ; //snmp_varbind_int(*vb, c,
(bgp_conn) ? bgp_conn->keepalive_time : 0); // (bgp_conn) ? bgp_conn->keepalive_time : 0);
break; break;
case BGP4_MIB_S_ORIGINATION_INTERVAL: case BGP4_MIB_S_ORIGINATION_INTERVAL:
@ -1105,7 +1689,7 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, 0); //snmp_varbind_int(*vb, c, 0);
break; break;
case BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT: case BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT:
@ -1113,16 +1697,16 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, 0); //snmp_varbind_int(*vb, c, 0);
break; break;
case BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME: case BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_gauge32(*vb, c, //snmp_varbind_gauge32(*vb, c,
(current_time() - bgp_proto->last_rx_update) TO_S //(current_time() - bgp_proto->last_rx_update) TO_S
); //);
break; break;
case BGP4_MIB_S_END: case BGP4_MIB_S_END:
@ -1167,21 +1751,21 @@ bgp_fill_static(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pd
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
c->size -= sz; c->size -= sz;
snmp_varbind_nstr(*vb, c, BGP4_VERSIONS, 1); //snmp_varbind_nstr(*vb, c, BGP4_VERSIONS, 1);
break; break;
case BGP4_MIB_S_LOCAL_AS: case BGP4_MIB_S_LOCAL_AS:
if (c->size < AGENTX_TYPE_INT_SIZE) if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, p->bgp_local_as); //snmp_varbind_int(*vb, c, p->bgp_local_as);
break; break;
case BGP4_MIB_S_IDENTIFIER: case BGP4_MIB_S_IDENTIFIER:
if (c->size < AGENTX_TYPE_IP4_SIZE) if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c); SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_ip4(*vb, c, p->bgp_local_id); //snmp_varbind_ip4(*vb, c, p->bgp_local_id);
break; break;
default: default:

View File

@ -1,9 +1,29 @@
#ifndef _BIRD_SNMP_BGP_MIB_H_ #ifndef _BIRD_SNMP_BGP4_MIB_H_
#define _BIRD_SNMP_BGP_MIB_H_ #define _BIRD_SNMP_BGP4_MIB_H_
#ifdef _BIRD_SNMP_SUBAGENT_H_
#define BIRD_SNMP_BGP4_SKIP
#endif
#include "snmp.h" #include "snmp.h"
#include "proto/bgp/bgp.h"
void snmp_bgp4_register(struct snmp_proto *p);
struct bgp4_mib {
enum snmp_tags tag; /* always BGP4_MIB, see subagent.h for more details */
ip4_addr addr;
const struct bgp_proto *bgp_proto;
const struct bgp_conn *bgp_conn;
const struct bgp_stats *bgp_stats;
const struct bgp_config *bgp_conf;
};
#include "subagent.h" #include "subagent.h"
#ifndef BIRD_SNMP_BGP4_SKIP
#define BGP4_MIB 15 #define BGP4_MIB 15
/* peers attributes */ /* peers attributes */
@ -40,11 +60,6 @@ enum bgp4_mib_peer_entry_row {
#define BGP4_MIB_NEGOTIATED_VER_VALUE 4 #define BGP4_MIB_NEGOTIATED_VER_VALUE 4
#define BGP4_MIB_NEGOTIATED_VER_NO_VALUE 0 #define BGP4_MIB_NEGOTIATED_VER_NO_VALUE 0
void snmp_bgp_register(struct snmp_proto *p);
void snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid);
void snmp_bgp_reg_failed(struct snmp_proto *p, struct agentx_response *r, struct oid *oid);
u8 snmp_bgp_get_valid(u8 state); u8 snmp_bgp_get_valid(u8 state);
u8 snmp_bgp_getnext_valid(u8 state); u8 snmp_bgp_getnext_valid(u8 state);
@ -127,3 +142,5 @@ STATIC_ASSERT(BGP4_MIB_ESTABLISHED == BS_ESTABLISHED + 1);
#define BGP4_MIB_BACKWARD_TRANS_NOTIFICATION 2 #define BGP4_MIB_BACKWARD_TRANS_NOTIFICATION 2
#endif #endif
#endif

View File

@ -18,7 +18,7 @@ CF_DEFINES
CF_DECLS CF_DECLS
CF_KEYWORDS(SNMP, PROTOCOL, BPG, LOCAL, AS, REMOTE, ADDRESS, PORT, DESCRIPTION, CF_KEYWORDS(SNMP, PROTOCOL, BGP, LOCAL, AS, REMOTE, ADDRESS, PORT, DESCRIPTION,
TIMEOUT, PRIORITY, CONTEXT, DEFAULT, MESSAGE) TIMEOUT, PRIORITY, CONTEXT, DEFAULT, MESSAGE)
CF_GRAMMAR CF_GRAMMAR

View File

@ -28,7 +28,7 @@ mib_mb_realloc(pool *p, void *ptr, unsigned size)
} }
/* /*
*mib_tree_init - Initialize a MIB tree * mib_tree_init - Initialize a MIB tree
* @p: allocation source pool * @p: allocation source pool
* @t: pointer to a tree being initialized * @t: pointer to a tree being initialized
* *

View File

@ -24,10 +24,13 @@ struct mib_node {
u32 child_len; u32 child_len;
}; };
struct mib_walk_state;
struct mib_leaf { struct mib_leaf {
struct mib_node_core c; struct mib_node_core c;
enum snmp_search_res (*filler)(struct snmp_proto *p, struct snmp_pdu *c); enum snmp_search_res (*filler)(struct snmp_proto *p, struct snmp_pdu *c);
//enum snmp_search_res (*filler)(struct snmp_proto_pdu *pc, struct agentx_varbind **vb); //enum snmp_search_res (*filler)(struct snmp_proto_pdu *pc, struct agentx_varbind **vb);
int (*call_next)(struct snmp_proto *p, struct snmp_pdu *c, struct mib_walk_state *state);
enum agentx_type type; enum agentx_type type;
int size; int size;
}; };

View File

@ -10,7 +10,7 @@
* *
* The SNMP protocol is divided into several parts: |snmp.c| which implements * The SNMP protocol is divided into several parts: |snmp.c| which implements
* the BIRD intergration, |subagent.c| contains functions for creating and * the BIRD intergration, |subagent.c| contains functions for creating and
* parsing packets, |bgp_mib.c| takes care of the bgp MIB subtree of standard * parsing packets, |bgp4_mib.c| takes care of the bgp MIB subtree of standard
* BGP4-MIB and |snmp_utils.c| which is collections of helper functions for * BGP4-MIB and |snmp_utils.c| which is collections of helper functions for
* working with OIDs, VarBinds. * working with OIDs, VarBinds.
* *
@ -334,14 +334,6 @@ snmp_cleanup(struct snmp_proto *p)
r = NULL; r = NULL;
} }
struct snmp_registered_oid *ro, *ro2;
WALK_LIST_DELSAFE(ro, ro2, p->bgp_registered)
{
rem_node(&r->n);
mb_free(ro);
ro = NULL;
}
HASH_FREE(p->bgp_hash); HASH_FREE(p->bgp_hash);
rfree(p->lp); rfree(p->lp);
@ -507,7 +499,6 @@ snmp_start(struct proto *P)
p->ping_timer = tm_new_init(p->pool, snmp_ping_timeout, p, p->timeout, 0); p->ping_timer = tm_new_init(p->pool, snmp_ping_timeout, p, p->timeout, 0);
init_list(&p->registration_queue); init_list(&p->registration_queue);
init_list(&p->bgp_registered);
/* We create copy of bonds to BGP protocols. */ /* We create copy of bonds to BGP protocols. */
HASH_INIT(p->bgp_hash, p->pool, 10); HASH_INIT(p->bgp_hash, p->pool, 10);

View File

@ -17,8 +17,7 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "filter/data.h" #include "filter/data.h"
#include "proto/bgp/bgp.h" #include "proto/bgp/bgp.h" // TODO remove me
#define SNMP_UNDEFINED 0 #define SNMP_UNDEFINED 0
#define SNMP_BGP 1 #define SNMP_BGP 1
@ -42,6 +41,11 @@ enum snmp_proto_state {
SNMP_RESET, SNMP_RESET,
}; };
enum snmp_tags {
EMPTY_TAG = 0,
BGP4_TAG,
};
struct snmp_bond { struct snmp_bond {
node n; node n;
struct proto_config *config; struct proto_config *config;
@ -81,20 +85,13 @@ struct snmp_bgp_peer {
struct snmp_bgp_peer *next; struct snmp_bgp_peer *next;
}; };
struct snmp_registration {
node n;
u8 mib_class;
u32 session_id;
u32 transaction_id;
u32 packet_id;
struct oid *oid;
};
struct snmp_registered_oid { struct snmp_registered_oid {
node n; node n;
struct oid *oid; struct oid *oid;
}; };
struct mib_tree; /* see mib_tree.h */
struct snmp_proto { struct snmp_proto {
struct proto p; struct proto p;
struct object_lock *lock; struct object_lock *lock;
@ -125,8 +122,6 @@ struct snmp_proto {
uint registrations_to_ack; /* counter of pending responses to register-pdu */ uint registrations_to_ack; /* counter of pending responses to register-pdu */
list registration_queue; /* list containing snmp_register records */ list registration_queue; /* list containing snmp_register records */
list bgp_registered; /* list of currently registered bgp oids
* (struct snmp_registered_oid) */
// map // map
struct f_trie *bgp_trie; struct f_trie *bgp_trie;
@ -138,6 +133,23 @@ struct snmp_proto {
timer *ping_timer; timer *ping_timer;
btime startup_delay; btime startup_delay;
timer *startup_timer; timer *startup_timer;
struct mib_tree *mib_tree;
};
struct snmp_registration;
struct agentx_response; /* declared in subagent.h */
typedef void (*snmp_reg_hook_t)(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg);
struct snmp_registration {
node n;
u8 mib_class;
u32 session_id;
u32 transaction_id;
u32 packet_id;
struct oid *oid;
snmp_reg_hook_t reg_hook_ok; /* hook called when successful response to OID registration is recieved */
snmp_reg_hook_t reg_hook_fail; /* hook called when OID registration fail */
}; };
//void snmp_tx(sock *sk); //void snmp_tx(sock *sk);

View File

@ -385,7 +385,7 @@ t_oid_compare(void)
bt_assert(snmp_oid_compare(no_pref2, pref2) == 0); bt_assert(snmp_oid_compare(no_pref2, pref2) == 0);
bt_assert(snmp_oid_compare(pref, pref2) < 0); bt_assert(snmp_oid_compare(pref, pref2) < 0);
bt_assert(snmp_oid_compare(pref2, pref) > 0); bt_assert(snmp_oid_compare(pref2, pref) > 0);
bt_assert(snmp_oid_compare(pref, no_pref2) < 0); bt_assert(snmp_oid_compare(pref, no_pref2) < 0);
bt_assert(snmp_oid_compare(no_pref2, pref) > 0); bt_assert(snmp_oid_compare(no_pref2, pref) > 0);
bt_assert(snmp_oid_compare(no_pref, pref2) < 0); bt_assert(snmp_oid_compare(no_pref, pref2) < 0);
@ -1119,7 +1119,7 @@ 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 = LOAD_U8(oids[i]->n_subid);
if (subids > 0) if (subids > 0)
{ {
found = NULL; found = NULL;
@ -1204,10 +1204,10 @@ gen_test_find(struct oid *(*generator)(void))
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); STORE_U8(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); STORE_U8(searched[search]->n_subid, subids);
found = mib_tree_find(tree, &walk, searched[search]); found = mib_tree_find(tree, &walk, searched[search]);
@ -1375,7 +1375,7 @@ gen_test_delete_remove(struct oid *(*generator)(void), int remove)
//mib_tree_walk_init(&walk, tree, 0); //mib_tree_walk_init(&walk, tree, 0);
mib_tree_walk_init(&walk, NULL); mib_tree_walk_init(&walk, NULL);
mib_node_u *node = mib_tree_find(tree, &walk, sorted[j]); mib_node_u *node = mib_tree_find(tree, &walk, sorted[j]);
if (snmp_is_oid_empty(oid)) if (snmp_is_oid_empty(oid))
; ;
/* the oid could have multiple instances in the oids dataset */ /* the oid could have multiple instances in the oids dataset */
@ -1478,7 +1478,7 @@ gen_test_traverse(struct oid *(*generator)(void))
nodes[d] = mib_tree_find(tree, &walk, sorted[d]); nodes[d] = mib_tree_find(tree, &walk, sorted[d]);
} }
int bound = 0; int bound = 0;
for (int d = 0; d < distinct; d++) for (int d = 0; d < distinct; d++)
{ {
@ -1630,8 +1630,8 @@ gen_test_leafs(struct oid *(*generator)(void))
bt_assert(snmp_oid_compare(last, oid) < 0); bt_assert(snmp_oid_compare(last, oid) < 0);
bt_assert(mib_node_is_leaf(((mib_node_u *)current))); bt_assert(mib_node_is_leaf(((mib_node_u *)current)));
while (oid_index < distinct && while (oid_index < distinct &&
(nodes[oid_index] == NULL || !mib_node_is_leaf(nodes[oid_index]))) (nodes[oid_index] == NULL || !mib_node_is_leaf(nodes[oid_index])))
oid_index++; oid_index++;
@ -1646,7 +1646,7 @@ gen_test_leafs(struct oid *(*generator)(void))
current = mib_tree_walk_next_leaf(tree, &walk); current = mib_tree_walk_next_leaf(tree, &walk);
bt_assert(current == NULL); bt_assert(current == NULL);
bt_assert(oid_index == distinct); bt_assert(oid_index == distinct);
bt_assert(i == leafs); bt_assert(i == leafs);
mb_free(oids); mb_free(oids);

View File

@ -65,7 +65,7 @@ snmp_varbind_set_name_len(struct snmp_proto *p, struct agentx_varbind **vb, u8 l
uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32); uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32);
if (c->size < diff_size) if (c->size < diff_size)
{ {
snmp_manage_tbuf(p, (void **) vb, c); snmp_manage_tbuf(p, c);
oid = &(*vb)->name; oid = &(*vb)->name;
} }
@ -81,7 +81,7 @@ snmp_varbind_duplicate_hdr(struct snmp_proto *p, struct agentx_varbind **vb, str
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);
if (c->size < hdr_size) if (c->size < hdr_size)
snmp_manage_tbuf(p, (void **) vb, c); snmp_manage_tbuf(p, c);
ASSERT(c->size >= hdr_size); ASSERT(c->size >= hdr_size);
byte *buffer = c->buffer; byte *buffer = c->buffer;
@ -260,12 +260,38 @@ snmp_varbind_hdr_size_from_oid(const struct oid *oid)
* *
* This function assumes valid @t. * This function assumes valid @t.
*/ */
inline void inline enum snmp_search_res
snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t) snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t)
{ {
ASSUME(t != AGENTX_INVALID); ASSUME(t != AGENTX_INVALID);
STORE_U16(vb->type, t); STORE_U16(vb->type, t);
STORE_U16(vb->reserved, 0); STORE_U16(vb->reserved, 0);
switch (t)
{
case AGENTX_END_OF_MIB_VIEW:
return SNMP_SEARCH_END_OF_VIEW;
case AGENTX_NO_SUCH_OBJECT:
return SNMP_SEARCH_NO_OBJECT;
case AGENTX_NO_SUCH_INSTANCE:
return SNMP_SEARCH_NO_INSTANCE;
/* valid varbind types */
case AGENTX_INTEGER:
case AGENTX_OCTET_STRING:
case AGENTX_NULL:
case AGENTX_OBJECT_ID:
case AGENTX_IP_ADDRESS:
case AGENTX_COUNTER_32:
case AGENTX_GAUGE_32:
case AGENTX_TIME_TICKS:
case AGENTX_OPAQUE:
case AGENTX_COUNTER_64:
return SNMP_SEARCH_OK;
default:
die("invalid varbind type");
}
} }
/* Internal wrapper */ /* Internal wrapper */
@ -660,7 +686,7 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
/* check prefix */ /* check prefix */
if (LOAD_U32(left->ids[4]) < (u32) right_prefix) if (LOAD_U32(left->ids[4]) < (u32) right_prefix)
return -1; return -1;
else if (LOAD_U32(left->ids[4]) > (u32) right_prefix) else if (LOAD_U32(left->ids[4]) > (u32) right_prefix)
return 1; return 1;
/* the right prefix is already checked (+1) */ /* the right prefix is already checked (+1) */
@ -798,45 +824,46 @@ snmp_varbind_type32(struct agentx_varbind *vb, struct snmp_pdu *c, enum agentx_t
} }
inline void inline void
snmp_varbind_int(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val) snmp_varbind_int(struct snmp_pdu *c, u32 val)
{ {
snmp_varbind_type32(vb, c, AGENTX_INTEGER, val); snmp_varbind_type32(c->sr_vb_start, c, AGENTX_INTEGER, val);
} }
inline void inline void
snmp_varbind_counter32(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val) snmp_varbind_counter32(struct snmp_pdu *c, u32 val)
{ {
snmp_varbind_type32(vb, c, AGENTX_COUNTER_32, val); snmp_varbind_type32(c->sr_vb_start, c, AGENTX_COUNTER_32, val);
} }
inline void inline void
snmp_varbind_ticks(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val) snmp_varbind_ticks(struct snmp_pdu *c, u32 val)
{ {
snmp_varbind_type32(vb, c, AGENTX_TIME_TICKS, val); snmp_varbind_type32(c->sr_vb_start, c, AGENTX_TIME_TICKS, val);
} }
inline void inline void
snmp_varbind_gauge32(struct agentx_varbind *vb, struct snmp_pdu *c, s64 time) snmp_varbind_gauge32(struct snmp_pdu *c, s64 time)
{ {
snmp_varbind_type32(vb, c, AGENTX_GAUGE_32, MAX(0, MIN(time, UINT32_MAX))); snmp_varbind_type32(c->sr_vb_start, c,
AGENTX_GAUGE_32, MAX(0, MIN(time, UINT32_MAX)));
} }
inline void inline void
snmp_varbind_ip4(struct agentx_varbind *vb, struct snmp_pdu *c, ip4_addr addr) snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr)
{ {
snmp_set_varbind_type(vb, AGENTX_IP_ADDRESS); snmp_set_varbind_type(c->sr_vb_start, AGENTX_IP_ADDRESS);
c->buffer = snmp_put_ip4(snmp_varbind_data(vb), addr); c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
} }
// TODO doc string, we have already the varbind prepared // TODO doc string, we have already the varbind prepared
inline byte * inline byte *
snmp_varbind_nstr2(struct agentx_varbind *vb, uint size, const char *str, uint len) snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
{ {
if (size < snmp_str_size_from_len(len)) if (size < snmp_str_size_from_len(len))
return NULL; return NULL;
snmp_set_varbind_type(vb, AGENTX_OCTET_STRING); snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
return snmp_put_nstr(snmp_varbind_data(vb), str, len); return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
} }
/* /*
@ -851,10 +878,10 @@ snmp_varbind_nstr2(struct agentx_varbind *vb, uint size, const char *str, uint l
* more info. * more info.
*/ */
void void
snmp_varbind_nstr(struct agentx_varbind *vb, struct snmp_pdu *c, const char *str, uint len) snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len)
{ {
snmp_set_varbind_type(vb, AGENTX_OCTET_STRING); snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
c->buffer = snmp_put_nstr(snmp_varbind_data(vb), str, len); c->buffer = snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
} }
inline enum agentx_type inline enum agentx_type

View File

@ -14,7 +14,7 @@ uint snmp_pkt_len(const byte *start, const byte *end);
/* /*
* AgentX - Variable Binding (VarBind) type utils * AgentX - Variable Binding (VarBind) type utils
*/ */
void 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); 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);
@ -74,12 +74,12 @@ int snmp_test_close_reason(byte value);
/* Functions filling buffer a typed value */ /* Functions filling buffer a typed value */
struct agentx_varbind *snmp_create_varbind(byte *buf, struct oid *oid); struct agentx_varbind *snmp_create_varbind(byte *buf, struct oid *oid);
struct agentx_varbind *snmp_create_varbind_null(byte *buf); struct agentx_varbind *snmp_create_varbind_null(byte *buf);
void snmp_varbind_int(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val); void snmp_varbind_int(struct snmp_pdu *c, u32 val);
void snmp_varbind_counter32(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val); void snmp_varbind_counter32(struct snmp_pdu *c, u32 val);
void snmp_varbind_gauge32(struct agentx_varbind *vb, struct snmp_pdu *c, s64 time); void snmp_varbind_gauge32(struct snmp_pdu *c, s64 time);
void snmp_varbind_ticks(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val); void snmp_varbind_ticks(struct snmp_pdu *c, u32 val);
void snmp_varbind_ip4(struct agentx_varbind *vb, struct snmp_pdu *c, ip4_addr addr); void snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr);
void snmp_varbind_nstr(struct agentx_varbind *vb, struct snmp_pdu *c, const char *str, uint len); void snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len);
/* 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);

View File

@ -10,8 +10,9 @@
#include "lib/unaligned.h" #include "lib/unaligned.h"
#include "subagent.h" #include "subagent.h"
#include "mib_tree.h"
#include "snmp_utils.h" #include "snmp_utils.h"
#include "bgp_mib.h" #include "bgp4_mib.h"
/* ============================================================= /* =============================================================
* Problems * Problems
@ -115,45 +116,11 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
snmp_header(h, type, (u8) 0); snmp_header(h, type, (u8) 0);
} }
/*
* snmp_register_ok - registration of OID was successful
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @oid: OID that was successfully registered
* @class: MIB subtree of @oid
*
* Send a notification to MIB (selected by @class) about successful registration
* of @oid.
*/
static void
snmp_register_ok(struct snmp_proto *p, struct agentx_response *res, struct oid *oid, u8 UNUSED class)
{
// todo switch based on oid type
snmp_bgp_reg_ok(p, res, oid);
}
/*
* snmp_regsiter_failed - registration of OID failed
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @oid: OID whose registration failed
* @class: MIB subtree of @oid
*
* Send a notification to MIB (selected by @class) about @oid registration
* failure.
*/
static void
snmp_register_failed(struct snmp_proto *p, struct agentx_response *res, struct oid *oid, u8 UNUSED class)
{
// todo switch based on oid type
snmp_bgp_reg_failed(p, res, oid);
}
/* /*
* 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
* @class: MIB subtree associated with agentx-Register-PDU * @class: MIB subtree associated with agentx-Register-PDU
*/ */
void void
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class) snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
@ -161,26 +128,18 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
struct snmp_registration *reg; struct snmp_registration *reg;
WALK_LIST(reg, p->registration_queue) WALK_LIST(reg, p->registration_queue)
{ {
// todo add support for more mib trees (other than BGP4-MIB)
if (snmp_registration_match(reg, &res->h, class)) if (snmp_registration_match(reg, &res->h, class))
{ {
struct snmp_registered_oid *ro = \
mb_alloc(p->p.pool, sizeof(struct snmp_registered_oid));
ro->n.prev = ro->n.next = NULL;
ro->oid = reg->oid;
rem_node(&reg->n); rem_node(&reg->n);
mb_free(reg);
p->registrations_to_ack--; p->registrations_to_ack--;
add_tail(&p->bgp_registered, &ro->n);
if (res->error == AGENTX_RES_NO_ERROR) if (res->error == AGENTX_RES_NO_ERROR)
snmp_register_ok(p, res, ro->oid, class); reg->reg_hook_ok(p, (const struct agentx_response *) res, reg);
else else
snmp_register_failed(p, res, ro->oid, class); reg->reg_hook_fail(p, (const struct agentx_response *) res, reg);
mb_free(reg->oid);
mb_free(reg);
return; return;
} }
} }
@ -247,7 +206,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
/* Make sure that we have enough space in TX-buffer */ /* Make sure that we have enough space in TX-buffer */
if (c.size < AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) + if (c.size < AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
+ snmp_str_size(cf->description)) + snmp_str_size(cf->description))
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -293,6 +252,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, sk); snmp_pdu_context(&c, sk);
// TODO use more readable anonymous structure decl.
#define UPTIME_SIZE \ #define UPTIME_SIZE \
(6 * sizeof(u32)) /* sizeof( { u32 vb_type, u32 oid_hdr, u32 ids[4] } ) */ (6 * sizeof(u32)) /* sizeof( { u32 vb_type, u32 oid_hdr, u32 ids[4] } ) */
#define TRAP0_HEADER_SIZE \ #define TRAP0_HEADER_SIZE \
@ -306,7 +266,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
/* Make sure that we have enough space in TX-buffer */ /* Make sure that we have enough space in TX-buffer */
if (c.size < sz) if (c.size < sz)
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -332,7 +292,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
/* 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(vb, &c, (uptime TO_S) / 100); snmp_varbind_ticks(&c, (uptime TO_S) / 100);
ASSUME(snmp_test_varbind(vb)); 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));
} }
@ -397,11 +357,11 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
#define BOUND_SIZE sizeof(u32) #define BOUND_SIZE sizeof(u32)
/* conditional +4 for upper-bound (optinal field) */ /* 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);
if (c.size < sz) if (c.size < sz)
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -483,7 +443,7 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
#define REASON_SIZE sizeof(u32) #define REASON_SIZE sizeof(u32)
if (c.size < AGENTX_HEADER_SIZE + REASON_SIZE) if (c.size < AGENTX_HEADER_SIZE + REASON_SIZE)
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -614,7 +574,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
snmp_pdu_context(&c, sk); snmp_pdu_context(&c, sk);
if (c.size < AGENTX_HEADER_SIZE) if (c.size < AGENTX_HEADER_SIZE)
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
res = prepare_response(p, &c); res = prepare_response(p, &c);
@ -675,7 +635,6 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
TRACE(D_PACKETS, "SNMP SET action failed (not writable)"); 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_RESOURCE_UNAVAILABLE, c.index + 1);
response_err_ind(p, res, AGENTX_RES_NOT_WRITABLE, c.index + 1); response_err_ind(p, res, AGENTX_RES_NOT_WRITABLE, c.index + 1);
} }
@ -711,7 +670,7 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, p->sock); snmp_pdu_context(&c, p->sock);
if (c.size < sizeof(struct agentx_response)) if (c.size < sizeof(struct agentx_response))
snmp_manage_tbuf(p, NULL, &c); snmp_manage_tbuf(p, &c);
struct agentx_response *r = prepare_response(p, &c); struct agentx_response *r = prepare_response(p, &c);
@ -786,6 +745,7 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
if (pkt_size != 0) if (pkt_size != 0)
{ {
// TODO should we free even for malformed packets ?? // TODO should we free even for malformed packets ??
// TODO -> check that data is not freed
return AGENTX_HEADER_SIZE; return AGENTX_HEADER_SIZE;
} }
@ -981,8 +941,7 @@ parse_response(struct snmp_proto *p, byte *res)
void void
snmp_register_mibs(struct snmp_proto *p) snmp_register_mibs(struct snmp_proto *p)
{ {
snmp_bgp_register(p); snmp_bgp4_register(p);
/* snmp_ospf_regsiter(p); ... */
} }
/* /*
@ -1071,7 +1030,8 @@ snmp_get_mib_class(const struct oid *oid)
* *
* Return 0 if the created VarBind type is endOfMibView, 1 otherwise. * Return 0 if the created VarBind type is endOfMibView, 1 otherwise.
*/ */
static int // TODO remove me
static int UNUSED
snmp_get_next2(struct snmp_proto *p, struct agentx_varbind **vb_search, struct oid *o_end, struct snmp_pdu *c) snmp_get_next2(struct snmp_proto *p, struct agentx_varbind **vb_search, struct oid *o_end, struct snmp_pdu *c)
{ {
enum snmp_search_res r; enum snmp_search_res r;
@ -1111,7 +1071,7 @@ snmp_get_next2(struct snmp_proto *p, struct agentx_varbind **vb_search, struct o
o_start = &(*vb_search)->name; o_start = &(*vb_search)->name;
if (c->size < snmp_varbind_hdr_size_from_oid(o_start)) if (c->size < snmp_varbind_hdr_size_from_oid(o_start))
snmp_manage_tbuf(p, (void **) vb_search, c); snmp_manage_tbuf(p, c);
snmp_set_varbind_type(*vb_search, AGENTX_END_OF_MIB_VIEW); snmp_set_varbind_type(*vb_search, AGENTX_END_OF_MIB_VIEW);
return 0; return 0;
@ -1186,7 +1146,7 @@ snmp_get_next3(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
} }
if (c->size < snmp_varbind_hdr_size_from_oid(o_start)) if (c->size < snmp_varbind_hdr_size_from_oid(o_start))
snmp_manage_tbuf(p, (void **) vb, c); snmp_manage_tbuf(p, c);
vb = snmp_create_varbind(c->buffer, o_start); vb = snmp_create_varbind(c->buffer, o_start);
vb->type = AGENTX_END_OF_MIB_VIEW; vb->type = AGENTX_END_OF_MIB_VIEW;
@ -1368,7 +1328,7 @@ snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu
uint oid_size = snmp_oid_size(oid); uint oid_size = snmp_oid_size(oid);
if (c->size < oid_size) if (c->size < oid_size)
snmp_manage_tbuf(p, NULL, c); snmp_manage_tbuf(p, c);
// TODO check if the @oid is prefixable // TODO check if the @oid is prefixable
ASSERT(c->size >= oid_size); ASSERT(c->size >= oid_size);
@ -1393,7 +1353,7 @@ snmp_vb_to_tx(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
{ {
uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid); uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid);
if (c->size < vb_hdr_size) if (c->size < vb_hdr_size)
snmp_manage_tbuf(p, NULL, c); snmp_manage_tbuf(p, c);
ASSERT(c->size >= vb_hdr_size); ASSERT(c->size >= vb_hdr_size);
struct agentx_varbind *vb = (void *) c->buffer; struct agentx_varbind *vb = (void *) c->buffer;
@ -1500,6 +1460,78 @@ parse_gets_error(struct snmp_proto *p, struct snmp_pdu *c, uint len)
return len + AGENTX_HEADER_SIZE; return len + AGENTX_HEADER_SIZE;
} }
static enum snmp_search_res
snmp_mib_fill2(struct snmp_proto *p, struct snmp_pdu *c, mib_node_u *mib_node)
{
if (!mib_node || !mib_node_is_leaf(mib_node))
{
snmp_set_varbind_type(c->sr_vb_start, AGENTX_NO_SUCH_OBJECT);
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(c->sr_vb_start));
return AGENTX_NO_SUCH_OBJECT;
}
struct mib_leaf *leaf = &mib_node->leaf;
return leaf->filler(p, c);
}
void
snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, struct mib_walk_state *walk)
{
mib_node_u *node;
node = mib_tree_find(p->mib_tree, walk, &c->sr_vb_start->name);
(void) snmp_mib_fill2(p, c, node);
}
int
snmp_get_next_pdu(struct snmp_proto *p, struct snmp_pdu *c, struct mib_walk_state *walk)
{
mib_node_u *node;
node = mib_tree_find(p->mib_tree, walk, &c->sr_vb_start->name);
int inclusive = c->sr_vb_start->name.include;
int move_next;
if (!node && inclusive)
move_next = 1;
else if (!node && !inclusive)
move_next = 1;
else if (node && inclusive && mib_node_is_leaf(node))
move_next = 0;
else if (node && inclusive)
move_next = 1;
else if (node && !inclusive)
move_next = 0;
struct mib_leaf *leaf = &node->leaf;
if (move_next && node && mib_node_is_leaf(node))
move_next = leaf->call_next(p, c, walk);
if (move_next)
node = (mib_node_u *) mib_tree_walk_next_leaf(p->mib_tree, walk);
enum snmp_search_res res;
res = snmp_mib_fill2(p, c, node);
if (res != SNMP_SEARCH_OK)
snmp_set_varbind_type(c->sr_vb_start, AGENTX_END_OF_MIB_VIEW);
return res == SNMP_SEARCH_OK;
}
void
snmp_get_bulk_pdu(struct snmp_proto *p, struct snmp_pdu *c, struct mib_walk_state *walk, struct agentx_bulk_state *bulk)
{
if (c->index >= bulk->getbulk.non_repeaters)
bulk->repeaters++;
// store the o_start and o_end
bulk->has_any |= snmp_get_next_pdu(p, c, walk);
}
/* /*
* parse_gets_pdu - parse received gets PDUs * parse_gets_pdu - parse received gets PDUs
* @p: SNMP protocol instance * @p: SNMP protocol instance
@ -1513,9 +1545,7 @@ static uint
parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start) parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
// TODO checks for c.size underflow // TODO checks for c.size underflow
//struct agentx_varbind *vb = NULL; struct mib_walk_state walk;
struct agentx_varbind *vb_start = NULL;
struct oid *o_end = NULL;
byte *pkt = pkt_start; byte *pkt = pkt_start;
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
@ -1530,7 +1560,6 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
* Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW * Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW
* has_any is true if some varbind has type other than END_OF_MIB_VIEW * has_any is true if some varbind has type other than END_OF_MIB_VIEW
*/ */
int has_any = 0;
struct agentx_bulk_state bulk_state = { }; struct agentx_bulk_state bulk_state = { };
if (h->type == AGENTX_GET_BULK_PDU) if (h->type == AGENTX_GET_BULK_PDU)
{ {
@ -1544,6 +1573,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
struct agentx_getbulk *bulk_info = (void *) pkt; struct agentx_getbulk *bulk_info = (void *) pkt;
ADVANCE(pkt, pkt_size, sizeof(struct agentx_getbulk)); ADVANCE(pkt, pkt_size, sizeof(struct agentx_getbulk));
//TODO: bulk_state = AGENTX_BULK_STATE_INITIALIZER(bulk_info);
bulk_state = (struct agentx_bulk_state) { bulk_state = (struct agentx_bulk_state) {
.getbulk = { .getbulk = {
.non_repeaters = LOAD_U32(bulk_info->non_repeaters), .non_repeaters = LOAD_U32(bulk_info->non_repeaters),
@ -1552,6 +1582,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
/* In contrast to the RFC, we use 0-based indices. */ /* In contrast to the RFC, we use 0-based indices. */
.index = 0, .index = 0,
.repetition = 0, .repetition = 0,
.has_any = 0,
}; };
} }
@ -1592,30 +1623,34 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
/* We don't too to check for oversided OID because the PDU has 8k size limit */ /* We don't too to check for oversided OID because the PDU has 8k size limit */
/* We create copy of OIDs outside of rx-buffer and also prefixize them */ /* We create copy of OIDs outside of rx-buffer and also prefixize them */
vb_start = snmp_vb_to_tx(p, o_start_rx, &c); c.sr_vb_start = snmp_vb_to_tx(p, o_start_rx, &c);
o_end = snmp_oid_to_scratch(o_end_rx); c.sr_o_end = snmp_oid_to_scratch(o_end_rx);
ASSERT(vb_start); ASSERT(c.sr_vb_start); // TODO implement failed parsing logic
ASSERT(o_end); ASSERT(c.sr_o_end);
if (!snmp_is_oid_empty(o_end) && snmp_oid_compare(&vb_start->name, o_end) > 0) if (!snmp_is_oid_empty(c.sr_o_end) &&
snmp_oid_compare(&c.sr_vb_start->name, c.sr_o_end) > 0)
{ {
c.error = AGENTX_RES_GEN_ERROR; c.error = AGENTX_RES_GEN_ERROR;
return parse_gets_error(p, &c, pkt_size); return parse_gets_error(p, &c, pkt_size);
} }
/* TODO find mib_class, check if type is GET of GET_NEXT, act accordingly */
switch (h->type) switch (h->type)
{ {
case AGENTX_GET_PDU: case AGENTX_GET_PDU:
snmp_mib_fill(p, &vb_start, &c); snmp_get_pdu(p, &c, &walk);
//snmp_mib_fill(p, &vb_start, &c);
break; break;
case AGENTX_GET_NEXT_PDU: case AGENTX_GET_NEXT_PDU:
snmp_get_next2(p, &vb_start, o_end, &c); snmp_get_next_pdu(p, &c, &walk);
//snmp_get_next2(p, &vb_start, o_end, &c);
break; break;
case AGENTX_GET_BULK_PDU: case AGENTX_GET_BULK_PDU:
snmp_get_bulk_pdu(p, &c, &walk, &bulk_state);
#if 0
if (c.index >= bulk_state.getbulk.non_repeaters) if (c.index >= bulk_state.getbulk.non_repeaters)
bulk_state.repeaters++; bulk_state.repeaters++;
@ -1624,14 +1659,15 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
/* The behavior of GetBulk pdu in the first iteration is /* The behavior of GetBulk pdu in the first iteration is
* identical to GetNext pdu. */ * identical to GetNext pdu. */
has_any = snmp_get_next2(p, &vb_start, o_end, &c) || has_any; has_any = snmp_get_next2(p, &vb_start, o_end, &c) || has_any;
#endif
break; break;
default: default:
die("incorrect usage"); die("incorrect usage");
} }
vb_start = NULL; c.sr_vb_start = NULL;
o_end = NULL; c.sr_o_end = NULL;
c.index++; c.index++;
} /* while (c.error == AGENTX_RES_NO_ERROR && size > 0) */ } /* while (c.error == AGENTX_RES_NO_ERROR && size > 0) */
@ -1641,6 +1677,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
if (h->type == AGENTX_GET_BULK_PDU) if (h->type == AGENTX_GET_BULK_PDU)
{ {
#if 0 #if 0
// TODO
for (bulk_state.repetition++; for (bulk_state.repetition++;
has_any && bulk_state.repetition < bulk_state.getbulk.max_repetitions; has_any && bulk_state.repetition < bulk_state.getbulk.max_repetitions;
bulk_state.repetition++) bulk_state.repetition++)
@ -1660,6 +1697,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
/* We send the message in TX-buffer. */ /* We send the message in TX-buffer. */
sk_send(sk, s); sk_send(sk, s);
// TODO think through the error state // TODO think through the error state
/* number of bytes parsed from RX-buffer */ /* number of bytes parsed from RX-buffer */
@ -2022,6 +2060,7 @@ snmp_prefixize(struct snmp_proto *proto, const struct oid *oid)
static void static void
snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c) snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c)
{ {
(void) p;
ASSUME(vb != NULL && *vb != NULL); ASSUME(vb != NULL && *vb != NULL);
struct oid *oid = &((*vb)->name); struct oid *oid = &((*vb)->name);
@ -2037,7 +2076,7 @@ snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu
switch (mib_class) switch (mib_class)
{ {
case SNMP_CLASS_BGP: case SNMP_CLASS_BGP:
snmp_bgp_fill(p, vb, c); //snmp_bgp_fill(p, vb, c);
break; break;
case SNMP_CLASS_INVALID: case SNMP_CLASS_INVALID:
@ -2050,7 +2089,26 @@ snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu
} }
/* /*
* snmp_manage_tbuf - handle situation with too short transmit buffer * snmp_manage_tbuf - TODO
*/
void
snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c)
{
sock *sk = p->sock;
int diff;
if (c->sr_vb_start != NULL)
diff = (void *) c->sr_vb_start - (void *) sk->tbuf;
log(L_INFO "snmp_manage_tbuf2()");
sk_set_tbsize(sk, sk->tbsize + 2048);
c->size += 2048;
if (c->sr_vb_start != NULL)
c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + diff);
}
/*
* snmp_manage_tbuf2 - handle situation with too short transmit buffer
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @c: transmit packet context to use * @c: transmit packet context to use
* *
@ -2058,7 +2116,7 @@ snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu
* are invalidated! * are invalidated!
*/ */
void void
snmp_manage_tbuf(struct snmp_proto *p, void **ptr, struct snmp_pdu *c) snmp_manage_tbuf2(struct snmp_proto *p, void **ptr, struct snmp_pdu *c)
{ {
sock *sk = p->sock; sock *sk = p->sock;
int diff; int diff;
@ -2069,7 +2127,6 @@ snmp_manage_tbuf(struct snmp_proto *p, void **ptr, struct snmp_pdu *c)
sk_set_tbsize(sk, sk->tbsize + 2048); sk_set_tbsize(sk, sk->tbsize + 2048);
c->size += 2048; c->size += 2048;
if (ptr) if (ptr)
*ptr = sk->tbuf + diff; *ptr = sk->tbuf + diff;
} }

View File

@ -191,11 +191,6 @@ struct agentx_octet_str {
byte data[0]; byte data[0];
}; };
struct agentx_getbulk {
u16 non_repeaters;
u16 max_repetitions;
};
struct agentx_response { struct agentx_response {
struct agentx_header h; struct agentx_header h;
u32 uptime; u32 uptime;
@ -219,11 +214,17 @@ struct agentx_un_register_hdr {
u8 reserved; /* always zero filled */ u8 reserved; /* always zero filled */
}; };
struct agentx_getbulk {
u16 non_repeaters;
u16 max_repetitions;
};
struct agentx_bulk_state { struct agentx_bulk_state {
struct agentx_getbulk getbulk; struct agentx_getbulk getbulk;
u16 index; u16 index;
u16 repetition; u16 repetition;
u32 repeaters; u32 repeaters;
int has_any; /* flag is clear when all responses are EndOfMibView */
}; };
enum agentx_pdu_types { enum agentx_pdu_types {
@ -292,17 +293,29 @@ enum agentx_response_errs {
AGENTX_RES_PROCESSING_ERR = 268, /* processingError */ AGENTX_RES_PROCESSING_ERR = 268, /* processingError */
} PACKED; } PACKED;
/* SNMP PDU TX-buffer info */ /* SNMP PDU info */
struct snmp_pdu { struct snmp_pdu {
/* TX buffer */
byte *buffer; /* pointer to buffer */ byte *buffer; /* pointer to buffer */
uint size; /* unused space in buffer */ uint size; /* unused space in buffer */
/* Search Range */
struct agentx_varbind *sr_vb_start; /* search range starting OID inside TX buffer (final storage) */
struct oid *sr_o_end; /* search range ending OID */
/* Control */
enum agentx_response_errs error; /* storage for result of current action */ enum agentx_response_errs error; /* storage for result of current action */
u32 index; /* index on which the error was found */ u32 index; /* index on which the error was found */
union snmp_mibs_data *mibs_data; /* data passed from MIB search phase to MIB fill phase */
}; };
struct snmp_proto_pdu { #include "bgp4_mib.h"
struct snmp_proto *p;
struct snmp_pdu *c; union snmp_mibs_data {
enum snmp_tags empty;
struct bgp4_mib bgp4;
}; };
struct snmp_packet_info { struct snmp_packet_info {
@ -331,7 +344,7 @@ void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len,
void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len, uint contid); void snmp_unregister(struct snmp_proto *p, struct oid *oid, uint index, uint len, uint contid);
void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime); void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime);
void snmp_manage_tbuf(struct snmp_proto *p, void **ptr, struct snmp_pdu *c); void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu *c);
struct agentx_varbind *snmp_vb_to_tx(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c); struct agentx_varbind *snmp_vb_to_tx(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c);
u8 snmp_get_mib_class(const struct oid *oid); u8 snmp_get_mib_class(const struct oid *oid);