* 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
/* 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
-/* Simply discard type */
-#define SNMP_MANAGE_TBUF(p, vb, c) snmp_manage_tbuf(p, (void **) vb, c)
+#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
-static inline void ip4_to_oid(struct oid *oid, ip4_addr addr);
+#define POPULATE_BGP4(addr, proto, conn, stats, config) populate_bgp4(p, c, &(addr), &(proto), &(conn), &(stats), &(config))
+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)
{
/*
* 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];
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;
}
/*
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;
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;
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);
}
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 */
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
}
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 -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)
{
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);
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;
{
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:
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;
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;
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:
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:
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:
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:
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:
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:
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:
#include "lib/unaligned.h"
#include "subagent.h"
+#include "mib_tree.h"
#include "snmp_utils.h"
-#include "bgp_mib.h"
+#include "bgp4_mib.h"
/* =============================================================
* Problems
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)
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(®->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;
}
}
/* 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);
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 \
/* 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);
/* 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));
}
#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);
#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);
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);
{
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);
}
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);
if (pkt_size != 0)
{
// TODO should we free even for malformed packets ??
+ // TODO -> check that data is not freed
return AGENTX_HEADER_SIZE;
}
void
snmp_register_mibs(struct snmp_proto *p)
{
- snmp_bgp_register(p);
- /* snmp_ospf_regsiter(p); ... */
+ snmp_bgp4_register(p);
}
/*
*
* 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;
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;
}
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;
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);
{
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;
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
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;
* 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)
{
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),
/* In contrast to the RFC, we use 0-based indices. */
.index = 0,
.repetition = 0,
+ .has_any = 0,
};
}
/* 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++;
/* 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) */
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++)
/* We send the message in TX-buffer. */
sk_send(sk, s);
+
// TODO think through the error state
/* number of bytes parsed from RX-buffer */
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);
switch (mib_class)
{
case SNMP_CLASS_BGP:
- snmp_bgp_fill(p, vb, c);
+ //snmp_bgp_fill(p, vb, c);
break;
case SNMP_CLASS_INVALID:
}
/*
- * 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
*
* 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;
sk_set_tbsize(sk, sk->tbsize + 2048);
c->size += 2048;
-
if (ptr)
*ptr = sk->tbuf + diff;
}