0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +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 subagent.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)
$(all-daemon)
$(cf-local)

View File

@ -8,10 +8,12 @@
* 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_utils.h"
#include "subagent.h"
#include "bgp_mib.h"
/* hash table macros */
#define SNMP_HASH_KEY(n) n->peer_ip
@ -25,13 +27,21 @@
/* hash table only store ip4 addresses */
#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
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
* SNMP_BPG_IDENTIFIER == 1
* SNMP_BGP_IDENTIFIER == 1
*/
if (field > 0 && field <= ARRAY_SIZE(translation_table)- 1)
return translation_table[field];
@ -193,25 +203,22 @@ snmp_bgp_state(const struct oid *oid)
return state;
}
void
snmp_bgp_reg_ok(struct snmp_proto *p, struct agentx_response *r, struct oid *oid)
static void
snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{
(void)p;
(void)r;
const struct oid * const oid = reg->oid;
(void)oid;
/* TODO: EXPENSIVE_CHECK() that
const struct oid *in_buf = ((void *) r) + sizeof(r);
struct oid *dup = snmp_prefixize(p, in_buf);
ASSUME(snmp_bgp_state(oid) == snmp_bgp_state(dup));
mb_free(dup);
*/
(void)p;
(void) res;
}
void
snmp_bgp_reg_failed(struct snmp_proto *p, struct agentx_response UNUSED *r, struct oid UNUSED *oid)
static void
snmp_bgp_reg_failed(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{
// TODO add more sensible action
snmp_stop_subagent(p);
const struct oid * const oid = reg->oid;
(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);
}
/* We have enough space inside the TX-buffer prepared */
struct snmp_pdu sink = { 0 };
snmp_varbind_ip4(addr_vb, &sink, ip4);
struct snmp_pdu dummy = { 0 };
dummy.sr_vb_start = addr_vb;
snmp_varbind_ip4(&dummy, ip4);
{ /* BGP4-MIB::bgpPeerLastError */
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;
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 */
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;
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 */
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
snmp_bgp_register(struct snmp_proto *p)
snmp_bgp4_register(struct snmp_proto *p)
{
u32 bgp_mib_prefix[] = { 1, 15 };
// TODO
{
/* 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));
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
@ -390,7 +405,7 @@ snmp_bgp_register(struct snmp_proto *p)
}
static int
snmp_bgp_valid_ip4(struct oid *o)
snmp_bgp_valid_ip4(const struct oid *o)
{
return snmp_valid_ip4_index(o, 5);
}
@ -586,6 +601,565 @@ oid_state_compare(const struct oid *oid, u8 state)
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 *
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))
addr = ip4_from_oid(oid);
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);
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;
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_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);
@ -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.",
bgp_proto->p.name);
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;
@ -931,20 +1513,20 @@ bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_p
{
case BGP4_MIB_S_PEER_IDENTIFIER:
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)
// 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
snmp_varbind_ip4(*vb, c, IP4_NONE);
; //snmp_varbind_ip4(*vb, c, IP4_NONE);
break;
case BGP4_MIB_S_STATE:
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;
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);
if (bgp_proto->p.disabled)
snmp_varbind_int(*vb, c, AGENTX_ADMIN_STOP);
; //snmp_varbind_int(*vb, c, AGENTX_ADMIN_STOP);
else
snmp_varbind_int(*vb, c, AGENTX_ADMIN_START);
; //snmp_varbind_int(*vb, c, AGENTX_ADMIN_START);
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)
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)
snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_VALUE);
; //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_VALUE);
else
snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE);
; //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE);
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)
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;
case BGP4_MIB_S_LOCAL_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
case BGP4_MIB_S_REMOTE_ADDR:
if (c->size < AGENTX_TYPE_IP4_SIZE)
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;
case BGP4_MIB_S_REMOTE_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
case BGP4_MIB_S_REMOTE_AS:
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
case BGP4_MIB_S_RX_UPDATES: /* bgpPeerInUpdates */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
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;
case BGP4_MIB_S_TX_UPDATES: /* bgpPeerOutUpdate */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
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;
case BGP4_MIB_S_RX_MESSAGES: /* bgpPeerInTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
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;
case BGP4_MIB_S_TX_MESSAGES: /* bgpPeerOutTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
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;
case BGP4_MIB_S_LAST_ERROR:
if (c->size < snmp_str_size_from_len(2))
SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_nstr(*vb, c, last_error, 2);
; //snmp_varbind_nstr(*vb, c, last_error, 2);
break;
case BGP4_MIB_S_FSM_TRANSITIONS:
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_counter32(*vb, c,
bgp_stats->fsm_established_transitions);
//snmp_varbind_counter32(*vb, c,
// bgp_stats->fsm_established_transitions);
break;
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_varbind_gauge32(*vb, c,
(current_time() - bgp_proto->last_established) TO_S);
//snmp_varbind_gauge32(*vb, c,
// (current_time() - bgp_proto->last_established) TO_S);
break;
case BGP4_MIB_S_RETRY_INTERVAL: /* retry inverval value should be != 0 */
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
case BGP4_MIB_S_HOLD_TIME: /* hold time should be == 0 or in 3..65535 */
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
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);
if (!bgp_conf->hold_time)
snmp_varbind_int(*vb, c, 0);
; //snmp_varbind_int(*vb, c, 0);
else
snmp_varbind_int(*vb, c,
(bgp_conn) ? bgp_conn->keepalive_time : 0);
; //snmp_varbind_int(*vb, c,
// (bgp_conn) ? bgp_conn->keepalive_time : 0);
break;
case BGP4_MIB_S_HOLD_TIME_CONFIGURED:
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
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)
snmp_varbind_int(*vb, c, 0);
; //snmp_varbind_int(*vb, c, 0);
else
snmp_varbind_int(*vb, c,
(bgp_conn) ? bgp_conn->keepalive_time : 0);
; //snmp_varbind_int(*vb, c,
// (bgp_conn) ? bgp_conn->keepalive_time : 0);
break;
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)
SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, 0);
//snmp_varbind_int(*vb, c, 0);
break;
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)
SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_int(*vb, c, 0);
//snmp_varbind_int(*vb, c, 0);
break;
case BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
snmp_varbind_gauge32(*vb, c,
(current_time() - bgp_proto->last_rx_update) TO_S
);
//snmp_varbind_gauge32(*vb, c,
//(current_time() - bgp_proto->last_rx_update) TO_S
//);
break;
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);
c->size -= sz;
snmp_varbind_nstr(*vb, c, BGP4_VERSIONS, 1);
//snmp_varbind_nstr(*vb, c, BGP4_VERSIONS, 1);
break;
case BGP4_MIB_S_LOCAL_AS:
if (c->size < AGENTX_TYPE_INT_SIZE)
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;
case BGP4_MIB_S_IDENTIFIER:
if (c->size < AGENTX_TYPE_IP4_SIZE)
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;
default:

View File

@ -1,9 +1,29 @@
#ifndef _BIRD_SNMP_BGP_MIB_H_
#define _BIRD_SNMP_BGP_MIB_H_
#ifndef _BIRD_SNMP_BGP4_MIB_H_
#define _BIRD_SNMP_BGP4_MIB_H_
#ifdef _BIRD_SNMP_SUBAGENT_H_
#define BIRD_SNMP_BGP4_SKIP
#endif
#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"
#ifndef BIRD_SNMP_BGP4_SKIP
#define BGP4_MIB 15
/* peers attributes */
@ -40,11 +60,6 @@ enum bgp4_mib_peer_entry_row {
#define BGP4_MIB_NEGOTIATED_VER_VALUE 4
#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_getnext_valid(u8 state);
@ -127,3 +142,5 @@ STATIC_ASSERT(BGP4_MIB_ESTABLISHED == BS_ESTABLISHED + 1);
#define BGP4_MIB_BACKWARD_TRANS_NOTIFICATION 2
#endif
#endif

View File

@ -18,7 +18,7 @@ CF_DEFINES
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)
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
* @t: pointer to a tree being initialized
*

View File

@ -24,10 +24,13 @@ struct mib_node {
u32 child_len;
};
struct mib_walk_state;
struct mib_leaf {
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_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;
int size;
};

View File

@ -10,7 +10,7 @@
*
* The SNMP protocol is divided into several parts: |snmp.c| which implements
* 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
* working with OIDs, VarBinds.
*
@ -334,14 +334,6 @@ snmp_cleanup(struct snmp_proto *p)
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);
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);
init_list(&p->registration_queue);
init_list(&p->bgp_registered);
/* We create copy of bonds to BGP protocols. */
HASH_INIT(p->bgp_hash, p->pool, 10);

View File

@ -17,8 +17,7 @@
#include "nest/bird.h"
#include "nest/protocol.h"
#include "filter/data.h"
#include "proto/bgp/bgp.h"
#include "proto/bgp/bgp.h" // TODO remove me
#define SNMP_UNDEFINED 0
#define SNMP_BGP 1
@ -42,6 +41,11 @@ enum snmp_proto_state {
SNMP_RESET,
};
enum snmp_tags {
EMPTY_TAG = 0,
BGP4_TAG,
};
struct snmp_bond {
node n;
struct proto_config *config;
@ -81,20 +85,13 @@ struct snmp_bgp_peer {
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 {
node n;
struct oid *oid;
};
struct mib_tree; /* see mib_tree.h */
struct snmp_proto {
struct proto p;
struct object_lock *lock;
@ -125,8 +122,6 @@ struct snmp_proto {
uint registrations_to_ack; /* counter of pending responses to register-pdu */
list registration_queue; /* list containing snmp_register records */
list bgp_registered; /* list of currently registered bgp oids
* (struct snmp_registered_oid) */
// map
struct f_trie *bgp_trie;
@ -138,6 +133,23 @@ struct snmp_proto {
timer *ping_timer;
btime startup_delay;
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);

View File

@ -385,7 +385,7 @@ t_oid_compare(void)
bt_assert(snmp_oid_compare(no_pref2, 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(no_pref2, pref) > 0);
bt_assert(snmp_oid_compare(no_pref, pref2) < 0);
@ -1119,7 +1119,7 @@ gen_test_find(struct oid *(*generator)(void))
last = found;
/* test finding with walk state not pointing at the root of the tree */
u8 subids = LOAD_U8(oids[i]->n_subid);
u8 subids = LOAD_U8(oids[i]->n_subid);
if (subids > 0)
{
found = NULL;
@ -1204,10 +1204,10 @@ gen_test_find(struct oid *(*generator)(void))
mib_tree_walk_init(&walk, (xrandom(2)) ? tree : NULL);
STORE_U8(searched[search]->n_subid, new_ids);
mib_node_u *ignored UNUSED;
ignored = mib_tree_find(tree, &walk, searched[search]);
STORE_U8(searched[search]->n_subid, subids);
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, NULL);
mib_node_u *node = mib_tree_find(tree, &walk, sorted[j]);
if (snmp_is_oid_empty(oid))
;
/* 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]);
}
int bound = 0;
int bound = 0;
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(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])))
oid_index++;
@ -1646,7 +1646,7 @@ gen_test_leafs(struct oid *(*generator)(void))
current = mib_tree_walk_next_leaf(tree, &walk);
bt_assert(current == NULL);
bt_assert(oid_index == distinct);
bt_assert(oid_index == distinct);
bt_assert(i == leafs);
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);
if (c->size < diff_size)
{
snmp_manage_tbuf(p, (void **) vb, c);
snmp_manage_tbuf(p, c);
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);
uint hdr_size = snmp_varbind_header_size(*vb);
if (c->size < hdr_size)
snmp_manage_tbuf(p, (void **) vb, c);
snmp_manage_tbuf(p, c);
ASSERT(c->size >= hdr_size);
byte *buffer = c->buffer;
@ -260,12 +260,38 @@ snmp_varbind_hdr_size_from_oid(const struct oid *oid)
*
* This function assumes valid @t.
*/
inline void
inline enum snmp_search_res
snmp_set_varbind_type(struct agentx_varbind *vb, enum agentx_type t)
{
ASSUME(t != AGENTX_INVALID);
STORE_U16(vb->type, t);
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 */
@ -660,7 +686,7 @@ snmp_oid_compare(const struct oid *left, const struct oid *right)
/* check prefix */
if (LOAD_U32(left->ids[4]) < (u32) right_prefix)
return -1;
else if (LOAD_U32(left->ids[4]) > (u32) right_prefix)
else if (LOAD_U32(left->ids[4]) > (u32) right_prefix)
return 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
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
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
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
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
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);
c->buffer = snmp_put_ip4(snmp_varbind_data(vb), addr);
snmp_set_varbind_type(c->sr_vb_start, AGENTX_IP_ADDRESS);
c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
}
// TODO doc string, we have already the varbind prepared
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))
return NULL;
snmp_set_varbind_type(vb, AGENTX_OCTET_STRING);
return snmp_put_nstr(snmp_varbind_data(vb), str, len);
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
return snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
}
/*
@ -851,10 +878,10 @@ snmp_varbind_nstr2(struct agentx_varbind *vb, uint size, const char *str, uint l
* more info.
*/
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);
c->buffer = snmp_put_nstr(snmp_varbind_data(vb), str, len);
snmp_set_varbind_type(c->sr_vb_start, AGENTX_OCTET_STRING);
c->buffer = snmp_put_nstr(snmp_varbind_data(c->sr_vb_start), str, len);
}
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
*/
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);
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 */
struct agentx_varbind *snmp_create_varbind(byte *buf, struct oid *oid);
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_counter32(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val);
void snmp_varbind_gauge32(struct agentx_varbind *vb, struct snmp_pdu *c, s64 time);
void snmp_varbind_ticks(struct agentx_varbind *vb, struct snmp_pdu *c, u32 val);
void snmp_varbind_ip4(struct agentx_varbind *vb, 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_int(struct snmp_pdu *c, u32 val);
void snmp_varbind_counter32(struct snmp_pdu *c, u32 val);
void snmp_varbind_gauge32(struct snmp_pdu *c, s64 time);
void snmp_varbind_ticks(struct snmp_pdu *c, u32 val);
void snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr);
void snmp_varbind_nstr(struct snmp_pdu *c, const char *str, uint len);
/* Raw */
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 "subagent.h"
#include "mib_tree.h"
#include "snmp_utils.h"
#include "bgp_mib.h"
#include "bgp4_mib.h"
/* =============================================================
* Problems
@ -115,45 +116,11 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
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
* @p: SNMP protocol instance
* @res: header of agentx-Response-PDU
* @class: MIB subtree associated with agentx-Register-PDU
* @class: MIB subtree associated with agentx-Register-PDU
*/
void
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;
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))
{
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);
mb_free(reg);
p->registrations_to_ack--;
add_tail(&p->bgp_registered, &ro->n);
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
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;
}
}
@ -247,7 +206,7 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
/* Make sure that we have enough space in TX-buffer */
if (c.size < AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
+ snmp_str_size(cf->description))
snmp_manage_tbuf(p, NULL, &c);
snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer;
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;
snmp_pdu_context(&c, sk);
// TODO use more readable anonymous structure decl.
#define UPTIME_SIZE \
(6 * sizeof(u32)) /* sizeof( { u32 vb_type, u32 oid_hdr, u32 ids[4] } ) */
#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 */
if (c.size < sz)
snmp_manage_tbuf(p, NULL, &c);
snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer;
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] */
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));
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)
/* 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);
if (c.size < sz)
snmp_manage_tbuf(p, NULL, &c);
snmp_manage_tbuf(p, &c);
struct agentx_header *h = (void *) c.buffer;
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)
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;
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);
if (c.size < AGENTX_HEADER_SIZE)
snmp_manage_tbuf(p, NULL, &c);
snmp_manage_tbuf(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)");
/* 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);
}
@ -711,7 +670,7 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
struct snmp_pdu c;
snmp_pdu_context(&c, p->sock);
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);
@ -786,6 +745,7 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
if (pkt_size != 0)
{
// TODO should we free even for malformed packets ??
// TODO -> check that data is not freed
return AGENTX_HEADER_SIZE;
}
@ -981,8 +941,7 @@ parse_response(struct snmp_proto *p, byte *res)
void
snmp_register_mibs(struct snmp_proto *p)
{
snmp_bgp_register(p);
/* snmp_ospf_regsiter(p); ... */
snmp_bgp4_register(p);
}
/*
@ -1071,7 +1030,8 @@ snmp_get_mib_class(const struct oid *oid)
*
* 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)
{
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;
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);
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))
snmp_manage_tbuf(p, (void **) vb, c);
snmp_manage_tbuf(p, c);
vb = snmp_create_varbind(c->buffer, o_start);
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);
if (c->size < oid_size)
snmp_manage_tbuf(p, NULL, c);
snmp_manage_tbuf(p, c);
// TODO check if the @oid is prefixable
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);
if (c->size < vb_hdr_size)
snmp_manage_tbuf(p, NULL, c);
snmp_manage_tbuf(p, c);
ASSERT(c->size >= vb_hdr_size);
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;
}
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
* @p: SNMP protocol instance
@ -1513,9 +1545,7 @@ static uint
parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
{
// TODO checks for c.size underflow
//struct agentx_varbind *vb = NULL;
struct agentx_varbind *vb_start = NULL;
struct oid *o_end = NULL;
struct mib_walk_state walk;
byte *pkt = pkt_start;
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
* 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 = { };
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;
ADVANCE(pkt, pkt_size, sizeof(struct agentx_getbulk));
//TODO: bulk_state = AGENTX_BULK_STATE_INITIALIZER(bulk_info);
bulk_state = (struct agentx_bulk_state) {
.getbulk = {
.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. */
.index = 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 create copy of OIDs outside of rx-buffer and also prefixize them */
vb_start = snmp_vb_to_tx(p, o_start_rx, &c);
o_end = snmp_oid_to_scratch(o_end_rx);
c.sr_vb_start = snmp_vb_to_tx(p, o_start_rx, &c);
c.sr_o_end = snmp_oid_to_scratch(o_end_rx);
ASSERT(vb_start);
ASSERT(o_end);
ASSERT(c.sr_vb_start); // TODO implement failed parsing logic
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;
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)
{
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;
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;
case AGENTX_GET_BULK_PDU:
snmp_get_bulk_pdu(p, &c, &walk, &bulk_state);
#if 0
if (c.index >= bulk_state.getbulk.non_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
* identical to GetNext pdu. */
has_any = snmp_get_next2(p, &vb_start, o_end, &c) || has_any;
#endif
break;
default:
die("incorrect usage");
}
vb_start = NULL;
o_end = NULL;
c.sr_vb_start = NULL;
c.sr_o_end = NULL;
c.index++;
} /* 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 0
// TODO
for (bulk_state.repetition++;
has_any && bulk_state.repetition < bulk_state.getbulk.max_repetitions;
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. */
sk_send(sk, s);
// TODO think through the error state
/* number of bytes parsed from RX-buffer */
@ -2022,6 +2060,7 @@ snmp_prefixize(struct snmp_proto *proto, const struct oid *oid)
static void
snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c)
{
(void) p;
ASSUME(vb != NULL && *vb != NULL);
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)
{
case SNMP_CLASS_BGP:
snmp_bgp_fill(p, vb, c);
//snmp_bgp_fill(p, vb, c);
break;
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
* @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!
*/
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;
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);
c->size += 2048;
if (ptr)
*ptr = sk->tbuf + diff;
}

View File

@ -191,11 +191,6 @@ struct agentx_octet_str {
byte data[0];
};
struct agentx_getbulk {
u16 non_repeaters;
u16 max_repetitions;
};
struct agentx_response {
struct agentx_header h;
u32 uptime;
@ -219,11 +214,17 @@ struct agentx_un_register_hdr {
u8 reserved; /* always zero filled */
};
struct agentx_getbulk {
u16 non_repeaters;
u16 max_repetitions;
};
struct agentx_bulk_state {
struct agentx_getbulk getbulk;
u16 index;
u16 repetition;
u32 repeaters;
int has_any; /* flag is clear when all responses are EndOfMibView */
};
enum agentx_pdu_types {
@ -292,17 +293,29 @@ enum agentx_response_errs {
AGENTX_RES_PROCESSING_ERR = 268, /* processingError */
} PACKED;
/* SNMP PDU TX-buffer info */
/* SNMP PDU info */
struct snmp_pdu {
/* TX buffer */
byte *buffer; /* pointer to 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 */
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 {
struct snmp_proto *p;
struct snmp_pdu *c;
#include "bgp4_mib.h"
union snmp_mibs_data {
enum snmp_tags empty;
struct bgp4_mib bgp4;
};
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_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);
u8 snmp_get_mib_class(const struct oid *oid);