0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

SNMP: Progress

Remove old logging messages, improve and correct function documentation,
minor tweaks and bugfixes
This commit is contained in:
Vojtech Vilimek 2024-08-09 21:05:32 +02:00
parent ffda7d1b2a
commit a70ab3051f
8 changed files with 275 additions and 399 deletions

View File

@ -144,7 +144,7 @@ snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_
addr->ids[ENTRY_TYPE] = BGP4_MIB_REMOTE_ADDR; addr->ids[ENTRY_TYPE] = BGP4_MIB_REMOTE_ADDR;
ip4_to_oid(addr, ip4); ip4_to_oid(addr, ip4);
} }
/* We have enough space inside the TX-buffer prepared */ /* We have enough space inside the TX buffer prepared */
struct snmp_pdu dummy = { 0 }; struct snmp_pdu dummy = { 0 };
dummy.sr_vb_start = addr_vb; dummy.sr_vb_start = addr_vb;
snmp_varbind_ip4(&dummy, ip4); snmp_varbind_ip4(&dummy, ip4);
@ -248,6 +248,7 @@ snmp_bgp4_register(struct snmp_proto *p)
STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix)); STORE_U8(oid->n_subid, ARRAY_SIZE(bgp_mib_prefix));
STORE_U8(oid->prefix, SNMP_MGMT); STORE_U8(oid->prefix, SNMP_MGMT);
// TODO use STATIC_OID
memcpy(oid->ids, bgp_mib_prefix, sizeof(bgp_mib_prefix)); memcpy(oid->ids, bgp_mib_prefix, sizeof(bgp_mib_prefix));
reg->oid = oid; reg->oid = oid;
reg->reg_hook_ok = snmp_bgp_reg_ok; reg->reg_hook_ok = snmp_bgp_reg_ok;
@ -257,7 +258,7 @@ snmp_bgp4_register(struct snmp_proto *p)
* We set both upper bound and index to zero, therefore only single OID * We set both upper bound and index to zero, therefore only single OID
* is being registered. * is being registered.
*/ */
snmp_register(p, oid, 0, 0, SNMP_REGISTER_TREE, SNMP_DEFAULT_CONTEXT); snmp_register(p, oid, 0, 0, SNMP_REGISTER_TREE);
} }
} }
@ -267,7 +268,6 @@ snmp_bgp_valid_ip4(const struct oid *o)
return snmp_valid_ip4_index(o, 5); return snmp_valid_ip4_index(o, 5);
} }
static inline ip4_addr static inline ip4_addr
ip4_from_oid(const struct oid *o) ip4_from_oid(const struct oid *o)
{ {
@ -332,7 +332,6 @@ print_bgp_record(const struct bgp_proto *bgp_proto)
DBG(" incoming_conn state: %u", bgp_proto->incoming_conn.state + 1); DBG(" incoming_conn state: %u", bgp_proto->incoming_conn.state + 1);
} }
static inline enum snmp_search_res static inline enum snmp_search_res
populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto, const struct bgp_conn populate_bgp4(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) **conn, const struct bgp_stats **stats, const struct bgp_config **config)
@ -341,23 +340,16 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
if (snmp_bgp_valid_ip4(oid) && LOAD_U8(oid->n_subid) == 9) if (snmp_bgp_valid_ip4(oid) && LOAD_U8(oid->n_subid) == 9)
*addr = ip4_from_oid(oid); *addr = ip4_from_oid(oid);
else else
{
snmp_log("populate() invalid ip4");
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
}
struct snmp_bgp_peer *pe = snmp_hash_find(c->p, *addr); struct snmp_bgp_peer *pe = snmp_hash_find(c->p, *addr);
if (!pe) if (!pe)
{
snmp_log("populate() hash find failed");
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
}
const struct bgp_proto *bgp_proto; const struct bgp_proto *bgp_proto;
*proto = bgp_proto = pe->bgp_proto; *proto = bgp_proto = pe->bgp_proto;
if (!ipa_is_ip4(bgp_proto->remote_ip)) if (!ipa_is_ip4(bgp_proto->remote_ip))
{ {
log(L_ERR "%s: Found BGP protocol instance with IPv6 address", bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR; c->error = AGENTX_RES_GEN_ERROR;
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
} }
@ -366,8 +358,6 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
if (!ip4_equal(proto_ip, pe->peer_ip)) if (!ip4_equal(proto_ip, pe->peer_ip))
{ {
/* Here, we could be in problem as the bgp_proto IP address could be changed */ /* 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 "
"(%I, %I).", bgp_proto->p.name, proto_ip, pe->peer_ip);
c->error = AGENTX_RES_GEN_ERROR; c->error = AGENTX_RES_GEN_ERROR;
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
} }
@ -376,11 +366,9 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
*stats = &bgp_proto->stats; *stats = &bgp_proto->stats;
*config = bgp_proto->cf; *config = bgp_proto->cf;
snmp_log("populate() ok");
return SNMP_SEARCH_OK; return SNMP_SEARCH_OK;
} }
/* /*
* *
* MIB tree fill hooks * MIB tree fill hooks
@ -390,7 +378,6 @@ populate_bgp4(struct snmp_pdu *c, ip4_addr *addr, const struct bgp_proto **proto
static enum snmp_search_res static enum snmp_search_res
fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill ver");
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
c->size -= snmp_str_size_from_len(1); c->size -= snmp_str_size_from_len(1);
@ -401,7 +388,6 @@ fill_bgp_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill as");
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_int(c, c->p->bgp_local_as); snmp_varbind_int(c, c->p->bgp_local_as);
@ -411,7 +397,6 @@ fill_local_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_peer_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_peer_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill peer id");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -431,7 +416,6 @@ fill_peer_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_peer_state(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_peer_state(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill peer state");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -447,7 +431,6 @@ fill_peer_state(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_admin_status(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_admin_status(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill adm status");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -464,7 +447,6 @@ fill_admin_status(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_neg_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_neg_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill neg ver");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -483,13 +465,10 @@ fill_neg_version(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_local_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_local_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("bgp4_mib fill local addr");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
snmp_log("fill local addr result %u", res);
if (res != SNMP_SEARCH_OK) if (res != SNMP_SEARCH_OK)
return res; return res;
@ -500,7 +479,6 @@ fill_local_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_local_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_local_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("bgp4_mib fill local port");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -514,7 +492,6 @@ fill_local_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_remote_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_remote_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("bgp4_mib fill remote addr");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -528,7 +505,6 @@ fill_remote_addr(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_remote_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_remote_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("bgp4_mib fill remote port");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -542,7 +518,6 @@ fill_remote_port(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_remote_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_remote_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill rem as");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -556,7 +531,6 @@ fill_remote_as(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_in_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_in_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill in updates");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -570,7 +544,6 @@ fill_in_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_out_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_out_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill out updates");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -584,7 +557,6 @@ fill_out_updates(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_in_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_in_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill in total");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -598,7 +570,6 @@ fill_in_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_out_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_out_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill out total");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -612,7 +583,6 @@ fill_out_total_msg(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_last_err(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_last_err(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill last err");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -629,7 +599,6 @@ fill_last_err(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_established_trans(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_established_trans(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill est trans");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -644,14 +613,12 @@ fill_established_trans(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_established_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_established_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill est time");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_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) if (res != SNMP_SEARCH_OK)
return res; return res;
snmp_varbind_gauge32(c, snmp_varbind_gauge32(c,
(current_time() - bgp_proto->last_established) TO_S); (current_time() - bgp_proto->last_established) TO_S);
return SNMP_SEARCH_OK; return SNMP_SEARCH_OK;
@ -660,7 +627,6 @@ fill_established_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_retry_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_retry_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill retry int");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -674,7 +640,6 @@ fill_retry_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_hold_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_hold_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill hold time");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -688,7 +653,6 @@ fill_hold_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_keep_alive(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_keep_alive(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill keepalive");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -706,7 +670,6 @@ fill_keep_alive(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_hold_time_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_hold_time_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill hold time c");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -720,14 +683,12 @@ fill_hold_time_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_keep_alive_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_keep_alive_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill keepalive c");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_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) if (res != SNMP_SEARCH_OK)
return res; return res;
if (!bgp_conf->keepalive_time) if (!bgp_conf->keepalive_time)
snmp_varbind_int(c, 0); snmp_varbind_int(c, 0);
else else
@ -739,7 +700,6 @@ fill_keep_alive_conf(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_min_as_org_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_min_as_org_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill min org int");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -754,7 +714,6 @@ fill_min_as_org_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_route_adv_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_route_adv_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill rt adv int");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -769,7 +728,6 @@ fill_route_adv_interval(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
static enum snmp_search_res static enum snmp_search_res
fill_in_update_elapsed_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_in_update_elapsed_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fil in elapsed");
enum snmp_search_res res; enum snmp_search_res res;
DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); DECLARE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf); res = POPULATE_BGP4(addr, bgp_proto, bgp_conn, bgp_stats, bgp_conf);
@ -785,7 +743,6 @@ fill_in_update_elapsed_time(struct mib_walk_state *walk UNUSED, struct snmp_pdu
static enum snmp_search_res static enum snmp_search_res
fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c) fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
{ {
snmp_log("fill local id");
if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3) if (LOAD_U8(c->sr_vb_start->name.n_subid) != 3)
return SNMP_SEARCH_NO_INSTANCE; return SNMP_SEARCH_NO_INSTANCE;
snmp_varbind_ip4(c, c->p->bgp_local_id); snmp_varbind_ip4(c, c->p->bgp_local_id);
@ -797,7 +754,7 @@ fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_pdu *c)
* @state: MIB tree walk state * @state: MIB tree walk state
* @c: SNMP PDU context data * @c: SNMP PDU context data
* *
* Update TX-buffer VarBind name to next peer address. * Update TX buffer VarBind name to next peer address.
*/ */
static int static int
bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c) bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
@ -831,7 +788,6 @@ bgp4_next_peer(struct mib_walk_state *state, struct snmp_pdu *c)
STORE_U8(oid->include, 1); STORE_U8(oid->include, 1);
} }
ASSUME(oid->n_subid == 9); ASSUME(oid->n_subid == 9);
/* Stack has one more node for empty prefix (tree root) */ /* Stack has one more node for empty prefix (tree root) */
ASSUME(state->stack_pos > 10); ASSUME(state->stack_pos > 10);
@ -903,10 +859,6 @@ snmp_bgp4_start(struct snmp_proto *p)
{ {
agentx_available_mibs[BGP4_MIB_ID] = (struct oid *) &bgp4_mib_oid; agentx_available_mibs[BGP4_MIB_ID] = (struct oid *) &bgp4_mib_oid;
snmp_log("snmp_bgp4_start setting bgp4_mib oid %u %p %p %p",
BGP4_MIB_ID, &agentx_available_mibs[BGP4_MIB_ID], agentx_available_mibs[BGP4_MIB_ID], &bgp4_mib_oid);
struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf); struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
/* Create binding to BGP protocols */ /* Create binding to BGP protocols */

View File

@ -49,9 +49,6 @@ snmp_proto_item:
if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT) if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT)
cf_error("Duplicit option remote address"); cf_error("Duplicit option remote address");
// TODO
//if (ip4_zero($3)) cf_error("Invalid remote ip address");
SNMP_CFG->remote_ip = $3; SNMP_CFG->remote_ip = $3;
SNMP_CFG->trans_type = SNMP_TRANS_TCP; SNMP_CFG->trans_type = SNMP_TRANS_TCP;
} }
@ -78,9 +75,11 @@ snmp_proto_item:
} }
| MESSAGE TIMEOUT expr_us { | MESSAGE TIMEOUT expr_us {
/* TODO */ /* TODO */
if ($3 TO_S > 255) log(L_WARN, "%s: msg", this_proto->name); if ($3 TO_S > 255 || $3 TO_S < 1)
if ($3 TO_S < 1) log(L_WARN, "%s: msg", this_proto->name); log(L_WARN "resolution of AgentX message timeout is from 1 to 255 s.");
if (($3 TO_S) - (int)($3 TO_S) > 0) log(L_WARN, "%s: ", this_proto->name); if (($3 TO_S) - (int)($3 TO_S) > 0)
log(L_WARN "AgentX message timeout cannot use second fraction, "
"will use rounded up value.");
SNMP_CFG->timeout = $3; SNMP_CFG->timeout = $3;
} }
/* /*

View File

@ -794,10 +794,7 @@ mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk, u
(void)t; (void)t;
if (walk->stack_pos == 0) if (walk->stack_pos == 0)
{
snmp_log("walk next leaf no leafs");
return NULL; return NULL;
}
u32 next_id = skip; u32 next_id = skip;
mib_node_u *node = walk->stack[walk->stack_pos - 1]; mib_node_u *node = walk->stack[walk->stack_pos - 1];
@ -812,7 +809,6 @@ mib_tree_walk_next_leaf(const struct mib_tree *t, struct mib_walk_state *walk, u
{ {
/* walk->stack_pos == 1, so we NULL out the last stack field */ /* walk->stack_pos == 1, so we NULL out the last stack field */
walk->stack[--walk->stack_pos] = NULL; walk->stack[--walk->stack_pos] = NULL;
snmp_log("walk next leaf single leaf");
return NULL; return NULL;
} }
@ -822,10 +818,7 @@ continue_while:
node = walk->stack[walk->stack_pos - 1]; node = walk->stack[walk->stack_pos - 1];
if (mib_node_is_leaf(node)) if (mib_node_is_leaf(node))
{
snmp_log("walk next leaf %p at level %u", node, walk->stack_pos - 1);
return (struct mib_leaf *) node; return (struct mib_leaf *) node;
}
struct mib_node *node_inner = &node->inner; struct mib_node *node_inner = &node->inner;
for (u32 id = next_id; id < node_inner->child_len; id++) for (u32 id = next_id; id < node_inner->child_len; id++)
@ -845,7 +838,6 @@ continue_while:
walk->stack[--walk->stack_pos] = NULL; walk->stack[--walk->stack_pos] = NULL;
} }
snmp_log("walk next leaf no more leafs");
return NULL; return NULL;
} }

View File

@ -49,7 +49,7 @@
* | SNMP_INIT | entry state after call snmp_start() * | SNMP_INIT | entry state after call snmp_start()
* +-----------------+ * +-----------------+
* | * |
* | acquiring object lock for communication socket * | acquiring object lock for tcp communication socket
* V * V
* +-----------------+ * +-----------------+
* | SNMP_LOCKED | object lock aquired * | SNMP_LOCKED | object lock aquired
@ -61,48 +61,37 @@
* | SNMP_OPEN | socket created, starting subagent * | SNMP_OPEN | socket created, starting subagent
* +-----------------+ * +-----------------+
* | * |
* | BIRD receive response for Open-PDU * | BIRD receive response for agentx-Open-PDU
* V * V
* +-----------------+ * +-----------------+
* | SNMP_REGISTER | session was established, subagent registers MIBs * | SNMP_REGISTER | session was established, subagent registers MIBs
* +-----------------+ * +-----------------+
* | * |
* | subagent received responses for all registration requests * | subagent received response for any registration requests
* V * V
* +-----------------+ * +-----------------+
* | SNMP_CONN | everything is set * | SNMP_CONN | everything is set
* +-----------------+ * +-----------------+
* | * |
* | function snmp_shutdown() is called, BIRD sends Close-PDU * | received malformed PDU, protocol disabled,
* | BIRD sends agentx-Close-PDU or agentx-Response-PDU with an error
* V * V
* +-----------------+ * +-----------------+
* | SNMP_STOP | waiting for response * | SNMP_STOP | waiting until the prepared PDUs are sent
* +-----------------+ * +-----------------+
* | * |
* | cleaning old state information * | cleaning protocol state
* V * V
* +-----------------+ * +-----------------+
* | SNMP_DOWN | session is closed * | SNMP_DOWN | session is closed
* +-----------------+ * +-----------------+
* *
* *
* +-----------------+
* | SNMP_RESET | waiting to transmit response to malformed packet
* +-----------------+
* |
* | response was send, reseting the session (with socket)
* |
* \--> SNMP_LOCKED
*
* *
* Erroneous transitions: * Erroneous transitions:
* SNMP is UP in states SNMP_CONN and also in SNMP_REGISTER because the * SNMP is UP (PS_UP) in states SNMP_CONN and also in SNMP_REGISTER because
* session is establised and the GetNext request should be responsed * the session is establised and the GetNext request should be responsed
* without regard to MIB registration. * without regards to MIB registration.
*
* When the session has been closed for some reason (socket error, receipt of
* Close-PDU) SNMP cleans the session information and message queue and goes
* back to the SNMP_LOCKED state.
* *
* Reconfiguration is done in similar fashion to BGP, the reconfiguration * Reconfiguration is done in similar fashion to BGP, the reconfiguration
* request is declined, the protocols is stoped and started with new * request is declined, the protocols is stoped and started with new
@ -122,9 +111,6 @@
#include "mib_tree.h" #include "mib_tree.h"
#include "bgp4_mib.h" #include "bgp4_mib.h"
// TODO: remove me
#include "proto/bgp/bgp.h"
const char agentx_master_addr[] = AGENTX_MASTER_ADDR; const char agentx_master_addr[] = AGENTX_MASTER_ADDR;
const struct oid *agentx_available_mibs[AGENTX_MIB_COUNT + 1] = { 0 }; const struct oid *agentx_available_mibs[AGENTX_MIB_COUNT + 1] = { 0 };
@ -133,6 +119,16 @@ static void snmp_sock_err(sock *sk, int err);
static void snmp_stop_timeout(timer *tm); static void snmp_stop_timeout(timer *tm);
static void snmp_cleanup(struct snmp_proto *p); static void snmp_cleanup(struct snmp_proto *p);
static const char *snmp_state_str[] = {
[SNMP_INIT] = "acquiring address lock",
[SNMP_LOCKED] = "address lock acquired",
[SNMP_OPEN] = "starting AgentX subagent",
[SNMP_REGISTER] = "registering MIBs",
[SNMP_CONN] = "AgentX session established",
[SNMP_STOP] = "stopping AgentX subagent",
[SNMP_DOWN] = "protocol down",
};
/* /*
* agentx_get_mib_init - init function for agentx_get_mib() * agentx_get_mib_init - init function for agentx_get_mib()
* @p: SNMP instance protocol pool * @p: SNMP instance protocol pool
@ -154,6 +150,7 @@ void agentx_get_mib_init(pool *p)
/* /*
* agentx_get_mib - classify an OID based on MIB prefix * agentx_get_mib - classify an OID based on MIB prefix
* @o: Object Identifier to classify
*/ */
enum agentx_mibs agentx_get_mib(const struct oid *o) enum agentx_mibs agentx_get_mib(const struct oid *o)
{ {
@ -185,29 +182,28 @@ snmp_rx_skip(sock UNUSED *sk, uint UNUSED size)
} }
/* /*
* snmp_tx_skip - handle empty TX-buffer during session reset * snmp_tx_skip - handle empty TX buffer during session reset
* @sk: communication socket * @sk: communication socket
* *
* The socket tx_hook is called when the TX-buffer is empty, i.e. all data was * The socket tx_hook is called when the TX buffer is empty, i.e. all data was
* send. This function is used only when we found malformed PDU and we are * send. This function is used only when we found malformed PDU and we are
* resetting the established session. If called, we are reseting the session. * resetting the established session. If called, we perform a SNMP protocol
* state change.
*/ */
static void static void
snmp_tx_skip(sock *sk) snmp_tx_skip(sock *sk)
{ {
struct snmp_proto *p = sk->data; struct snmp_proto *p = sk->data;
proto_notify_state(&p->p, snmp_set_state(p, SNMP_DOWN)); proto_notify_state(&p->p, snmp_set_state(p, SNMP_STOP));
} }
/* /*
* snmp_set_state - change state with associated actions * snmp_set_state - change state with associated actions
* @p - SNMP protocol instance * @p: SNMP protocol instance
* @state - new SNMP protocol state * @state: new SNMP protocol state
* *
* This function does not notify the bird about protocol state. It is therefore * This function does not notify the bird about protocol state. Return current
* a responsibility of the caller to use the returned value appropriately. * protocol state (PS_UP, ...).
*
* Return current protocol state.
*/ */
int int
snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state) snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
@ -215,14 +211,12 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
enum snmp_proto_state last = p->state; enum snmp_proto_state last = p->state;
const struct snmp_config *cf = (struct snmp_config *) p->p.cf; const struct snmp_config *cf = (struct snmp_config *) p->p.cf;
TRACE(D_EVENTS, "SNMP changing state to %u", state);
p->state = state; p->state = state;
switch (state) switch (state)
{ {
case SNMP_INIT: case SNMP_INIT:
DBG("snmp -> SNMP_INIT\n"); TRACE(D_EVENTS, "TODO");
ASSERT(last == SNMP_DOWN); ASSERT(last == SNMP_DOWN);
if (cf->trans_type == SNMP_TRANS_TCP) if (cf->trans_type == SNMP_TRANS_TCP)
@ -230,11 +224,6 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
/* We need to lock the IP address */ /* We need to lock the IP address */
struct object_lock *lock; struct object_lock *lock;
lock = p->lock = olock_new(p->pool); lock = p->lock = olock_new(p->pool);
/*
* lock->iface
* lock->vrf
*/
lock->addr = p->remote_ip; lock->addr = p->remote_ip;
lock->port = p->remote_port; lock->port = p->remote_port;
lock->type = OBJLOCK_TCP; lock->type = OBJLOCK_TCP;
@ -244,18 +233,19 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
return PS_START; return PS_START;
} }
last = SNMP_INIT;
p->state = state = SNMP_LOCKED; p->state = state = SNMP_LOCKED;
/* Fall thru */ /* Fall thru */
case SNMP_LOCKED: case SNMP_LOCKED:
DBG("snmp -> SNMP_LOCKED\n"); TRACE(D_EVENTS, "snmp %s: address lock acquired", p->p.name);
ASSERT(last == SNMP_INIT || SNMP_RESET); ASSERT(last == SNMP_INIT);
sock *s = sk_new(p->pool); sock *s = sk_new(p->pool);
if (cf->trans_type == SNMP_TRANS_TCP) if (cf->trans_type == SNMP_TRANS_TCP)
{ {
s->type = SK_TCP_ACTIVE; s->type = SK_TCP_ACTIVE;
s->saddr = ipa_from_ip4(p->local_ip); //s->saddr = ipa_from_ip4(p->local_ip);
s->daddr = p->remote_ip; s->daddr = p->remote_ip;
s->dport = p->remote_port; s->dport = p->remote_port;
s->rbsize = SNMP_RX_BUFFER_SIZE; s->rbsize = SNMP_RX_BUFFER_SIZE;
@ -279,65 +269,69 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
/* Try opening the socket, schedule a retry on fail */ /* Try opening the socket, schedule a retry on fail */
if (sk_open(s) < 0) if (sk_open(s) < 0)
{ {
TRACE(D_EVENTS, "opening of communication socket failed");
rfree(s); rfree(s);
p->sock = NULL; p->sock = NULL;
// TODO handle 0 timeout
tm_start(p->startup_timer, p->timeout); tm_start(p->startup_timer, p->timeout);
} }
return PS_START; return PS_START;
case SNMP_OPEN: case SNMP_OPEN:
DBG("snmp -> SNMP_OPEN\n"); TRACE(D_EVENTS, "communication socket opened, starting AgentX subagent");
ASSERT(last == SNMP_LOCKED); ASSERT(last == SNMP_LOCKED);
p->sock->rx_hook = snmp_rx; p->sock->rx_hook = snmp_rx;
p->sock->tx_hook = NULL; p->sock->tx_hook = NULL;
snmp_start_subagent(p); snmp_start_subagent(p);
p->startup_timer->hook = snmp_stop_timeout; p->startup_timer->hook = snmp_stop_timeout;
tm_start(p->startup_timer, 1 S); tm_start(p->startup_timer, 1 S);
return PS_START; return PS_START;
case SNMP_REGISTER: case SNMP_REGISTER:
DBG("snmp -> SNMP_REGISTER\n"); TRACE(D_EVENTS, "registering MIBs");
ASSERT(last == SNMP_OPEN); ASSERT(last == SNMP_OPEN);
tm_stop(p->startup_timer); /* stop timeout */ tm_stop(p->startup_timer); /* stop timeout */
p->sock->rx_hook = snmp_rx;
p->sock->tx_hook = snmp_tx;
snmp_register_mibs(p); snmp_register_mibs(p);
return PS_START; return PS_START;
case SNMP_CONN: case SNMP_CONN:
DBG("snmp -> SNMP_CONN\n"); TRACE(D_EVENTS, "MIBs registered");
ASSERT(last == SNMP_REGISTER); ASSERT(last == SNMP_REGISTER);
return PS_UP; return PS_UP;
case SNMP_STOP: case SNMP_STOP:
DBG("snmp -> SNMP_STOP\n"); if (p->sock && p->state != SNMP_OPEN)
ASSUME(last == SNMP_REGISTER || last == SNMP_CONN); {
TRACE(D_EVENTS, "closing AgentX session");
if (p->state == SNMP_OPEN || p->state == SNMP_REGISTER ||
p->state == SNMP_CONN)
snmp_stop_subagent(p); snmp_stop_subagent(p);
// FIXME: special treatment for SNMP_OPEN last state?
p->sock->rx_hook = snmp_rx_skip; p->sock->rx_hook = snmp_rx_skip;
p->sock->tx_hook = snmp_tx_skip; p->sock->tx_hook = snmp_tx_skip;
p->startup_timer->hook = snmp_stop_timeout; p->startup_timer->hook = snmp_stop_timeout;
tm_start(p->startup_timer, p->timeout); tm_start(p->startup_timer, 150 MS);
return PS_STOP; return PS_STOP;
}
p->state = state = SNMP_DOWN;
/* Fall thru */
case SNMP_DOWN: case SNMP_DOWN:
DBG("snmp -> SNMP_DOWN\n"); TRACE(D_EVENTS, "AgentX session closed");
ASSERT(last == SNMP_STOP || last == SNMP_RESET);
snmp_cleanup(p); snmp_cleanup(p);
// FIXME: handle the state in which we call proto_notify_state and
// immediately return PS_DOWN from snmp_shutdown()
return PS_DOWN; return PS_DOWN;
case SNMP_RESET:
// TODO remove SNMP_RESET state
DBG("snmp -> SNMP_RESET\n");
ASSUME(last == SNMP_REGISTER || last == SNMP_CONN);
ASSUME(p->sock);
snmp_stop_subagent(p);
// FIXME: special treatment for SNMP_OPEN last state?
p->sock->rx_hook = snmp_rx_skip;
p->sock->tx_hook = snmp_tx_skip;
return PS_STOP;
default: default:
die("unknown snmp state transition"); die("unknown snmp state transition");
return PS_DOWN; return PS_DOWN;
@ -346,7 +340,7 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state)
/* /*
* snmp_init - preinitialize SNMP instance * snmp_init - preinitialize SNMP instance
* @CF - SNMP configuration generic handle * @CF: SNMP configuration generic handle
* *
* Returns a generic handle pointing to preinitialized SNMP procotol * Returns a generic handle pointing to preinitialized SNMP procotol
* instance. * instance.
@ -358,7 +352,6 @@ snmp_init(struct proto_config *CF)
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P); struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS; p->rl_gen = (struct tbf) TBF_DEFAULT_LOG_LIMITS;
p->state = SNMP_DOWN; p->state = SNMP_DOWN;
return P; return P;
@ -366,12 +359,10 @@ snmp_init(struct proto_config *CF)
/* /*
* snmp_cleanup - free all resources allocated by SNMP protocol * snmp_cleanup - free all resources allocated by SNMP protocol
* @p - SNMP protocol instance * @p: SNMP protocol instance
* *
* This function forcefully stops and cleans all resources and memory acqiured * This function forcefully stops and cleans all resources and memory acqiured
* by given SNMP protocol instance, such as timers, lists, hash tables etc. * by given SNMP protocol instance, such as timers, lists, hash tables etc.
* Function snmp_cleanup() does not change the protocol state to PS_DOWN for
* practical reasons, it should be done by the caller.
*/ */
static inline void static inline void
snmp_cleanup(struct snmp_proto *p) snmp_cleanup(struct snmp_proto *p)
@ -407,7 +398,7 @@ snmp_cleanup(struct snmp_proto *p)
/* /*
* snmp_connected - start AgentX session on created socket * snmp_connected - start AgentX session on created socket
* @sk - socket owned by SNMP protocol instance * @sk: socket owned by SNMP protocol instance
* *
* Starts the AgentX communication by sending an agentx-Open-PDU. * Starts the AgentX communication by sending an agentx-Open-PDU.
* This function is internal and shouldn't be used outside the SNMP module. * This function is internal and shouldn't be used outside the SNMP module.
@ -426,47 +417,35 @@ snmp_connected(sock *sk)
* We wait until the last PDU written into the socket is send while ignoring all * We wait until the last PDU written into the socket is send while ignoring all
* incomming PDUs. Then we hard reset the connection by socket closure. The * incomming PDUs. Then we hard reset the connection by socket closure. The
* protocol instance is automatically restarted by nest. * protocol instance is automatically restarted by nest.
*
* Return protocol state (PS_STOP, ...).
*/ */
void int
snmp_reset(struct snmp_proto *p) snmp_reset(struct snmp_proto *p)
{ {
proto_notify_state(&p->p, snmp_set_state(p, SNMP_RESET)); int proto_state = snmp_set_state(p, SNMP_STOP);
} proto_notify_state(&p->p, proto_state);
return proto_state;
/*
* snmp_stop - close AgentX session
* @p: SNMP protocol instance
*
* We write agentx-Close-PDU into the socket, wait until all written PDUs are
* send and then close the socket. The protocol instance is automatically
* restarted by nest.
*/
void
snmp_stop(struct snmp_proto *p)
{
// TODO: add option for passing close reason for agentx-Close-PDU
proto_notify_state(&p->p, snmp_set_state(p, SNMP_STOP));
} }
/* /*
* snmp_sock_err - handle errors on socket by reopenning the socket * snmp_sock_err - handle errors on socket by reopenning the socket
* @sk - socket owned by SNMP protocol instance * @sk: socket owned by SNMP protocol instance
* @err - socket error errno * @err: socket error code
*/ */
static void static void
snmp_sock_err(sock *sk, int UNUSED err) snmp_sock_err(sock *sk, int UNUSED err)
{ {
struct snmp_proto *p = sk->data; struct snmp_proto *p = sk->data;
if (err != 0)
TRACE(D_EVENTS, "SNMP socket error %d", err); TRACE(D_EVENTS, "SNMP socket error (%d)", err);
snmp_reset(p); snmp_set_state(p, SNMP_DOWN);
} }
/* /*
* snmp_start_locked - open the socket on locked address * snmp_start_locked - open the socket on locked address
* @lock - object lock guarding the communication mean (address, ...) * @lock: object lock guarding the communication mean (address, ...)
* *
* This function is called when the object lock is acquired. Main goal is to set * This function is called when the object lock is acquired. Main goal is to set
* socket parameters and try to open configured socket. Function * socket parameters and try to open configured socket. Function
@ -487,29 +466,14 @@ snmp_start_locked(struct object_lock *lock)
snmp_set_state(p, SNMP_LOCKED); snmp_set_state(p, SNMP_LOCKED);
} }
/*
* snmp_reconnect - helper restarting the AgentX session on packet errors
* @tm - the startup_timer holding the SNMP protocol instance
*
* Try to recover from an error by reseting the SNMP protocol. It is a simple
* snmp_reset() wrapper for timers.
*/
void
snmp_reconnect(timer *tm)
{
struct snmp_proto *p = tm->data;
snmp_reset(p);
return;
}
/* /*
* snmp_startup_timeout - start the initiliazed SNMP protocol * snmp_startup_timeout - start the initiliazed SNMP protocol
* @tm - the startup_timer holding the SNMP protocol instance. * @tm: the startup_timer holding the SNMP protocol instance.
* *
* When the timer rings, the function snmp_startup() is invoked. * When the timer rings, the function snmp_startup() is invoked.
* This function is internal and shouldn't be used outside the SNMP module. * This function is internal and shouldn't be used outside the SNMP module.
* Used when we delaying the start procedure, or we want to resend * Used when we delaying the start procedure, or we want to retry opening
* an agentx-Open-PDU for non-responding master agent. * the communication socket.
*/ */
void void
snmp_startup_timeout(timer *tm) snmp_startup_timeout(timer *tm)
@ -519,13 +483,13 @@ snmp_startup_timeout(timer *tm)
} }
/* /*
* snmp_stop_timeout - a timeout for nonresponding master agent * snmp_stop_timeout - a timeout for non-responding master agent
* @tm - the startup_timer holding the SNMP protocol instance. * @tm: the startup_timer holding the SNMP protocol instance.
* *
* We are shutting down the SNMP protocol instance and we sent the * We are trying to empty the TX buffer of communication socket. But if it is
* agentx-Close-PDU. This function forcefully closes the AgentX session and * not done in reasonable amount of time, the function is called by timeout
* stops the SNMP protocol instance. Used only when we did not receive any * timer. We down the whole SNMP protocol with cleanup of associated data
* agentx-Response-PDU for the sent closed packet (before timeout). * structures.
*/ */
static void static void
snmp_stop_timeout(timer *tm) snmp_stop_timeout(timer *tm)
@ -536,7 +500,7 @@ snmp_stop_timeout(timer *tm)
/* /*
* snmp_ping_timeout - send a agentx-Ping-PDU * snmp_ping_timeout - send a agentx-Ping-PDU
* @tm - the ping_timer holding the SNMP protocol instance. * @tm: the ping_timer holding the SNMP protocol instance.
* *
* Send an agentx-Ping-PDU. This function is periodically called by ping * Send an agentx-Ping-PDU. This function is periodically called by ping
* timer. * timer.
@ -550,11 +514,11 @@ snmp_ping_timeout(timer *tm)
/* /*
* snmp_start - Initialize the SNMP protocol instance * snmp_start - Initialize the SNMP protocol instance
* @P - SNMP protocol generic handle * @P: SNMP protocol generic handle
* *
* The first step in AgentX subagent startup is protocol initialition. * The first step in AgentX subagent startup is protocol initialition.
* We must prepare lists, find BGP peers and finally asynchronously open * We must prepare lists, find BGP peers and finally asynchronously start
* a AgentX subagent session through snmp_startup() function call. * a AgentX subagent session.
*/ */
static int static int
snmp_start(struct proto *P) snmp_start(struct proto *P)
@ -605,7 +569,7 @@ snmp_reconfigure_logic(struct snmp_proto *p, const struct snmp_config *new)
{ {
WALK_LIST(b2, old->bgp_entries) WALK_LIST(b2, old->bgp_entries)
{ {
if (!strcmp(b1->config->name, b2->config->name)) if (!bstrcmp(b1->config->name, b2->config->name))
goto skip; goto skip;
} }
@ -617,10 +581,29 @@ skip:
if (bonds != 0) if (bonds != 0)
return 0; return 0;
if (old->trans_type != new->trans_type
|| ip4_compare(old->local_ip, new->local_ip)
|| old->local_port != new->local_port
|| ipa_compare(old->remote_ip, new->remote_ip)
|| !bstrcmp(old->remote_path, new->remote_path)
|| old->remote_port != new->remote_port
// TODO can be changed on the fly
|| !ip4_compare(old->bgp_local_id, new->bgp_local_id)
|| old->bgp_local_as != new->bgp_local_as // TODO can be changed on the fly
|| old->timeout != new->timeout
//|| old->startup_delay != new->startup_delay
|| old->priority != new->priority
|| !strncmp(old->description, new->description, UINT32_MAX))
return 0;
return 1;
/*
return !memcmp(((byte *) old) + sizeof(struct proto_config), return !memcmp(((byte *) old) + sizeof(struct proto_config),
((byte *) new) + sizeof(struct proto_config), ((byte *) new) + sizeof(struct proto_config),
OFFSETOF(struct snmp_config, description) - sizeof(struct proto_config)) OFFSETOF(struct snmp_config, description) - sizeof(struct proto_config))
&& ! strncmp(old->description, new->description, UINT32_MAX); && ! strncmp(old->description, new->description, UINT32_MAX);
*/
} }
/* /*
@ -638,6 +621,8 @@ snmp_reconfigure(struct proto *P, struct proto_config *CF)
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P); struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
const struct snmp_config *new = SKIP_BACK(struct snmp_config, cf, CF); const struct snmp_config *new = SKIP_BACK(struct snmp_config, cf, CF);
// TODO do not reject reconfiguration when only BGP peer list changed
/* We are searching for configuration changes */ /* We are searching for configuration changes */
int config_changed = snmp_reconfigure_logic(p, new); int config_changed = snmp_reconfigure_logic(p, new);
@ -660,7 +645,7 @@ snmp_show_proto_info(struct proto *P)
{ {
struct snmp_proto *p = (void *) P; struct snmp_proto *p = (void *) P;
cli_msg(-1006, " SNMP state %u", p->state); cli_msg(-1006, " SNMP state: %s", snmp_state_str[p->state]);
cli_msg(-1006, " MIBs"); cli_msg(-1006, " MIBs");
snmp_bgp4_show_info(p); snmp_bgp4_show_info(p);
@ -682,19 +667,16 @@ snmp_postconfig(struct proto_config *CF)
/* /*
* snmp_shutdown - Forcefully stop the SNMP protocol instance * snmp_shutdown - Forcefully stop the SNMP protocol instance
* @P - SNMP protocol generic handle * @P: SNMP protocol generic handle
* *
* If we have established connection, we firstly stop the subagent and then * Simple cast-like wrapper around snmp_reset(), see more info there.
* later cleanup the protocol. The subagent stopping consist of sending the
* agentx-Close-PDU and changing the current protocol state to PS_STOP.
* If we have no connection created, we simple do the cleanup.
* The cleanup is transition straight to PS_DOWN state with snmp_cleanup() call.
*/ */
static int static int
snmp_shutdown(struct proto *P) snmp_shutdown(struct proto *P)
{ {
struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P); struct snmp_proto *p = SKIP_BACK(struct snmp_proto, p, P);
return snmp_set_state(p, SNMP_DOWN); return snmp_set_state(p, SNMP_DOWN);
return snmp_reset(p);
} }

View File

@ -10,12 +10,12 @@
#ifndef _BIRD_SNMP_H_ #ifndef _BIRD_SNMP_H_
#define _BIRD_SNMP_H_ #define _BIRD_SNMP_H_
#include "lib/ip.h"
#include "lib/socket.h"
#include "lib/resource.h"
#include "lib/timer.h"
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "lib/resource.h"
#include "lib/ip.h"
#include "lib/socket.h"
#include "lib/timer.h"
#include "filter/data.h" #include "filter/data.h"
#define SNMP_UNDEFINED 0 #define SNMP_UNDEFINED 0
@ -39,7 +39,6 @@ enum snmp_proto_state {
SNMP_REGISTER, SNMP_REGISTER,
SNMP_CONN, SNMP_CONN,
SNMP_STOP, SNMP_STOP,
SNMP_RESET,
}; };
struct snmp_bond { struct snmp_bond {
@ -69,7 +68,6 @@ struct snmp_config {
btime timeout; btime timeout;
btime startup_delay; btime startup_delay;
u8 priority; u8 priority;
//struct iface *iface; TODO
u32 bonds; u32 bonds;
const char *description; /* The order of fields is not arbitrary */ const char *description; /* The order of fields is not arbitrary */
list bgp_entries; /* We want dynamically allocated fields to be list bgp_entries; /* We want dynamically allocated fields to be
@ -170,9 +168,16 @@ void snmp_startup_timeout(timer *tm);
void snmp_reconnect(timer *tm); void snmp_reconnect(timer *tm);
int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state); int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state);
void snmp_reset(struct snmp_proto *p); int snmp_reset(struct snmp_proto *p);
void snmp_stop(struct snmp_proto *p);
extern const char agentx_master_addr[sizeof(AGENTX_MASTER_ADDR)]; extern const char agentx_master_addr[sizeof(AGENTX_MASTER_ADDR)];
static inline int
proto_is_snmp(const struct proto *P)
{
extern struct protocol proto_snmp;
return P->proto == &proto_snmp;
}
#endif #endif

View File

@ -66,10 +66,7 @@ snmp_varbind_set_name_len(struct snmp_pdu *c, struct agentx_varbind **vb, u8 len
uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32); uint diff_size = (len - LOAD_U8(oid->n_subid)) * sizeof(u32);
if (snmp_tbuf_reserve(c, diff_size)) if (snmp_tbuf_reserve(c, diff_size))
{
snmp_log("varbind_set_name_len small buffer");
oid = &(*vb)->name; oid = &(*vb)->name;
}
ASSERT(c->size >= diff_size); ASSERT(c->size >= diff_size);
c->size -= diff_size; c->size -= diff_size;
@ -82,8 +79,7 @@ snmp_varbind_duplicate_hdr(struct snmp_pdu *c, struct agentx_varbind **vb)
{ {
ASSUME(vb != NULL && *vb != NULL); ASSUME(vb != NULL && *vb != NULL);
uint hdr_size = snmp_varbind_header_size(*vb); uint hdr_size = snmp_varbind_header_size(*vb);
if (snmp_tbuf_reserve(c, hdr_size)) (void) snmp_tbuf_reserve(c, hdr_size);
snmp_log("varbind_duplicate small buffer");
ASSERT(c->size >= hdr_size); ASSERT(c->size >= hdr_size);
byte *buffer = c->buffer; byte *buffer = c->buffer;
@ -175,6 +171,23 @@ snmp_oid_copy2(struct oid *dest, const struct oid *src)
memcpy(dest->ids, src->ids, LOAD_U8(src->n_subid) * sizeof(u32)); memcpy(dest->ids, src->ids, LOAD_U8(src->n_subid) * sizeof(u32));
} }
/*
* snmp_oid_from_buf - copy OID from RX buffer to dest in native byte order
* @dst: destination to use
* @src: OID to be copied from
*/
void
snmp_oid_from_buf(struct oid *dst, const struct oid *src)
{
dst->n_subid = LOAD_U8(src->n_subid);
dst->prefix = LOAD_U8(src->prefix);
dst->include = LOAD_U8(src->include) ? 1 : 0;
dst->reserved = 0;
for (uint i = 0; i < dst->n_subid; i++)
dst->ids[i] = LOAD_U32(src->ids[i]);
}
/* /*
* snmp_oid_duplicate - duplicate an OID from memory pool * snmp_oid_duplicate - duplicate an OID from memory pool
* @pool: pool to use * @pool: pool to use
@ -256,7 +269,7 @@ snmp_varbind_hdr_size_from_oid(const struct oid *oid)
/* /*
* snmp_set_varbind_type - set VarBind's type field * snmp_set_varbind_type - set VarBind's type field
* @vb: Varbind inside TX-buffer * @vb: Varbind inside TX buffer
* @t: a valid type to be set * @t: a valid type to be set
* *
* This function assumes valid @t. * This function assumes valid @t.
@ -304,10 +317,10 @@ snmp_load_varbind_type(const struct agentx_varbind *vb)
/* /*
* snmp_get_varbind_type - loads a VarBind type * snmp_get_varbind_type - loads a VarBind type
* @vb: VarBind pointer to TX-buffer * @vb: VarBind pointer to TX buffer
* *
* This function assumes VarBind with valid type, always call snmp_test_varbind * This function assumes VarBind with valid type, always call snmp_test_varbind
* for in TX-buffer VarBinds! * for in TX buffer VarBinds.
*/ */
inline enum agentx_type inline enum agentx_type
snmp_get_varbind_type(const struct agentx_varbind *vb) snmp_get_varbind_type(const struct agentx_varbind *vb)
@ -742,7 +755,6 @@ snmp_registration_create(struct snmp_proto *p, enum agentx_mibs mib)
r->packet_id = p->packet_id + 1; r->packet_id = p->packet_id + 1;
r->mib = mib; r->mib = mib;
snmp_log("using registration packet_id %u", r->packet_id);
add_tail(&p->registration_queue, &r->n); add_tail(&p->registration_queue, &r->n);
return r; return r;
@ -751,7 +763,6 @@ snmp_registration_create(struct snmp_proto *p, enum agentx_mibs mib)
int int
snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, enum agentx_mibs mib) snmp_registration_match(struct snmp_registration *r, struct agentx_header *h, enum agentx_mibs mib)
{ {
snmp_log("snmp_reg_same() r->packet_id %u p->packet_id %u", r->packet_id, h->packet_id);
return return
(r->mib == mib) && (r->mib == mib) &&
(r->session_id == h->session_id) && (r->session_id == h->session_id) &&
@ -864,7 +875,7 @@ snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
* @len: length of the string @str * @len: length of the string @str
* *
* Beware: this function assumes there is enough space in the underlaying * Beware: this function assumes there is enough space in the underlaying
* TX-buffer. The caller has to provide that, see snmp_str_size_from_len() for * TX buffer. The caller has to provide that, see snmp_str_size_from_len() for
* more info. * more info.
*/ */
void void
@ -951,7 +962,7 @@ snmp_oid_log(const struct oid *oid)
for (int id = 0; id < oid->n_subid; id++) for (int id = 0; id < oid->n_subid; id++)
pos += snprintf(pos, buf + 1024 - pos, ".%u", oid->ids[id]); pos += snprintf(pos, buf + 1024 - pos, ".%u", oid->ids[id]);
snmp_log("%s", buf); log(L_WARN, "%s", buf);
} }
@ -1096,10 +1107,7 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p
int old = snmp_oid_size(&c->sr_vb_start->name); int old = snmp_oid_size(&c->sr_vb_start->name);
if (mib_tree_walk_to_oid(walk, if (mib_tree_walk_to_oid(walk,
&c->sr_vb_start->name, 20 * sizeof(u32))) &c->sr_vb_start->name, 20 * sizeof(u32)))
{
snmp_log("walk_next copy failed");
return NULL; return NULL;
}
int new = snmp_oid_size(&c->sr_vb_start->name); int new = snmp_oid_size(&c->sr_vb_start->name);
c->buffer += (new - old); c->buffer += (new - old);
@ -1122,10 +1130,7 @@ snmp_walk_next(struct mib_tree *tree, struct mib_walk_state *walk, struct snmp_p
int old = snmp_oid_size(&c->sr_vb_start->name); int old = snmp_oid_size(&c->sr_vb_start->name);
// TODO autogrow // TODO autogrow
if (mib_tree_walk_to_oid(walk, &c->sr_vb_start->name, 20 * sizeof(u32))) if (mib_tree_walk_to_oid(walk, &c->sr_vb_start->name, 20 * sizeof(u32)))
{
snmp_log("walk_next copy failed");
return NULL; return NULL;
}
int new = snmp_oid_size(&c->sr_vb_start->name); int new = snmp_oid_size(&c->sr_vb_start->name);
c->buffer += (new - old); c->buffer += (new - old);
@ -1172,10 +1177,7 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_p
size = leaf->size; size = leaf->size;
} }
snmp_log("walk_fill got size %u based on lt %u ls %u, calling filler()", size, leaf->type, leaf->size); (void) snmp_tbuf_reserve(c, size);
if (snmp_tbuf_reserve(c, size))
snmp_log("walk_fill small buffer size");
enum snmp_search_res res = leaf->filler(walk, c); enum snmp_search_res res = leaf->filler(walk, c);

View File

@ -15,38 +15,19 @@
#include "bgp4_mib.h" #include "bgp4_mib.h"
/* /*
* Goals:
* In current situation, we do not handle the dynamic BGP case.
*/
/**
*
* Handling of malformed packet: * Handling of malformed packet:
* *
* When we find an error in PDU data, we create and send a response with error * When we find an error in PDU data, we create and send a response with error
* defined by the RFC. We await until the packet is send and then we close the * defined by the RFC. We await until the packet is send and then we close the
* communication socket. This implicitly closes the established session. We * communication socket ignoring any possible response. This implicitly closes
* chose this approach because we cannot easily mark the boundary between packets. * the established session. We chose this approach because we cannot easily
* When we are reseting the connection, we change the snmp_state to SNMP_RESET. * mark the boundary between packets.
* In SNMP_RESET state we skip all received bytes and wait for snmp_tx_skip()
* to be called. The socket's tx_hook is called when the TX-buffer is empty,
* meaning our response (agentx-Response-PDU) was send.
* *
* *
* Partial parsing: * Partial parsing:
* *
* It may happen that we received only staring part of some PDU from the * It may happen that we received only staring part of some PDU from the
* communication socket. In most cases, if we recognize this situation we * communication socket. In most cases, if we recognize this situation, we
* immediately return, waiting for rest of the PDU to arrive. But for packets
* like agentx-Get-PDU, agentx-GetNext-PDU and agentx-GetBulk-PDU it could be
* costly as they could hold many VarBinds. We don't want to process these
* packet twice because it is a lot work. We parse all VarBinds until we hit the
* first incomplete one. The logic behind this is to release as much as
* possible space from receive buffer. When we hit the first incomplete VarBind,
* we store information about the parsing state and move the header inside the
* receive buffer.
*
* Transmit packet context
* *
*/ */
@ -61,13 +42,13 @@ static uint update_packet_size(struct agentx_header *start, byte *end);
const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET }; const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
/* /*
* snmp_header - store packet information into buffer * snmp_header - store packet header into buffer
* @h: pointer to created packet header in TX-buffer * @h: pointer to created packet header in TX buffer
* @type: created PDU type * @type: created PDU type
* @flags: set flags * @flags: set flags
* *
* Payload length is set to zero legth. Padding is also zeroed. Real stored * Payload length is set to zero legth. Padding is also zeroed. Real stored
* flags are dependent on compile-time message byte-order configuration. * flags depend on compile-time message byte order configuration.
*/ */
static inline void static inline void
snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags) snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
@ -81,7 +62,7 @@ snmp_header(struct agentx_header *h, enum agentx_pdu_types type, u8 flags)
/* /*
* snmp_blank_header - create header with no flags except byte order * snmp_blank_header - create header with no flags except byte order
* @h: pointer to created header in TX-buffer * @h: pointer to created header in TX buffer
* @type: create PDU type * @type: create PDU type
* *
* Only flag possibly set may be packet byte order configuration. * Only flag possibly set may be packet byte order configuration.
@ -96,7 +77,7 @@ snmp_blank_header(struct agentx_header *h, enum agentx_pdu_types type)
* snmp_register_ack - handle registration response * snmp_register_ack - handle registration response
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @res: header of agentx-Response-PDU * @res: header of agentx-Response-PDU
* @mib: MIB subtree identifier * @oid: MIB subtree Object Identifier
*/ */
void void
snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid) snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struct oid *oid)
@ -129,8 +110,8 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, const struc
* @error: response PDU error fields value * @error: response PDU error fields value
* @index: response PDU error index field value * @index: response PDU error index field value
* *
* This function assumes that the buffer has enough space to fill in the AgentX * This function assumes that the buffer has enough space to fill
* Response PDU. So it is the responsibility of the caller to provide that. * in the agentx-Response-PDU.
*/ */
static void static void
snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16 index) snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16 index)
@ -151,8 +132,8 @@ snmp_simple_response(struct snmp_proto *p, enum agentx_response_errs error, u16
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @oid: PDU OID description field value * @oid: PDU OID description field value
* *
* Other fields are filled based on @p configuration (timeout, subagent string * Other fields are filled based on @p configuration (timeout, subagent
* description) * description).
*/ */
static void static void
open_pdu(struct snmp_proto *p, struct oid *oid) open_pdu(struct snmp_proto *p, struct oid *oid)
@ -165,11 +146,11 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
#define TIMEOUT_SIZE sizeof(u32) /* 1B timeout, 3B zero padding */ #define TIMEOUT_SIZE sizeof(u32) /* 1B timeout, 3B zero padding */
/* Make sure that we have enough space in TX-buffer */ /* Make sure that we have enough space in TX buffer */
uint s = AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) + uint s = AGENTX_HEADER_SIZE + TIMEOUT_SIZE + snmp_oid_size(oid) +
snmp_str_size(cf->description); snmp_str_size(cf->description);
if (snmp_tbuf_reserve(&c, s))
snmp_log("agentx-Open-PDU small buffer"); (void) snmp_tbuf_reserve(&c, s);
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -204,12 +185,15 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @oid: PDU notification Varbind name (OID) * @oid: PDU notification Varbind name (OID)
* @data: PDU Varbind payload * @data: PDU Varbind payload
* @size - PDU Varbind payload size * @size: PDU Varbind payload size
* @include_uptime: flag enabling inclusion of sysUpTime.0 OID * @include_uptime: flag enabling inclusion of sysUpTime.0 OID
*/ */
void void
snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime) snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime)
{ {
if (!snmp_is_active(p))
return;
sock *sk = p->sock; sock *sk = p->sock;
struct snmp_pdu c; struct snmp_pdu c;
@ -224,9 +208,8 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
if (include_uptime) if (include_uptime)
sz += UPTIME_SIZE; sz += UPTIME_SIZE;
/* Make sure that we have enough space in TX-buffer */ /* Make sure that we have enough space in TX buffer */
if (snmp_tbuf_reserve(&c, sz)) (void) snmp_tbuf_reserve(&c, sz);
snmp_log("agentx-Notify-PDU small buffer");
struct agentx_header *h = (struct agentx_header *) c.buffer; struct agentx_header *h = (struct agentx_header *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -292,24 +275,23 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
* @index: OIDs registration n_subid index * @index: OIDs registration n_subid index
* @type: register/unregister PDU type * @type: register/unregister PDU type
* @is_instance: flag enabling instance registration (used only for register) * @is_instance: flag enabling instance registration (used only for register)
* @contid: context ID to register in (currently unsupported)
* *
* Both register and unregister PDUs are capable of specifing a number of OIDs * Both register and unregister PDUs are capable of specifing a number of OIDs
* by using pair of index and upper bound. The index (r.range_subid) points into * by using a pair of index and upper bound. The index (r.range_subid) points into
* the OID's n_subid array to ID being threated as variable. The upper bound * the OID's n_subid array to ID being threated as variable. The upper bound
* (r.upper_bound) determins maximal value for n_subid selected by index. * (r.upper_bound) determins maximal value for n_subid selected by the index.
* The index and upper bound are passed as @index, and @bound respectively. * The index and the upper bound are passed as @index, and @bound respectively.
* *
* Zero value for @is_instance means we want to register/unregister OID as a MIB * Zero value for @is_instance means we want to register/unregister OID as a MIB
* subtree, for nonzero value we are registering MIB tree an instance (leaf). * subtree, for nonzero value we are registering MIB tree an instance (leaf).
* Full name of PDUs are agentx-Register-PDU and agentx-Unregister-PDU.
* *
* This function in internal and shoulnd't be used outside the SNMP module, * This function in internal and shoulnd't be used outside the SNMP module,
* see snmp_register() and snmp_unregister() functions. * see snmp_register() and snmp_unregister() functions.
*/ */
static void static void
un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, enum agentx_pdu_types type, u8 is_instance, uint UNUSED contid) un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, enum agentx_pdu_types type, u8 is_instance)
{ {
/* used for agentx-Register-PDU and agentx-Unregister-PDU */
const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf); const struct snmp_config *cf = SKIP_BACK(struct snmp_config, cf, p->p.cf);
sock *sk = p->sock; sock *sk = p->sock;
struct snmp_pdu c; struct snmp_pdu c;
@ -320,8 +302,7 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) + uint sz = AGENTX_HEADER_SIZE + snmp_oid_size(oid) +
((bound > 1) ? BOUND_SIZE : 0); ((bound > 1) ? BOUND_SIZE : 0);
if (snmp_tbuf_reserve(&c, sz)) (void) snmp_tbuf_reserve(&c, sz);
snmp_log("agentx-Register-PDU small buffer");
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -363,14 +344,13 @@ un_register_pdu(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, en
* @bound: OIDs registration upper bound * @bound: OIDs registration upper bound
* @index: OIDs registration n_subid index * @index: OIDs registration n_subid index
* @is_instance: flag enabling instance registration * @is_instance: flag enabling instance registration
* @contid: context ID to register in (currently unsupported)
* *
* For more detailed description see un_register_pdu() function. * For more detailed description see un_register_pdu() function.
*/ */
void void
snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 is_instance, uint contid) snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 is_instance)
{ {
un_register_pdu(p, oid, bound, index, AGENTX_REGISTER_PDU, is_instance, contid); un_register_pdu(p, oid, bound, index, AGENTX_REGISTER_PDU, is_instance);
} }
/* /*
@ -379,14 +359,13 @@ snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 i
* @oid: OID to uregister * @oid: OID to uregister
* @bound: OIDs unregistration upper bound * @bound: OIDs unregistration upper bound
* @index: OIDs unregistration n_subid index * @index: OIDs unregistration n_subid index
* @contid: context ID to unregister from (currently unsupported)
* *
* For more detailed description see un_register_pdu() function. * For more detailed description see un_register_pdu() function.
*/ */
void void
snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, uint contid) snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index)
{ {
un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0, contid); un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0);
} }
/* /*
@ -402,8 +381,7 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
snmp_pdu_context(&c, p, sk); snmp_pdu_context(&c, p, sk);
#define REASON_SIZE sizeof(u32) #define REASON_SIZE sizeof(u32)
if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE + REASON_SIZE)) (void) snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE + REASON_SIZE);
snmp_log("agentx-Close-PDU small buffer");
struct agentx_header *h = (void *) c.buffer; struct agentx_header *h = (void *) c.buffer;
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
@ -424,7 +402,7 @@ close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt_start: pointer to first byte of PDU * @pkt_start: pointer to first byte of PDU
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static uint static uint
parse_close_pdu(struct snmp_proto *p, byte * const pkt_start) parse_close_pdu(struct snmp_proto *p, byte * const pkt_start)
@ -440,22 +418,22 @@ parse_close_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
TRACE(D_PACKETS, "SNMP malformed agentx-Close-PDU, closing anyway"); TRACE(D_PACKETS, "SNMP malformed agentx-Close-PDU, closing anyway");
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0); snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
snmp_set_state(p, SNMP_RESET); snmp_reset(p);
return MIN(pkt_size + AGENTX_HEADER_SIZE, sizeof(struct agentx_close_pdu)); return 0;
} }
if (!snmp_test_close_reason(pdu->reason)) if (!snmp_test_close_reason(pdu->reason))
{ {
TRACE(D_PACKETS, "SNMP invalid close reason %u", pdu->reason); TRACE(D_PACKETS, "SNMP invalid close reason %u", pdu->reason);
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0); snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
snmp_set_state(p, SNMP_RESET); snmp_reset(p);
return pkt_size + AGENTX_HEADER_SIZE; return 0;
} }
enum agentx_close_reasons reason = (enum agentx_close_reasons) pdu->reason; enum agentx_close_reasons reason = (enum agentx_close_reasons) pdu->reason;
TRACE(D_PACKETS, "SNMP close reason %u", reason); TRACE(D_PACKETS, "SNMP close reason %u", reason);
snmp_simple_response(p, AGENTX_RES_NO_ERROR, 0); snmp_simple_response(p, AGENTX_RES_NO_ERROR, 0);
snmp_set_state(p, SNMP_RESET); snmp_reset(p);
return pkt_size + AGENTX_HEADER_SIZE; return pkt_size + AGENTX_HEADER_SIZE;
} }
@ -478,15 +456,15 @@ refresh_ids(struct snmp_proto *p, struct agentx_header *h)
* @pkt_start: first byte of test set PDU * @pkt_start: first byte of test set PDU
* @size: number of bytes received from a socket * @size: number of bytes received from a socket
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static inline uint static inline uint
parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start) parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
TRACE(D_PACKETS, "SNMP received agentx-TestSet-PDU"); TRACE(D_PACKETS, "SNMP received agentx-TestSet-PDU");
byte *pkt = pkt_start; /* pointer to agentx-TestSet-PDU in RX-buffer */ byte *pkt = pkt_start; /* pointer to agentx-TestSet-PDU in RX buffer */
uint s; /* final packat size */ uint s; /* final packat size */
struct agentx_response *res; /* pointer to reponse in TX-buffer */ struct agentx_response *res; /* pointer to reponse in TX buffer */
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
pkt += AGENTX_HEADER_SIZE; pkt += AGENTX_HEADER_SIZE;
@ -495,8 +473,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, p, sk); snmp_pdu_context(&c, p, sk);
if (snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE)) (void) snmp_tbuf_reserve(&c, AGENTX_HEADER_SIZE);
snmp_log("agentx-TestSet-PDU small buffer");
res = prepare_response(p, &c); res = prepare_response(p, &c);
@ -534,7 +511,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
* @pkt_start: pointer to first byte of on of set related PDU * @pkt_start: pointer to first byte of on of set related PDU
* @error: error status to use * @error: error status to use
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static uint static uint
parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err) parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_response_errs err)
@ -554,8 +531,7 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, p, p->sock); snmp_pdu_context(&c, p, p->sock);
if (snmp_tbuf_reserve(&c, sizeof(struct agentx_response))) (void) snmp_tbuf_reserve(&c, sizeof(struct agentx_response));
snmp_log("parse_sets_pdu small buffer");
struct agentx_response *r = prepare_response(p, &c); struct agentx_response *r = prepare_response(p, &c);
@ -578,9 +554,9 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
/* /*
* parse_commit_set_pdu - parse an agentx-CommitSet-PDU * parse_commit_set_pdu - parse an agentx-CommitSet-PDU
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt: pointer to first byte of PDU inside RX-buffer * @pkt: pointer to first byte of PDU inside RX buffer
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static inline uint static inline uint
parse_commit_set_pdu(struct snmp_proto *p, byte *pkt) parse_commit_set_pdu(struct snmp_proto *p, byte *pkt)
@ -594,7 +570,7 @@ parse_commit_set_pdu(struct snmp_proto *p, byte *pkt)
/* /*
* parse_undo_set_pdu - parse an agentx-UndoSet-PDU * parse_undo_set_pdu - parse an agentx-UndoSet-PDU
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt: pointer to first byte of PDU inside RX-buffer * @pkt: pointer to first byte of PDU inside RX buffer
* *
* Return number of bytes parsed from buffer. * Return number of bytes parsed from buffer.
*/ */
@ -610,9 +586,9 @@ parse_undo_set_pdu(struct snmp_proto *p, byte *pkt)
/* /*
* parse_cleanup_set_pdu - parse an agentx-CleanupSet-PDU * parse_cleanup_set_pdu - parse an agentx-CleanupSet-PDU
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt_start: pointer to first byte of PDU inside RX-buffer * @pkt_start: pointer to first byte of PDU inside RX buffer
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static uint static uint
parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start) parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
@ -639,7 +615,7 @@ parse_cleanup_set_pdu(struct snmp_proto *p, byte * const pkt_start)
} }
/* /*
* space_for_response - check if TX-buffer has space for agentx-Response-PDU * space_for_response - check if TX buffer has space for agentx-Response-PDU
* @sk: communication socket owned by SNMP protocol instance * @sk: communication socket owned by SNMP protocol instance
* *
* In some cases we send only the AgentX header but if we want to signal an * In some cases we send only the AgentX header but if we want to signal an
@ -657,10 +633,10 @@ space_for_response(const sock *sk)
/** /**
* parse_pkt - parse received AgentX packet * parse_pkt - parse received AgentX packet
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt: first byte of PDU inside RX-buffer * @pkt: first byte of PDU inside RX buffer
* @size: number of bytes received from a socket * @size: number of bytes received from a socket
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static uint static uint
parse_pkt(struct snmp_proto *p, byte *pkt, uint size) parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
@ -685,7 +661,7 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
TRACE(D_PACKETS, "SNMP received PDU is too long"); TRACE(D_PACKETS, "SNMP received PDU is too long");
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0); snmp_simple_response(p, AGENTX_RES_GEN_ERROR, 0);
snmp_reset(p); snmp_reset(p);
return 0; /* no bytes parsed */ return 0;
} }
/* This guarantees that we have the full packet already received */ /* This guarantees that we have the full packet already received */
@ -768,9 +744,9 @@ parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
/* /*
* parse_response - parse an agentx-Response-PDU * parse_response - parse an agentx-Response-PDU
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @res: pointer of agentx-Response-PDU header in RX-buffer * @res: pointer of agentx-Response-PDU header in RX buffer
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static uint static uint
parse_response(struct snmp_proto *p, byte *res) parse_response(struct snmp_proto *p, byte *res)
@ -778,7 +754,6 @@ parse_response(struct snmp_proto *p, byte *res)
struct agentx_response *r = (void *) res; struct agentx_response *r = (void *) res;
struct agentx_header *h = (void *) r; struct agentx_header *h = (void *) r;
// todo reject not compiled byte order
uint pkt_size = LOAD_U32(h->payload); uint pkt_size = LOAD_U32(h->payload);
switch (r->error) switch (r->error)
@ -812,7 +787,8 @@ parse_response(struct snmp_proto *p, byte *res)
case AGENTX_RES_PROCESSING_ERR: case AGENTX_RES_PROCESSING_ERR:
default: default:
TRACE(D_PACKETS, "SNMP agentx-Response-PDU with unexepected error %u", r->error); TRACE(D_PACKETS, "SNMP agentx-Response-PDU with unexepected error %u", r->error);
snmp_stop(p); //snmp_stop(p);
snmp_reset(p);
break; break;
} }
@ -832,9 +808,9 @@ snmp_register_mibs(struct snmp_proto *p)
/* /*
* do_response - act on agentx-Response-PDU and protocol state * do_response - act on agentx-Response-PDU and protocol state
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @pkt: RX-buffer with PDU bytes * @pkt: RX buffer with PDU bytes
* *
* Return number of bytes parsed from RX-buffer. * Return number of bytes parsed from RX buffer.
*/ */
static void static void
do_response(struct snmp_proto *p, byte *pkt) do_response(struct snmp_proto *p, byte *pkt)
@ -910,8 +886,7 @@ void
snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid) snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
{ {
uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid); uint vb_hdr_size = snmp_varbind_hdr_size_from_oid(oid);
if (snmp_tbuf_reserve(c, vb_hdr_size)) (void) snmp_tbuf_reserve(c, vb_hdr_size);
snmp_log("SNMP vb_to_tx small buffer");
ASSERT(c->size >= vb_hdr_size); ASSERT(c->size >= vb_hdr_size);
struct agentx_varbind *vb = (struct agentx_varbind *) c->buffer; struct agentx_varbind *vb = (struct agentx_varbind *) c->buffer;
@ -935,12 +910,22 @@ snmp_vb_to_tx(struct snmp_pdu *c, const struct oid *oid)
c->sr_vb_start = vb; c->sr_vb_start = vb;
} }
/*
* snmp_fix_vb - fix VarBind's name OID byte order
* @vb: VarBind to use
*/
void
snmp_fix_vb(struct agentx_varbind *vb)
{
snmp_oid_copy(&vb->name, &vb->name);
}
/* /*
* update_packet_size - set PDU size * update_packet_size - set PDU size
* @start - pointer to PDU data start (excluding header size) * @start - pointer to PDU data start (excluding header size)
* @end - pointer after the last PDU byte * @end - pointer after the last PDU byte
* *
* Return number of bytes in TX-buffer (including header size). * Return number of bytes in TX buffer (including header size).
*/ */
static inline uint static inline uint
update_packet_size(struct agentx_header *start, byte *end) update_packet_size(struct agentx_header *start, byte *end)
@ -985,18 +970,6 @@ response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_
STORE_U16(res->index, 0); STORE_U16(res->index, 0);
} }
static inline uint
parse_gets_error(struct snmp_proto *p, struct snmp_pdu *c, uint len)
{
TRACE(D_PACKETS, "SNMP error %u while parsing gets PDU", c->error);
if (c->index > UINT16_MAX)
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, UINT16_MAX);
else
snmp_simple_response(p, AGENTX_RES_GEN_ERROR, c->index);
return len + AGENTX_HEADER_SIZE;
}
/* /*
* AgentX GetPDU, GetNextPDU and GetBulkPDU * AgentX GetPDU, GetNextPDU and GetBulkPDU
*/ */
@ -1005,18 +978,12 @@ parse_gets_error(struct snmp_proto *p, struct snmp_pdu *c, uint len)
void void
snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk) snmp_get_pdu(struct snmp_proto *p, struct snmp_pdu *c, const struct oid *o_start, struct mib_walk_state *walk)
{ {
snmp_log("snmp_get_pdu()");
struct mib_leaf *leaf; struct mib_leaf *leaf;
leaf = snmp_walk_init(p->mib_tree, walk, o_start, c); leaf = snmp_walk_init(p->mib_tree, walk, o_start, c);
snmp_log("found node %p", leaf);
enum snmp_search_res res; enum snmp_search_res res;
res = snmp_walk_fill(leaf, walk, c); res = snmp_walk_fill(leaf, walk, c);
snmp_log("fill result %u", res);
if (res != SNMP_SEARCH_OK) if (res != SNMP_SEARCH_OK)
snmp_set_varbind_type(c->sr_vb_start, snmp_search_res_to_type(res)); snmp_set_varbind_type(c->sr_vb_start, snmp_search_res_to_type(res));
} }
@ -1060,7 +1027,6 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
if ((sz = snmp_oid_size(start)) > pkt_size) if ((sz = snmp_oid_size(start)) > pkt_size)
{ {
snmp_log("load_oids start %u / %u", sz, pkt_size);
c->error = AGENTX_RES_PARSE_ERROR; c->error = AGENTX_RES_PARSE_ERROR;
*pkt_ptr = pkt; *pkt_ptr = pkt;
*pkt_sz = pkt_size; *pkt_sz = pkt_size;
@ -1072,7 +1038,6 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
const struct oid *end = (const struct oid *) pkt; const struct oid *end = (const struct oid *) pkt;
if ((sz = snmp_oid_size(end)) > pkt_size) if ((sz = snmp_oid_size(end)) > pkt_size)
{ {
snmp_log("load_oids end %u / %u", sz, pkt_size);
c->error = AGENTX_RES_PARSE_ERROR; c->error = AGENTX_RES_PARSE_ERROR;
*pkt_ptr = pkt; *pkt_ptr = pkt;
*pkt_sz = pkt_size; *pkt_sz = pkt_size;
@ -1081,6 +1046,7 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
ADVANCE(pkt, pkt_size, sz); ADVANCE(pkt, pkt_size, sz);
// TODO: this does not work
if (!snmp_is_oid_empty(end) && if (!snmp_is_oid_empty(end) &&
snmp_oid_compare(start, end) > 0) snmp_oid_compare(start, end) > 0)
{ {
@ -1106,13 +1072,11 @@ snmp_load_oids(byte **pkt_ptr, uint *pkt_sz, struct snmp_pdu *c)
* *
* Gets PDUs are agentx-Get-PDU, agentx-GetNext-PDU, agentx-GetBulk-PDU. * Gets PDUs are agentx-Get-PDU, agentx-GetNext-PDU, agentx-GetBulk-PDU.
* *
* Return number of bytes parsed from RX-buffer * Return number of bytes parsed from RX buffer
*/ */
static uint static uint
parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start) parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
snmp_log("parse_gets_pdu msg");
// TODO checks for c.size underflow
struct mib_walk_state walk; struct mib_walk_state walk;
byte *pkt = pkt_start; byte *pkt = pkt_start;
@ -1125,18 +1089,20 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
snmp_pdu_context(&c, p, sk); snmp_pdu_context(&c, p, sk);
/* /*
* Get-Bulk processing stops if all the varbind have type END_OF_MIB_VIEW * Get-Bulk processing stops if all the varbind have type endOfMibView
* has_any is true if some varbind has type other than END_OF_MIB_VIEW * has_any is true if some varbind has type other than endOfMibView
*/ */
struct agentx_bulk_state bulk_state = { 0 }; struct agentx_bulk_state bulk_state = { 0 };
if (h->type == AGENTX_GET_BULK_PDU) if (h->type == AGENTX_GET_BULK_PDU)
{ {
die("bulk");
#if 0
if (pkt_size < sizeof(struct agentx_getbulk)) if (pkt_size < sizeof(struct agentx_getbulk))
{ {
snmp_log("parse_gets GetBulkPDU prepare"); snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
c.error = AGENTX_RES_PARSE_ERROR; snmp_reset(p);
c.index = 0; return pkt_size + AGENTX_HEADER_SIZE;
return parse_gets_error(p, &c, pkt_size);
} }
struct agentx_getbulk *bulk_info = (void *) pkt; struct agentx_getbulk *bulk_info = (void *) pkt;
@ -1152,6 +1118,7 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
.repetition = 0, .repetition = 0,
.has_any = 0, .has_any = 0,
}; };
#endif
} }
struct agentx_response *response_header = prepare_response(p, &c); struct agentx_response *response_header = prepare_response(p, &c);
@ -1165,8 +1132,10 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
const struct oid *start_rx; const struct oid *start_rx;
if (!(start_rx = snmp_load_oids(&pkt, &pkt_size, &c))) if (!(start_rx = snmp_load_oids(&pkt, &pkt_size, &c)))
{ {
snmp_log("snmp_load_oid ends with an error"); snmp_simple_response(p, c.error,
return parse_gets_error(p, &c, pkt_size); (c.index > UINT16_MAX) ? UINT16_MAX : c.index);
snmp_reset(p);
return pkt_size + AGENTX_HEADER_SIZE;
} }
switch (h->type) switch (h->type)
@ -1195,23 +1164,24 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
lp_restore(tmp_linpool, &tmps); lp_restore(tmp_linpool, &tmps);
#if 0
if (h->type == AGENTX_GET_BULK_PDU) if (h->type == AGENTX_GET_BULK_PDU)
{ {
// TODO: an error for now // TODO: an error for now
die("bulk");
} }
#endif
/* We update the error, index pair on the beginning of the packet. */ /* We update the error, index pair on the beginning of the packet. */
response_err_ind(p, response_header, c.error, c.index + 1); response_err_ind(p, response_header, c.error, c.index + 1);
uint s = update_packet_size(&response_header->h, c.buffer); uint s = update_packet_size(&response_header->h, c.buffer);
/* We send the message in TX-buffer. */ /* We send the message in TX buffer. */
sk_send(sk, s); sk_send(sk, s);
snmp_log("gets send %t", current_time());
// TODO think through the error state // TODO think through the error state
/* number of bytes parsed from RX-buffer */ /* number of bytes parsed from RX buffer */
return pkt - pkt_start; return pkt - pkt_start;
} }
@ -1246,7 +1216,7 @@ snmp_stop_subagent(struct snmp_proto *p)
} }
/* /*
* snmp_rx - handle received PDUs in RX-buffer in normal operation * snmp_rx - handle received PDUs in RX buffer in normal operation
* @sk: communication socket * @sk: communication socket
* @size: number of bytes received * @size: number of bytes received
*/ */
@ -1268,9 +1238,9 @@ snmp_rx(sock *sk, uint size)
size -= parsed_len; size -= parsed_len;
} }
/* We flush the RX-buffer on errors */ /* We flush the RX buffer on errors */
if (!snmp_is_active(p) || pkt_start == end) if (!snmp_is_active(p) || pkt_start == end)
return 1; /* The whole RX-buffer was consumed */ return 1; /* The whole RX buffer was consumed */
/* Incomplete packet parsing */ /* Incomplete packet parsing */
memmove(sk->rbuf, pkt_start, size); memmove(sk->rbuf, pkt_start, size);
@ -1279,21 +1249,20 @@ snmp_rx(sock *sk, uint size)
} }
/* /*
* snmp_tx - handle TX-buffer * snmp_tx - handle TX buffer
* @sk: communication socket owned by SNMP protocol instance * @sk: communication socket owned by SNMP protocol instance
* *
* The snmp_tx hook is used only to delay the processing in cases we don't have * The snmp_tx hook is used only to delay the processing in cases we don't have
* enough space in TX-buffer. Therefore we simply call the snmp_rx hook. * enough space in TX buffer. Therefore we simply call the snmp_rx hook.
*/ */
void void
snmp_tx(sock *sk) snmp_tx(sock *sk)
{ {
snmp_log("snmp_tx()");
/* We still not have enough space */ /* We still not have enough space */
if (!space_for_response(sk)) if (!space_for_response(sk))
return; return;
/* There is nothing to process, no bytes in RX-buffer */ /* There is nothing to process, no bytes in RX buffer */
if (sk_tx_buffer_empty(sk)) if (sk_tx_buffer_empty(sk))
return; return;
@ -1326,7 +1295,6 @@ snmp_ping(struct snmp_proto *p)
ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE); ADVANCE(c.buffer, c.size, AGENTX_HEADER_SIZE);
snmp_blank_header(h, AGENTX_PING_PDU); snmp_blank_header(h, AGENTX_PING_PDU);
p->packet_id++; p->packet_id++;
snmp_log("incrementing packet_id to %u (ping)", p->packet_id);
snmp_session(p, h); snmp_session(p, h);
/* sending only header */ /* sending only header */
@ -1335,27 +1303,12 @@ snmp_ping(struct snmp_proto *p)
sk_send(sk, s); sk_send(sk, s);
} }
/**
* snmp_search_check_end_oid - check if oid is before SearchRange end
*
* @found: best oid found in MIB tree
* @bound: upper bound specified in SearchRange
*
* check if found oid meet the SearchRange upper bound condition in
* lexicographical order, returns boolean value
*/
int
snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
{
if (snmp_is_oid_empty(bound))
return 1;
return (snmp_oid_compare(found, bound) < 0);
}
/* /*
* snmp_tbuf_reserve - TODO * snmp_tbuf_reserve - conditionally grow the TX buffer
* @c: transmit PDU context
* @size: size to make available
* *
* Return non-zero if the buffer was relocated.
*/ */
int int
snmp_tbuf_reserve(struct snmp_pdu *c, size_t size) snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
@ -1365,16 +1318,15 @@ snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
struct snmp_proto *p = c->p; struct snmp_proto *p = c->p;
sock *sk = p->sock; sock *sk = p->sock;
int diff; int start_diff;
if (c->sr_vb_start != NULL) if (c->sr_vb_start != NULL)
diff = (char *) c->sr_vb_start - (char *) sk->tbuf; start_diff = (char *) c->sr_vb_start - (char *) sk->tbuf;
snmp_log("snmp_tbuf_reserve()");
sk_set_tbsize(sk, sk->tbsize + 2048); sk_set_tbsize(sk, sk->tbsize + 2048);
c->size += 2048; c->size += 2048;
if (c->sr_vb_start != NULL) if (c->sr_vb_start != NULL)
c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + diff); c->sr_vb_start = (struct agentx_varbind *) (sk->tbuf + start_diff);
return 1; return 1;
} }
@ -1387,7 +1339,7 @@ snmp_tbuf_reserve(struct snmp_pdu *c, size_t size)
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @c: transmit PDU context to use * @c: transmit PDU context to use
* *
* Prepare known parts of AgentX packet header into the TX-buffer held by @c. * Prepare known parts of AgentX packet header into the TX buffer held by @c.
*/ */
static struct agentx_response * static struct agentx_response *
prepare_response(struct snmp_proto *p, struct snmp_pdu *c) prepare_response(struct snmp_proto *p, struct snmp_pdu *c)

View File

@ -357,10 +357,10 @@ struct snmp_packet_info {
}; };
int snmp_rx(sock *sk, uint size); int snmp_rx(sock *sk, uint size);
void snmp_tx(sock *sk);
int snmp_rx_stop(sock *sk, uint size); int snmp_rx_stop(sock *sk, uint size);
void snmp_down(struct snmp_proto *p); void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance);
void snmp_register(struct snmp_proto *p, struct oid *oid, uint index, uint len, u8 is_instance, uint contid); void snmp_unregister(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_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, int include_uptime);
int snmp_tbuf_reserve(struct snmp_pdu *c, size_t bytes); int snmp_tbuf_reserve(struct snmp_pdu *c, size_t bytes);
@ -378,12 +378,4 @@ u8 snmp_get_mib_class(const struct oid *oid);
void snmp_register_mibs(struct snmp_proto *p); void snmp_register_mibs(struct snmp_proto *p);
/* MIB modules */
#if 1
#define snmp_log(...) log(L_INFO "SNMP " __VA_ARGS__)
#else
#define snmp_log(...) do { } while(0)
#endif
#endif #endif