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

SNMP: tmp

This commit is contained in:
Vojtech Vilimek 2024-07-09 16:56:16 +02:00
parent 5ef5b19dae
commit 4b7989aa45
8 changed files with 11 additions and 1614 deletions

View File

@ -59,148 +59,6 @@ snmp_bgp_last_error(const struct bgp_proto *bgp, char err[2])
err[1] = bgp->last_error_code & 0x000000FF; err[1] = bgp->last_error_code & 0x000000FF;
} }
static u8
bgp_get_candidate(u32 field)
{
const u8 translation_table[] = {
[BGP4_MIB_PEER_IDENTIFIER] = BGP4_MIB_S_PEER_IDENTIFIER,
[BGP4_MIB_STATE] = BGP4_MIB_S_STATE,
[BGP4_MIB_ADMIN_STATUS] = BGP4_MIB_S_ADMIN_STATUS,
[BGP4_MIB_NEGOTIATED_VERSION] = BGP4_MIB_S_NEGOTIATED_VERSION,
[BGP4_MIB_LOCAL_ADDR] = BGP4_MIB_S_LOCAL_ADDR,
[BGP4_MIB_LOCAL_PORT] = BGP4_MIB_S_LOCAL_PORT,
[BGP4_MIB_REMOTE_ADDR] = BGP4_MIB_S_REMOTE_ADDR,
[BGP4_MIB_REMOTE_PORT] = BGP4_MIB_S_REMOTE_PORT,
[BGP4_MIB_REMOTE_AS] = BGP4_MIB_S_REMOTE_AS,
[BGP4_MIB_RX_UPDATES] = BGP4_MIB_S_RX_UPDATES,
[BGP4_MIB_TX_UPDATES] = BGP4_MIB_S_TX_UPDATES,
[BGP4_MIB_RX_MESSAGES] = BGP4_MIB_S_RX_MESSAGES,
[BGP4_MIB_TX_MESSAGES] = BGP4_MIB_S_TX_MESSAGES,
[BGP4_MIB_LAST_ERROR] = BGP4_MIB_S_LAST_ERROR,
[BGP4_MIB_FSM_TRANSITIONS] = BGP4_MIB_S_FSM_TRANSITIONS,
[BGP4_MIB_FSM_ESTABLISHED_TIME] = BGP4_MIB_S_FSM_ESTABLISHED_TIME,
[BGP4_MIB_RETRY_INTERVAL] = BGP4_MIB_S_RETRY_INTERVAL,
[BGP4_MIB_HOLD_TIME] = BGP4_MIB_S_HOLD_TIME,
[BGP4_MIB_KEEPALIVE] = BGP4_MIB_S_KEEPALIVE,
[BGP4_MIB_HOLD_TIME_CONFIGURED] = BGP4_MIB_S_HOLD_TIME_CONFIGURED,
[BGP4_MIB_KEEPALIVE_CONFIGURED] = BGP4_MIB_S_KEEPALIVE_CONFIGURED,
[BGP4_MIB_ORIGINATION_INTERVAL] = BGP4_MIB_S_ORIGINATION_INTERVAL,
[BGP4_MIB_MIN_ROUTE_ADVERTISEMENT] = BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT,
[BGP4_MIB_IN_UPDATE_ELAPSED_TIME] = BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME,
};
/*
* First value is in secord cell of array translation_table, as the
* SNMP_BGP_IDENTIFIER == 1
*/
if (field > 0 && field <= ARRAY_SIZE(translation_table)- 1)
return translation_table[field];
else if (field == 0)
return BGP4_MIB_S_PEER_ENTRY;
else
return BGP4_MIB_S_PEER_TABLE_END;
}
/**
* snmp_bgp_state - linearize oid from BGP4-MIB
* @oid: prefixed object identifier from BGP4-MIB::bgp subtree
*
* Returns linearized state for Get-PDU, GetNext-PDU and GetBulk-PDU packets.
*/
static u8
snmp_bgp_state(const struct oid *oid)
{
/*
* Ids of Object Identifier that are already checked:
* internet oid.prefix
* v...... v
* (*oid): .1.3.6.1.2.1.15
* -> BGP4-MIB::bgp (root)
*/
if (snmp_is_oid_empty(oid))
return BGP4_MIB_S_END;
u8 state = BGP4_MIB_S_NO_VALUE;
u8 candidate;
switch (oid->n_subid)
{
default:
if (oid->n_subid < 2)
{
state = BGP4_MIB_S_INVALID;
break;
}
/* fall through */
/*
* Between ids[5] and ids[8] (n_subid == 9) should be IP address.
* Validity is checked later in execution because
* this field also could mean a query boundry (upper or lower).
*/
case 9:
case 8:
case 7:
case 6:
case 5:
state = bgp_get_candidate(oid->ids[4]);
/* fall through */
case 4:
if (oid->ids[3] == BGP4_MIB_PEER_ENTRY)
state = (state == BGP4_MIB_S_NO_VALUE) ?
BGP4_MIB_S_PEER_ENTRY : state;
else
state = BGP4_MIB_S_NO_VALUE;
/* fall through */
case 3:
/* u8 candidate; */
switch (oid->ids[2])
{
case BGP4_MIB_VERSION:
state = BGP4_MIB_S_VERSION;
break;
case BGP4_MIB_LOCAL_AS:
state = BGP4_MIB_S_LOCAL_AS;
break;
case BGP4_MIB_PEER_TABLE:
/* We use candidate to avoid overriding more specific state */
candidate = BGP4_MIB_S_PEER_TABLE;
break;
case BGP4_MIB_IDENTIFIER:
state = BGP4_MIB_S_IDENTIFIER;
break;
default: /* test fails */
/* We force state invalidation */
if (oid->ids[2] < BGP4_MIB_VERSION)
{
state = BGP4_MIB_S_NO_VALUE;
candidate = BGP4_MIB_S_NO_VALUE;
}
else /* oid->ids[2] > BGP4_MIB_PEER_TABLE */
state = BGP4_MIB_S_END;
}
state = (state == BGP4_MIB_S_NO_VALUE) ?
candidate : state;
/* fall through */
case 2: /* We found bare BGP4-MIB::bgp ObjectId */
if (state == BGP4_MIB_S_NO_VALUE ||
state == BGP4_MIB_S_INVALID)
state = BGP4_MIB_S_BGP;
}
return state;
}
static void static void
snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg) snmp_bgp_reg_ok(struct snmp_proto *p, const struct agentx_response *res, struct snmp_registration *reg)
{ {
@ -430,10 +288,9 @@ ip4_to_oid(struct oid *o, ip4_addr addr)
STORE_U32(o->ids[8], (tmp & 0x000000FF) >> 0); STORE_U32(o->ids[8], (tmp & 0x000000FF) >> 0);
} }
static void static void UNUSED
print_bgp_record(const struct bgp_proto *bgp_proto) print_bgp_record(const struct bgp_proto *bgp_proto)
{ {
//struct proto_config *cf = bgp_proto->p.cf;
struct bgp_conn *conn = bgp_proto->conn; struct bgp_conn *conn = bgp_proto->conn;
DBG(" name: %s", cf->name); DBG(" name: %s", cf->name);
@ -473,130 +330,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 void UNUSED
print_bgp_record_all(struct snmp_proto *p)
{
DBG("dumping watched bgp status");
HASH_WALK(p->bgp_hash, next, peer)
{
print_bgp_record(peer->bgp_proto);
}
HASH_WALK_END;
DBG("dumping watched end");
}
/*
* is_dynamic - is state dependent on runtime BGP peer state
* @state: tested bgp4_mib state
*
* Used to distinguish states that depend on runtime BGP peer states.
*
* Return nonzero for states with value that may change at runtime.
*/
static inline int
is_dynamic(u8 state)
{
return (state >= BGP4_MIB_S_PEER_IDENTIFIER &&
state <= BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME);
}
/*
* is_static - logical inverse of is_dynamic() for states with value
* @state: tested bgp4_mib state
*
* Return nonzero for states with value that do not change at runtime.
*/
static inline int
is_static(u8 state)
{
return (state == BGP4_MIB_S_VERSION ||
state == BGP4_MIB_S_LOCAL_AS ||
state == BGP4_MIB_S_IDENTIFIER);
}
static inline int
snmp_bgp_has_value(u8 state)
{
if (state <= BGP4_MIB_S_BGP ||
state == BGP4_MIB_S_PEER_TABLE ||
state == BGP4_MIB_S_PEER_ENTRY ||
state == BGP4_MIB_S_PEER_TABLE_END ||
state >= BGP4_MIB_S_END)
return 0;
else
return 1;
}
/**
* snmp_bgp_get_valid - only states with valid value
* @state: BGP linearized state
*
* Returns @state if has value in BGP4-MIB, zero otherwise. Used for Get-PDU
* packets.
*/
u8
snmp_bgp_get_valid(u8 state)
{
if (state == BGP4_MIB_S_INVALID ||
state == BGP4_MIB_S_BGP ||
state == BGP4_MIB_S_PEER_TABLE ||
state == BGP4_MIB_S_PEER_ENTRY ||
state == BGP4_MIB_S_PEER_TABLE_END ||
state >= BGP4_MIB_S_END)
return 0;
else
return state;
}
/**
* snmp_bgp_next_state - next state that has value
* @state: BGP linearized state
*
* Returns successor state of @state with valid value in BG4-MIB. Used for
* GetNext-PDU and GetBulk-PDU packets.
*/
u8
snmp_bgp_next_state(u8 state)
{
switch (state)
{
case BGP4_MIB_S_LOCAL_AS:
case BGP4_MIB_S_PEER_TABLE:
case BGP4_MIB_S_PEER_ENTRY:
return BGP4_MIB_S_PEER_IDENTIFIER;
case BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME:
case BGP4_MIB_S_PEER_TABLE_END:
return BGP4_MIB_S_IDENTIFIER;
case BGP4_MIB_S_IDENTIFIER:
case BGP4_MIB_S_END:
return BGP4_MIB_S_END;
default:
return state + 1;
}
}
static int
oid_state_compare(const struct oid *oid, u8 state)
{
ASSUME(oid != NULL);
if (state >= BGP4_MIB_S_PEER_IDENTIFIER &&
state <= BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME)
return (oid->n_subid > 9) - (oid->n_subid < 9);
if ((state >= BGP4_MIB_S_VERSION && state <= BGP4_MIB_S_PEER_TABLE) ||
(state == BGP4_MIB_S_IDENTIFIER))
return (oid->n_subid > 3) - (oid->n_subid < 3);
if (state == BGP4_MIB_S_PEER_ENTRY)
return (oid->n_subid > 4) - (oid->n_subid < 4);
if (state == BGP4_MIB_S_BGP)
return (oid->n_subid > 2) - (oid->n_subid < 2);
return -1;
}
static inline enum snmp_search_res static inline enum snmp_search_res
populate_bgp4(struct snmp_data *d, ip4_addr *addr, const struct bgp_proto **proto, const struct bgp_conn populate_bgp4(struct snmp_data *d, ip4_addr *addr, const struct bgp_proto **proto, const struct bgp_conn
@ -1050,652 +783,10 @@ fill_local_id(struct mib_walk_state *walk UNUSED, struct snmp_data *d)
return SNMP_SEARCH_OK; return SNMP_SEARCH_OK;
} }
static struct oid *
update_bgp_vb(struct snmp_proto *p, struct agentx_varbind **vb, u8 state, struct snmp_pdu *c)
{
struct oid *oid = &(*vb)->name;
if (state == BGP4_MIB_S_END || state == BGP4_MIB_S_INVALID ||
state == BGP4_MIB_S_NO_VALUE)
return &(*vb)->name;
/* No need to reallocate anything if the OID has same lin. state */
if (snmp_bgp_state(oid) == state)
{
if (state >= BGP4_MIB_S_PEER_IDENTIFIER &&
state <= BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME &&
oid->n_subid == 9)
return oid;
if (state >= BGP4_MIB_S_VERSION &&
state <= BGP4_MIB_S_PEER_TABLE && oid->n_subid == 3)
return oid;
if (state == BGP4_MIB_S_PEER_ENTRY && oid->n_subid == 4)
return oid;
if (state == BGP4_MIB_S_BGP && oid->n_subid == 2)
return oid;
}
switch (state)
{
case BGP4_MIB_S_BGP:
/* This could potentially destroy same old data */
if (oid->n_subid != 2)
oid = snmp_varbind_set_name_len(p, vb, 2, c);
oid->ids[0] = SNMP_MIB_2;
oid->ids[1] = BGP4_MIB;
break;
case BGP4_MIB_S_VERSION:
if (oid->n_subid != 3)
oid = snmp_varbind_set_name_len(p, vb, 3, c);
oid->ids[2] = BGP4_MIB_VERSION;
break;
case BGP4_MIB_S_LOCAL_AS:
if (oid->n_subid != 3)
oid =snmp_varbind_set_name_len(p, vb, 3, c);
oid->ids[2] = BGP4_MIB_LOCAL_AS;
break;
case BGP4_MIB_S_PEER_IDENTIFIER:
if (oid->n_subid != 9)
{
u8 n_subid = LOAD_U8(oid->n_subid);
oid = snmp_varbind_set_name_len(p, vb, 9, c);
if (n_subid < 6)
oid->ids[5] = 0;
if (n_subid < 7)
oid->ids[6] = 0;
if (n_subid < 8)
oid->ids[7] = 0;
if (n_subid < 9)
oid->ids[8] = 0;
}
oid->ids[2] = BGP4_MIB_PEER_TABLE;
oid->ids[3] = BGP4_MIB_PEER_ENTRY;
oid->ids[4] = BGP4_MIB_PEER_IDENTIFIER;
break;
#define SNMP_UPDATE_CASE(num, update) \
case num: \
if (oid->n_subid != 9) \
{ \
u8 n_subid = LOAD_U8(oid->n_subid); \
oid = snmp_varbind_set_name_len(p, vb, 9, c); \
\
if (n_subid < 6) \
oid->ids[5] = 0; \
if (n_subid < 7) \
oid->ids[6] = 0; \
if (n_subid < 8) \
oid->ids[7] = 0; \
if (n_subid < 9) \
oid->ids[8] = 0; \
} \
\
oid->n_subid = 9; \
oid->ids[4] = update; \
break;
SNMP_UPDATE_CASE(BGP4_MIB_S_STATE, BGP4_MIB_STATE)
SNMP_UPDATE_CASE(BGP4_MIB_S_ADMIN_STATUS, BGP4_MIB_ADMIN_STATUS)
SNMP_UPDATE_CASE(BGP4_MIB_S_NEGOTIATED_VERSION, BGP4_MIB_NEGOTIATED_VERSION)
SNMP_UPDATE_CASE(BGP4_MIB_S_LOCAL_ADDR, BGP4_MIB_LOCAL_ADDR)
SNMP_UPDATE_CASE(BGP4_MIB_S_LOCAL_PORT, BGP4_MIB_LOCAL_PORT)
SNMP_UPDATE_CASE(BGP4_MIB_S_REMOTE_ADDR, BGP4_MIB_REMOTE_ADDR)
SNMP_UPDATE_CASE(BGP4_MIB_S_REMOTE_PORT, BGP4_MIB_REMOTE_PORT)
SNMP_UPDATE_CASE(BGP4_MIB_S_REMOTE_AS, BGP4_MIB_REMOTE_AS)
SNMP_UPDATE_CASE(BGP4_MIB_S_RX_UPDATES, BGP4_MIB_RX_UPDATES)
SNMP_UPDATE_CASE(BGP4_MIB_S_TX_UPDATES, BGP4_MIB_TX_UPDATES)
SNMP_UPDATE_CASE(BGP4_MIB_S_RX_MESSAGES, BGP4_MIB_RX_MESSAGES)
SNMP_UPDATE_CASE(BGP4_MIB_S_TX_MESSAGES, BGP4_MIB_TX_MESSAGES)
SNMP_UPDATE_CASE(BGP4_MIB_S_LAST_ERROR, BGP4_MIB_LAST_ERROR)
SNMP_UPDATE_CASE(BGP4_MIB_S_FSM_TRANSITIONS, BGP4_MIB_FSM_TRANSITIONS)
SNMP_UPDATE_CASE(BGP4_MIB_S_FSM_ESTABLISHED_TIME, BGP4_MIB_FSM_ESTABLISHED_TIME)
SNMP_UPDATE_CASE(BGP4_MIB_S_RETRY_INTERVAL, BGP4_MIB_RETRY_INTERVAL)
SNMP_UPDATE_CASE(BGP4_MIB_S_HOLD_TIME, BGP4_MIB_HOLD_TIME)
SNMP_UPDATE_CASE(BGP4_MIB_S_KEEPALIVE, BGP4_MIB_KEEPALIVE)
SNMP_UPDATE_CASE(BGP4_MIB_S_HOLD_TIME_CONFIGURED, BGP4_MIB_HOLD_TIME_CONFIGURED)
SNMP_UPDATE_CASE(BGP4_MIB_S_KEEPALIVE_CONFIGURED, BGP4_MIB_KEEPALIVE_CONFIGURED)
SNMP_UPDATE_CASE(BGP4_MIB_S_ORIGINATION_INTERVAL, BGP4_MIB_ORIGINATION_INTERVAL)
SNMP_UPDATE_CASE(BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT, BGP4_MIB_MIN_ROUTE_ADVERTISEMENT)
SNMP_UPDATE_CASE(BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME, BGP4_MIB_IN_UPDATE_ELAPSED_TIME)
case BGP4_MIB_S_IDENTIFIER:
if (oid->n_subid != 3)
oid = snmp_varbind_set_name_len(p, vb, 3, c);
oid->n_subid = 3;
oid->ids[2] = 4;
break;
default:
/* intentionally left blank */
break;
}
return oid;
#undef SNMP_UPDATE_CASE
}
/**
* snmp_bgp_find_next_oid - walk bgp peer addresses and update @o_start oid
*
* @p:
* @oid:
* @contid:
*/
static int
snmp_bgp_find_next_oid(struct snmp_proto *p, struct oid *oid, uint UNUSED contid)
{
ip4_addr ip4 = ip4_from_oid(oid);
net_addr net;
net_fill_ip4(&net, ip4, IP4_MAX_PREFIX_LENGTH);
struct f_trie_walk_state ws;
int match = trie_walk_init(&ws, p->bgp_trie, &net, 1);
if (match && oid->include)
{
oid->include = 0;
return 1;
}
/* We skip the first match as we should not include ip address in oid */
if (match)
{
trie_walk_next(&ws, &net);
}
if (trie_walk_next(&ws, &net))
{
ASSUME(oid->n_subid == 9);
ip4_addr res = ipa_to_ip4(net_prefix(&net));
ip4_to_oid(oid, res);
return 1;
}
return 0;
}
static enum snmp_search_res UNUSED
snmp_bgp_search_dynamic(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint UNUSED contid, u8 next_state, struct snmp_pdu *c)
{
struct oid *oid = *searched;
u8 end_state = MIN(snmp_bgp_state(o_end), BGP4_MIB_S_PEER_TABLE_END);
ASSUME(end_state <= BGP4_MIB_S_END);
ASSUME(oid != NULL);
// TODO TODO remove me
struct agentx_varbind data = { 0 };
struct agentx_varbind *vb = &data;
oid = update_bgp_vb(p, &vb, next_state, c);
//oid = update_bgp_oid(oid, next_state);
int found;
while (!(found = snmp_bgp_find_next_oid(p, oid, contid)) && next_state <= end_state)
{
next_state = snmp_bgp_next_state(next_state);
if (next_state == BGP4_MIB_S_IDENTIFIER)
break;
//oid = update_bgp_oid(oid, next_state);
oid = update_bgp_vb(p, &vb, next_state, c);
/* In case of search for next bgp state, we want to start from beginning. */
oid->ids[5] = oid->ids[6] = oid->ids[7] = oid->ids[8] = 0;
}
if (next_state < BGP4_MIB_S_PEER_TABLE_END && next_state <= end_state)
{
*searched = oid;
return SNMP_SEARCH_OK;
}
return SNMP_SEARCH_END_OF_VIEW;
}
enum snmp_search_res
snmp_bgp_search(struct snmp_proto *p, struct agentx_varbind **vb_search, const struct oid *o_end, struct snmp_pdu *c)
{
(void)p;
(void)vb_search;
(void)o_end;
(void)c;
return SNMP_SEARCH_END_OF_VIEW;
#if 0
enum snmp_search_res r = SNMP_SEARCH_END_OF_VIEW;
u8 bgp_state = snmp_bgp_state(*searched);
u8 state;
if (bgp_state == BGP4_MIB_S_END)
{
return SNMP_SEARCH_NO_OBJECT;
}
if (is_static(bgp_state) && (*searched)->include)
{
return SNMP_SEARCH_OK;
}
state = snmp_bgp_next_state(bgp_state);
if (is_static(state) && !is_dynamic(bgp_state))
{
*searched = update_bgp_oid(*searched, state);
return SNMP_SEARCH_OK;
}
if (is_dynamic(state) && !is_dynamic(bgp_state))
{
for (uint i = 5; i < MIN(9, (*searched)->n_subid); i++)
(*searched)->ids[i] = 0;
r = snmp_bgp_search_dynamic(p, searched, o_end, contid, state);
if (r != SNMP_SEARCH_END_OF_VIEW)
return r;
}
if (is_dynamic(bgp_state))
{
r = snmp_bgp_search_dynamic(p, searched, o_end, contid, bgp_state);
if (r != SNMP_SEARCH_END_OF_VIEW)
return r;
}
state = snmp_bgp_next_state(bgp_state);
if (state <= BGP4_MIB_S_IDENTIFIER)
{
*searched = update_bgp_oid(*searched, state);
return SNMP_SEARCH_OK;
}
// TODO add route table
/* end not found */
return SNMP_SEARCH_END_OF_VIEW;
#endif
}
static void
bgp_fill_dynamic(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c, u8 state)
{
struct oid *oid = &(*vb)->name;
//byte *pkt;
ip4_addr addr;
if (oid_state_compare(oid, state) == 0 && snmp_bgp_valid_ip4(oid))
addr = ip4_from_oid(oid);
else
{
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
struct snmp_bgp_peer *pe = snmp_hash_find(p, addr);
if (!pe)
{
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
const struct bgp_proto *bgp_proto = pe->bgp_proto;
if (!ipa_is_ip4(bgp_proto->remote_ip))
{
log(L_ERR, "%s: Found BGP protocol instance with IPv6 address", bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR;
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
ip4_addr proto_ip = ipa_to_ip4(bgp_proto->remote_ip);
if (!ip4_equal(proto_ip, pe->peer_ip))
{
/* Here, we could be in problem as the bgp_proto IP address could be changed */
log(L_ERR, "%s: Stored hash key IP address and peer remote address differ.",
bgp_proto->p.name);
c->error = AGENTX_RES_GEN_ERROR;
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
return;
}
//const struct bgp_conn *bgp_conn = bgp_proto->conn;
//const struct bgp_stats *bgp_stats = &bgp_proto->stats;
const struct bgp_config *bgp_conf = bgp_proto->cf;
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
char last_error[2];
snmp_bgp_last_error(bgp_proto, last_error);
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
switch (state)
{
case BGP4_MIB_S_PEER_IDENTIFIER:
if (c->size < AGENTX_TYPE_IP4_SIZE)
{
snmp_log("BGP4-MIB small buffer");
snmp_manage_tbuf(p, c);
}
if (fsm_state == BGP4_MIB_OPENCONFIRM || fsm_state == BGP4_MIB_ESTABLISHED)
// TODO last
{} //snmp_varbind_ip4(*vb, c, ip4_from_u32(bgp_proto->remote_id));
else
{} //snmp_varbind_ip4(*vb, c, IP4_NONE);
break;
case BGP4_MIB_S_STATE:
if (c->size < AGENTX_TYPE_INT_SIZE)
{
snmp_log("BGP4-MIB small buffer 2");
snmp_manage_tbuf(p, c);
}
//snmp_varbind_int(*vb, c, fsm_state);
break;
case BGP4_MIB_S_ADMIN_STATUS:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
if (bgp_proto->p.disabled)
{} //snmp_varbind_int(*vb, c, AGENTX_ADMIN_STOP);
else
{} //snmp_varbind_int(*vb, c, AGENTX_ADMIN_START);
break;
case BGP4_MIB_S_NEGOTIATED_VERSION:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
uint fsm_state = snmp_bgp_fsm_state(bgp_proto);
if (fsm_state == BGP4_MIB_ESTABLISHED || fsm_state == BGP4_MIB_ESTABLISHED)
{} //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_VALUE);
else
{} //snmp_varbind_int(*vb, c, BGP4_MIB_NEGOTIATED_VER_NO_VALUE);
break;
case BGP4_MIB_S_LOCAL_ADDR:
if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->local_ip));
break;
case BGP4_MIB_S_LOCAL_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_int(*vb, c, bgp_conf->local_port);
break;
case BGP4_MIB_S_REMOTE_ADDR:
if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_ip4(*vb, c, ipa_to_ip4(bgp_proto->remote_ip));
break;
case BGP4_MIB_S_REMOTE_PORT:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_int(*vb, c, bgp_conf->remote_port);
break;
case BGP4_MIB_S_REMOTE_AS:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_int(*vb, c, bgp_proto->remote_as);
break;
case BGP4_MIB_S_RX_UPDATES: /* bgpPeerInUpdates */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_counter32(*vb, c, bgp_stats->rx_updates);
break;
case BGP4_MIB_S_TX_UPDATES: /* bgpPeerOutUpdate */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_counter32(*vb, c, bgp_stats->tx_updates);
break;
case BGP4_MIB_S_RX_MESSAGES: /* bgpPeerInTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_counter32(*vb, c, bgp_stats->rx_messages);
break;
case BGP4_MIB_S_TX_MESSAGES: /* bgpPeerOutTotalMessages */
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_counter32(*vb, c, bgp_stats->tx_messages);
break;
case BGP4_MIB_S_LAST_ERROR:
if (c->size < snmp_str_size_from_len(2))
SNMP_MANAGE_TBUF(p, vb, c);
{} //snmp_varbind_nstr(*vb, c, last_error, 2);
break;
case BGP4_MIB_S_FSM_TRANSITIONS:
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_counter32(*vb, c,
// bgp_stats->fsm_established_transitions);
break;
case BGP4_MIB_S_FSM_ESTABLISHED_TIME:
if (c->size < AGENTX_TYPE_COUNTER32_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_gauge32(*vb, c,
// (current_time() - bgp_proto->last_established) TO_S);
break;
case BGP4_MIB_S_RETRY_INTERVAL: /* retry inverval value should be != 0 */
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, bgp_conf->connect_retry_time);
break;
case BGP4_MIB_S_HOLD_TIME: /* hold time should be == 0 or in 3..65535 */
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, (bgp_conn) ? bgp_conn->hold_time : 0);
break;
case BGP4_MIB_S_KEEPALIVE:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
if (!bgp_conf->hold_time)
{} //snmp_varbind_int(*vb, c, 0);
else
{} //snmp_varbind_int(*vb, c,
// (bgp_conn) ? bgp_conn->keepalive_time : 0);
break;
case BGP4_MIB_S_HOLD_TIME_CONFIGURED:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, bgp_conf->hold_time);
break;
case BGP4_MIB_S_KEEPALIVE_CONFIGURED:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
if (!bgp_conf->keepalive_time)
{} //snmp_varbind_int(*vb, c, 0);
else
{} //snmp_varbind_int(*vb, c,
// (bgp_conn) ? bgp_conn->keepalive_time : 0);
break;
case BGP4_MIB_S_ORIGINATION_INTERVAL:
/* value should be in 1..65535 but is not supported by bird */
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, 0);
break;
case BGP4_MIB_S_MIN_ROUTE_ADVERTISEMENT:
/* value should be in 1..65535 but is not supported by bird */
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, 0);
break;
case BGP4_MIB_S_IN_UPDATE_ELAPSED_TIME:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_gauge32(*vb, c,
//(current_time() - bgp_proto->last_rx_update) TO_S
//);
break;
case BGP4_MIB_S_END:
break;
case BGP4_MIB_S_INVALID:
break;
case BGP4_MIB_S_BGP:
break;
case BGP4_MIB_S_PEER_TABLE:
break;
case BGP4_MIB_S_PEER_ENTRY:
break;
case BGP4_MIB_S_NO_VALUE:
break;
}
}
void
bgp_fill_static(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c, u8 state)
{
(void)p;
ASSUME(c->buffer == snmp_varbind_data(*vb));
struct oid *oid = &(*vb)->name;
/*
* snmp_bgp_state() check only prefix. To be sure on OID equivalence we need to
* compare the oid->n_subid length. All BGP static fields have same n_subid.
*/
if (oid_state_compare(oid, state) < 0 || state == BGP4_MIB_S_END)
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_OBJECT);
else if (oid_state_compare(oid, state) > 0)
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_INSTANCE);
switch (state)
{
case BGP4_MIB_S_VERSION:;
uint sz = snmp_str_size_from_len(1);
if (c->size < sz)
SNMP_MANAGE_TBUF(p, vb, c);
c->size -= sz;
//snmp_varbind_nstr(*vb, c, BGP4_VERSIONS, 1);
break;
case BGP4_MIB_S_LOCAL_AS:
if (c->size < AGENTX_TYPE_INT_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_int(*vb, c, p->bgp_local_as);
break;
case BGP4_MIB_S_IDENTIFIER:
if (c->size < AGENTX_TYPE_IP4_SIZE)
SNMP_MANAGE_TBUF(p, vb, c);
//snmp_varbind_ip4(*vb, c, p->bgp_local_id);
break;
default:
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_OBJECT);
break;
}
}
void
snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c)
{
ASSERT(vb != NULL);
u8 state = snmp_bgp_state(&((*vb)->name));
if (is_static(state))
{
bgp_fill_static(p, vb, c, state);
return;
}
if (is_dynamic(state))
{
bgp_fill_dynamic(p, vb, c, state);
return;
}
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_OBJECT);
}
/* /*
* bgp4_next_peer * bgp4_next_peer
*/ */
static int UNUSED static int
bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data) bgp4_next_peer(struct mib_walk_state *state, struct snmp_data *data)
{ {
//struct agentx_varbind *vb = data->c->sr_vb_start; //struct agentx_varbind *vb = data->c->sr_vb_start;

View File

@ -629,7 +629,7 @@ mib_tree_walk_to_oid(const struct mib_walk_state *walk, struct oid *result, u32
* return +1 if walk_oid > oid * return +1 if walk_oid > oid
* *
*/ */
// TODO tests // TODO tests, doc string
int int
mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *oid) mib_tree_walk_oid_compare(const struct mib_walk_state *walk, const struct oid *oid)
{ {

View File

@ -26,8 +26,6 @@ struct mib_node {
struct mib_walk_state; struct mib_walk_state;
//typedef enum snmp_search_res (*snmp_filler_hook_t)(struct mib_walk_state *state, struct snmp_data *data);
struct mib_leaf { struct mib_leaf {
struct mib_node_core c; struct mib_node_core c;
@ -99,7 +97,6 @@ struct mib_tree {
}; };
void mib_tree_init(pool *p, struct mib_tree *t); void mib_tree_init(pool *p, struct mib_tree *t);
// TODO: remove need for argument include_root
void mib_tree_walk_init(struct mib_walk_state *state, const struct mib_tree *t); void mib_tree_walk_init(struct mib_walk_state *state, const struct mib_tree *t);
int mib_tree_walk_to_oid(const struct mib_walk_state *state, struct oid *result, u32 subids); int mib_tree_walk_to_oid(const struct mib_walk_state *state, struct oid *result, u32 subids);
int mib_tree_walk_oid_compare(const struct mib_walk_state *state, const struct oid *oid); int mib_tree_walk_oid_compare(const struct mib_walk_state *state, const struct oid *oid);

View File

@ -119,6 +119,10 @@
#include "snmp_utils.h" #include "snmp_utils.h"
#include "mib_tree.h" #include "mib_tree.h"
// TODO: remove me
#include "proto/bgp/bgp.h"
static void snmp_start_locked(struct object_lock *lock); static void snmp_start_locked(struct object_lock *lock);
static void snmp_sock_err(sock *sk, int err); static void snmp_sock_err(sock *sk, int err);
static void snmp_stop_timeout(timer *tm); static void snmp_stop_timeout(timer *tm);

View File

@ -17,7 +17,6 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "filter/data.h" #include "filter/data.h"
#include "proto/bgp/bgp.h" // TODO remove me
#define SNMP_UNDEFINED 0 #define SNMP_UNDEFINED 0
#define SNMP_BGP 1 #define SNMP_BGP 1

View File

@ -107,7 +107,6 @@ snmp_is_oid_empty(const struct oid *oid)
/* We intentionaly ignore padding that should be zeroed */ /* We intentionaly ignore padding that should be zeroed */
if (oid != NULL) if (oid != NULL)
return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0; return LOAD_U8(oid->n_subid) == 0 && LOAD_U8(oid->prefix) == 0;
// && LOAD_U8(oid->include) == 0;
else else
return 0; return 0;
} }
@ -178,19 +177,6 @@ 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_update
*
*/
void
snmp_oid_update(struct oid *dest, const struct oid *src)
{
dest->prefix = src->prefix;
dest->include = src->include;
dest->reserved = 0;
memcpy(dest->ids, src->ids, MIN(dest->n_subid, src->n_subid) * sizeof(u32));
}
/* /*
* 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
@ -514,15 +500,6 @@ snmp_create_varbind(byte *buf, struct oid *oid)
return vb; return vb;
} }
#if 0
byte *
snmp_fix_varbind(struct agentx_varbind *vb, struct oid *new)
{
memcpy(&vb->name, new, snmp_oid_size(new));
return (void *) vb + snmp_varbind_header_size(vb);
}
#endif
/** /**
* snmp_oid_ip4_index - check IPv4 address validity in oid * snmp_oid_ip4_index - check IPv4 address validity in oid
* @o: object identifier holding ip address * @o: object identifier holding ip address
@ -675,7 +652,7 @@ int
snmp_oid_compare(const struct oid *left, const struct oid *right) snmp_oid_compare(const struct oid *left, const struct oid *right)
{ {
const u8 left_subids = LOAD_U8(left->n_subid); const u8 left_subids = LOAD_U8(left->n_subid);
u8 right_subids = LOAD_U8(right->n_subid); // see hack for more info u8 right_subids = LOAD_U8(right->n_subid); /* see hack for more info */
const u8 left_prefix = LOAD_U8(left->prefix); const u8 left_prefix = LOAD_U8(left->prefix);
const u8 right_prefix = LOAD_U8(right->prefix); const u8 right_prefix = LOAD_U8(right->prefix);
@ -764,7 +741,6 @@ snmp_registration_create(struct snmp_proto *p, u8 mib_class)
r->session_id = p->session_id; r->session_id = p->session_id;
/* will be incremented by snmp_session() macro during packet assembly */ /* will be incremented by snmp_session() macro during packet assembly */
r->transaction_id = p->transaction_id; r->transaction_id = p->transaction_id;
// TODO where is incremented? is this valid?
r->packet_id = p->packet_id + 1; r->packet_id = p->packet_id + 1;
snmp_log("using registration packet_id %u", r->packet_id); snmp_log("using registration packet_id %u", r->packet_id);
@ -873,7 +849,6 @@ snmp_varbind_ip4(struct snmp_pdu *c, ip4_addr addr)
c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr); c->buffer = snmp_put_ip4(snmp_varbind_data(c->sr_vb_start), addr);
} }
// TODO doc string, we have already the varbind prepared
inline byte * inline byte *
snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len) snmp_varbind_nstr2(struct snmp_pdu *c, uint size, const char *str, uint len)
{ {
@ -1180,7 +1155,6 @@ snmp_walk_fill(struct mib_leaf *leaf, struct mib_walk_state *walk, struct snmp_d
struct agentx_varbind *vb = data->c->sr_vb_start; struct agentx_varbind *vb = data->c->sr_vb_start;
if (!leaf) if (!leaf)
//if (!leaf || mib_tree_walk_is_oid_descendant(walk, &vb->name) < 0)
return SNMP_SEARCH_NO_OBJECT; return SNMP_SEARCH_NO_OBJECT;
uint size = 0; uint size = 0;

View File

@ -62,17 +62,12 @@
* *
*/ */
//static void snmp_mib_fill(struct snmp_proto *p, struct oid *oid, struct snmp_pdu *c);
static void snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c);
static uint parse_response(struct snmp_proto *p, byte *buf); static uint parse_response(struct snmp_proto *p, byte *buf);
static void do_response(struct snmp_proto *p, byte *buf); static void do_response(struct snmp_proto *p, byte *buf);
static uint parse_gets_pdu(struct snmp_proto *p, byte *pkt); static uint parse_gets_pdu(struct snmp_proto *p, byte *pkt);
static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c); static struct agentx_response *prepare_response(struct snmp_proto *p, struct snmp_pdu *c);
static void response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind); static void response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind);
static uint update_packet_size(struct agentx_header *start, byte *end); static uint update_packet_size(struct agentx_header *start, byte *end);
//static struct oid *search_mib2(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_end, struct oid *o_curr, struct snmp_pdu *c, enum snmp_search_res *result);
static enum snmp_search_res search_mib(struct snmp_proto *p, struct agentx_varbind **vb_search, const struct oid *o_end, struct snmp_pdu *c);
/* standard SNMP internet prefix (1.3.6.1) */ /* standard SNMP internet prefix (1.3.6.1) */
const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET }; const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
@ -254,7 +249,6 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
struct snmp_pdu c; struct snmp_pdu c;
snmp_pdu_context(&c, sk); snmp_pdu_context(&c, sk);
// TODO use more readable anonymous structure decl.
#define UPTIME_SIZE \ #define UPTIME_SIZE \
sizeof( struct { u32 vb_type; u32 oid_hdr; u32 ids[4]; } ) sizeof( struct { u32 vb_type; u32 oid_hdr; u32 ids[4]; } )
#define TRAP0_HEADER_SIZE \ #define TRAP0_HEADER_SIZE \
@ -431,7 +425,7 @@ snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 i
* *
* For more detailed description see un_register_pdu() function. * For more detailed description see un_register_pdu() function.
*/ */
void UNUSED 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, uint contid)
{ {
un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0, contid); un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0, contid);
@ -442,7 +436,7 @@ snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, ui
* @p: SNMP protocol instance * @p: SNMP protocol instance
* @reason: reason for closure * @reason: reason for closure
*/ */
static void UNUSED static void
close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason) close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
{ {
sock *sk = p->sock; sock *sk = p->sock;
@ -511,43 +505,6 @@ parse_close_pdu(struct snmp_proto *p, byte * const pkt_start)
} }
/*
* snmp_testset - check possibility of VarBind name and data setting
* @p: SNMP protocol instance
* @vb: checked VarBind
* @oid: pool-allocated prefixed copy of VarBind name
* @pkt_size: number of not parsed bytes in processed PDU
*
* Check done by specialized function for specific MIB subtree whether
* the VarBind is valid for set action (changing to current value to value
* in VarBind).
*
* Return 1 if the VarBind setting is possible, 0 otherwise.
*/
/* MUCH better signature would be
static int snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, uint pkt_size);
*/
static int UNUSED
snmp_testset(struct snmp_proto *p, const struct agentx_varbind *vb, struct oid *oid, uint pkt_size)
{
/* Hard-coded no support for writing */
(void)p;(void)vb;(void)oid;(void)pkt_size;
snmp_simple_response(p, AGENTX_RES_NOT_WRITABLE, 1);
return pkt_size + AGENTX_HEADER_SIZE;
#if 0
if (!oid)
return 0;
switch (oid->ids[1])
{
case SNMP_BGP4_MIB:
return snmp_bgp_testset(p, vb, oid, pkt_size);
default:
return 0;
}
#endif
}
/* /*
* refresh_ids - Copy current ids from packet to protocol * refresh_ids - Copy current ids from packet to protocol
* @p: SNMP protocol instance * @p: SNMP protocol instance
@ -578,7 +535,6 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
struct agentx_header *h = (void *) pkt; struct agentx_header *h = (void *) pkt;
pkt += AGENTX_HEADER_SIZE; pkt += AGENTX_HEADER_SIZE;
//uint pkt_size = LOAD_U32(h->payload);
sock *sk = p->sock; sock *sk = p->sock;
struct snmp_pdu c; struct snmp_pdu c;
@ -598,42 +554,6 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
* variables, when implementing the mentioned support, change the initializer * variables, when implementing the mentioned support, change the initializer
* to 1 * to 1
*/ */
#if 0
// TODO think about future value setting data structure
//struct agentx_transaction *tr = mb_alloc(...);
void *tr = mb_alloc(p->pool, 16);
struct agentx_varbind *vb;
uint sz;
while (size > 0 && all_possible)
{
vb = (void *) pkt;
sz = snmp_varbind_size(vb, size);
if (sz > pkt_size)
{
c.error = AGENTX_RES_PARSE_ERROR;
all_possible = 0;
break;
}
/* Unknown VarBind type check */
if (!snmp_test_varbind(vb))
{
c.error = AGENTX_RES_PARSE_ERROR;
all_possible = 0;
break;
}
ADVANCE(pkt, size, snmp_varbind_size(vb, size));
// TODO remove the mb_alloc() in prefixize()
struct oid *work = snmp_prefixize(p, &vb->name);
(void)work;
all_possible = snmp_testset(p, vb, tr, work, pkt_size);
mb_free(work);
}
mb_free(tr);
#endif
s = update_packet_size(h, c.buffer); s = update_packet_size(h, c.buffer);
if (c.error != AGENTX_RES_NO_ERROR) if (c.error != AGENTX_RES_NO_ERROR)
@ -678,7 +598,6 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0); snmp_simple_response(p, AGENTX_RES_PARSE_ERROR, 0);
// TODO best solution for possibly malicious pkt_size // TODO best solution for possibly malicious pkt_size
return AGENTX_HEADER_SIZE; return AGENTX_HEADER_SIZE;
// use varbind_list_size()??
} }
struct snmp_pdu c; struct snmp_pdu c;
@ -1036,285 +955,6 @@ snmp_get_mib_class(const struct oid *oid)
} }
} }
/*
* snmp_get_next - process single agentx-GetNext-PDU search range
* @p: SNMP protocol instance
* @o_start: SearchRange start OID
* @o_end: SearchRange end OID
* @c: transmit PDU context to use
*
* Return 0 if the created VarBind type is endOfMibView, 1 otherwise.
*/
// TODO remove me
static int UNUSED
snmp_get_next2(struct snmp_proto *p, struct agentx_varbind **vb_search, struct oid *o_end, struct snmp_pdu *c)
{
enum snmp_search_res r;
//struct oid *o_copy = search_mib(p, o_start, o_end, NULL, c, &r);
r = search_mib(p, vb_search, o_end, c);
struct oid *o_start = &(*vb_search)->name;
switch (r)
{
case SNMP_SEARCH_NO_OBJECT:
case SNMP_SEARCH_NO_INSTANCE:
case SNMP_SEARCH_END_OF_VIEW:;
snmp_set_varbind_type(*vb_search, AGENTX_END_OF_MIB_VIEW);
return 0;
case SNMP_SEARCH_OK:
default:
break;
}
// TODO TODO different API
snmp_mib_fill(p, vb_search, c);
/* override the error for GetNext-PDU object not find */
switch ((*vb_search)->type)
{
case AGENTX_NO_SUCH_OBJECT:
case AGENTX_NO_SUCH_INSTANCE:
case AGENTX_END_OF_MIB_VIEW:
(*vb_search)->type = AGENTX_END_OF_MIB_VIEW;
return 0;
default:
return 1;
}
o_start = &(*vb_search)->name;
if (c->size < snmp_varbind_hdr_size_from_oid(o_start))
{
snmp_log("get_next2 small buffer");
snmp_manage_tbuf(p, c);
}
snmp_set_varbind_type(*vb_search, AGENTX_END_OF_MIB_VIEW);
return 0;
}
#if 0
/*
* snmp_get_next - process single agentx-GetNext-PDU search range
* @p: SNMP protocol instance
* @o_start: SearchRange start OID
* @o_end: SearchRange end OID
* @c: transmit PDU context to use
*
* Return 0 if the created VarBind type is endOfMibView, 1 otherwise.
*/
static int
snmp_get_next3(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
struct snmp_pdu *c)
{
enum snmp_search_res r;
struct oid *o_copy = search_mib2(p, o_start, o_end, NULL, c, &r);
struct agentx_varbind *vb = NULL;
switch (r)
{
case SNMP_SEARCH_NO_OBJECT:
case SNMP_SEARCH_NO_INSTANCE:
case SNMP_SEARCH_END_OF_VIEW:;
uint sz = snmp_varbind_hdr_size_from_oid(o_start);
if (c->size < sz && c->size >= sizeof(struct agentx_varbind))
{
struct agentx_varbind *vb_null = snmp_create_varbind_null(c->buffer);
ADVANCE(c->buffer, c->size, snmp_varbind_size_unsafe(vb_null));
c->error = AGENTX_RES_GEN_ERROR;
return 0;
}
else if (c->size < sz)
{
c->error = AGENTX_RES_GEN_ERROR;
return 0;
}
vb = snmp_create_varbind(c->buffer, o_start);
vb->type = AGENTX_END_OF_MIB_VIEW;
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
return 0;
case SNMP_SEARCH_OK:
default:
break;
}
if (o_copy)
{
/* basicaly snmp_create_varbind(c->buffer, o_copy), but without any copying */
vb = (void *) c->buffer;
snmp_mib_fill(p, o_copy, c);
/* override the error for GetNext-PDU object not find */
switch (vb->type)
{
case AGENTX_NO_SUCH_OBJECT:
case AGENTX_NO_SUCH_INSTANCE:
case AGENTX_END_OF_MIB_VIEW:
vb->type = AGENTX_END_OF_MIB_VIEW;
return 0;
default:
return 1;
}
}
if (c->size < snmp_varbind_hdr_size_from_oid(o_start))
{
snmp_manage_tbuf(p, c);
}
vb = snmp_create_varbind(c->buffer, o_start);
vb->type = AGENTX_END_OF_MIB_VIEW;
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
return 0;
}
#endif
#if 0
/*
* snmp_get_bulk - process one iteration of get bulk PDU
* @p: SNMP protocol instance
* @o_start: SearchRange start OID
* @o_end: SearchRange end OID
* @state: state of get bulk PDU processing
* @c: transmit PDU context to use
*
* Return 0 if the created VarBind has type endOfMibView, 1 otherwise.
*/
static int
snmp_get_bulk2(struct snmp_proto *p, struct oid *o_start, struct oid *o_end,
struct agentx_bulk_state *state, struct snmp_pdu *c)
{
struct oid *o_curr = NULL;
struct oid *o_predecessor = NULL;
enum snmp_search_res r;
uint i = 0;
do
{
o_predecessor = o_curr;
o_curr = search_mib(p, o_start, o_end, o_curr, c, &r);
i++;
} while (o_curr && i < state->repetition);
// TODO check if the approach below works
// it need to generate varbinds that will be only of type endOfMibView
/* Object Identifier fall-backs */
if (!o_curr)
o_curr = o_predecessor;
if (!o_curr)
o_curr = o_start;
uint sz = snmp_varbind_hdr_size_from_oid(o_curr);
if (c->size < sz)
{
c->error = AGENTX_RES_GEN_ERROR;
return 0;
}
/* we need the varbind handle to be able to override it's type */
struct agentx_varbind *vb = (void *) c->buffer;
vb->type = AGENTX_END_OF_MIB_VIEW;
if (r == SNMP_SEARCH_OK)
/* the varbind will be recreated inside the snmp_mib_fill() */
snmp_mib_fill(p, o_curr, c);
else
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
/* override the error for GetBulk-PDU object not found */
switch (vb->type)
{
case AGENTX_NO_SUCH_OBJECT:
case AGENTX_NO_SUCH_INSTANCE:
case AGENTX_END_OF_MIB_VIEW:
vb->type = AGENTX_END_OF_MIB_VIEW;
return 0;
default:
return 1;
}
}
#endif
#if 0
static int
snmp_get_bulk2(struct snmp_proto *p, struct agentx_varbind **vb_search, const struct oid *o_end, struct agentx_bulk_state *state, struct snmp_pdu *c)
{
//struct oid *o_curr = NULL;
//struct oid *o_predecessor = NULL;
enum snmp_search_res r;
uint i = 0;
r = search_mib(p, vb_search, o_end, c);
while (r != SNMP_SEARCH_END_OF_VIEW && i < state->repetition)
{
snmp_mib_fill(p, vb_search, c);
snmp_varbind_duplicate_hdr(p, vb_search, c);
// renew all pointers here
r = search_mib(p, vb_search, o_end, c);
}
return r == SNMP_SEARCH_END_OF_VIEW;
do
{
r = search_mib(p, vb_search, o_end, c);
snmp_mib_fill(p, vb_search, ;
o_predecessor = o_curr;
o_curr = search_mib(p, o_start, o_end, o_curr, c, &r);
i++;
} while (r != SNMP_SEARCH_END_OF_VIEW && i < state->repetition);
// TODO check if the approach below works
// it need to generate varbinds that will be only of type endOfMibView
/* Object Identifier fall-backs */
if (!o_curr)
o_curr = o_predecessor;
if (!o_curr)
o_curr = o_start;
uint sz = snmp_varbind_hdr_size_from_oid(o_curr);
if (c->size < sz)
{
c->error = AGENTX_RES_GEN_ERROR;
return 0;
}
/* we need the varbind handle to be able to override it's type */
struct agentx_varbind *vb = (void *) c->buffer;
vb->type = AGENTX_END_OF_MIB_VIEW;
if (r == SNMP_SEARCH_OK)
/* the varbind will be recreated inside the snmp_mib_fill() */
snmp_mib_fill(p, o_curr, c);
else
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(vb));
/* override the error for GetBulk-PDU object not found */
switch (vb->type)
{
case AGENTX_NO_SUCH_OBJECT:
case AGENTX_NO_SUCH_INSTANCE:
case AGENTX_END_OF_MIB_VIEW:
vb->type = AGENTX_END_OF_MIB_VIEW;
return 0;
default:
return 1;
}
}
#endif
static inline struct oid * static inline struct oid *
snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src) snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
{ {
@ -1330,36 +970,6 @@ snmp_oid_prefixize_unsafe(struct oid *dest, const struct oid *src)
return dest; return dest;
} }
#if 0
/*
* snmp_oid_prefixize - convert oid to prefixed form
* @p: SNMP protocol instance
* @oid: object identifier to convert
* @c: PDU context
*
* The function assumes that the supplied @oid is prefixable. The resulting OID
* is allocated from PDU buffer inside @c.
*/
struct oid *
snmp_oid_prefixize(struct snmp_proto *p, const struct oid *oid, struct snmp_pdu *c)
{
/* It may be beneficial to move to snmp_utils.c */
uint subids = LOAD_U8(oid->n_subid) - 5;
uint oid_size = snmp_oid_size(oid);
if (c->size < oid_size)
{
snmp_manage_tbuf(p, c);
}
// TODO check if the @oid is prefixable
ASSERT(c->size >= oid_size);
struct oid *result = c->buffer;
ADVANCE(c->buffer, c->size, oid_size);
return snmp_oid_prefixize_unsafe(result, oid);
}
#endif
/* /*
* snmp_vb_to_tx - create varbind from RX buffer OID * snmp_vb_to_tx - create varbind from RX buffer OID
* @p: SNMP protocol instance * @p: SNMP protocol instance
@ -1646,26 +1256,14 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
{ {
case AGENTX_GET_PDU: case AGENTX_GET_PDU:
snmp_get_pdu(p, &c, start_rx, &walk); snmp_get_pdu(p, &c, start_rx, &walk);
//snmp_mib_fill(p, &vb_start, &c);
break; break;
case AGENTX_GET_NEXT_PDU: case AGENTX_GET_NEXT_PDU:
snmp_get_next_pdu(p, &c, start_rx, &walk); snmp_get_next_pdu(p, &c, start_rx, &walk);
//snmp_get_next2(p, &vb_start, o_end, &c);
break; break;
case AGENTX_GET_BULK_PDU: case AGENTX_GET_BULK_PDU:
snmp_get_bulk_pdu(p, &c, start_rx, &walk, &bulk_state); snmp_get_bulk_pdu(p, &c, start_rx, &walk, &bulk_state);
#if 0
if (c.index >= bulk_state.getbulk.non_repeaters)
bulk_state.repeaters++;
// store the o_start, o_end
/* The behavior of GetBulk pdu in the first iteration is
* identical to GetNext pdu. */
has_any = snmp_get_next2(p, &vb_start, o_end, &c) || has_any;
#endif
break; break;
default: default:
@ -1682,19 +1280,6 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
if (h->type == AGENTX_GET_BULK_PDU) if (h->type == AGENTX_GET_BULK_PDU)
{ {
#if 0
// TODO
for (bulk_state.repetition++;
has_any && bulk_state.repetition < bulk_state.getbulk.max_repetitions;
bulk_state.repetition++)
{
vb_start = snmp_vb_copy_to_tx(p, vb_start, &c);
has_any = 0;
for (bulk_state.index = 0; bulk_state.index < bulk_state.repeaters;
bulk_state.repeaters++)
has_any = snmp_get_bulk2(p, &vb_start, end, &bulk_state, &c) || has_any;
}
#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. */
@ -1739,7 +1324,7 @@ snmp_stop_subagent(struct snmp_proto *p)
{ {
tm_stop(p->ping_timer); tm_stop(p->ping_timer);
/* This cause problems with net-snmp daemon witch halts afterwards */ /* This cause problems with net-snmp daemon witch halts afterwards */
//close_pdu(p, AGENTX_CLOSE_SHUTDOWN); close_pdu(p, AGENTX_CLOSE_SHUTDOWN);
} }
/* /*
@ -1820,7 +1405,6 @@ snmp_ping(struct snmp_proto *p)
if (unused < AGENTX_HEADER_SIZE) if (unused < AGENTX_HEADER_SIZE)
return; return;
//struct agentx_header *h = (void *) sk->tpos;
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);
snmp_blank_header(h, AGENTX_PING_PDU); snmp_blank_header(h, AGENTX_PING_PDU);
@ -1852,248 +1436,6 @@ snmp_search_check_end_oid(const struct oid *found, const struct oid *bound)
return (snmp_oid_compare(found, bound) < 0); return (snmp_oid_compare(found, bound) < 0);
} }
/*
* search_mib - search for successor of given OID
* @p: SNMP protocol instance
* @o_start: search starting OID
* @o_end: search ending OID
* @o_curr: current OID inside @o_start, @o_end interval
* @c: transmit PDU context to use
* @result: search result state
*
* Perform a search in MIB tree in SearchRange from @o_start to @o_end.
* If the @o_start has set include the search is inclusive, the @o_end has
* always the include flag cleared. For agentx-GetNext-PDU, the o_curr is always
* NULL, for agentx-GetBulk-PDU it could have non-NULL value. In such case the
* @o_curr effectively replaces the role of @o_start. It is mandatory to pass
* @o_start and @o_end only allocated from @p protocol's memory pool.
*
* Return found OID or NULL.
*/
/* tree is tree with "internet" prefix .1.3.6.1
working only with o_start, o_end allocated in heap (not from buffer)*/
static enum snmp_search_res
search_mib(struct snmp_proto *p, struct agentx_varbind **vb_search, const struct oid *o_end, struct snmp_pdu *c)
{
ASSUME(vb_search != NULL);
struct oid *o_start = &(*vb_search)->name;
ASSUME(o_start != NULL);
(void)p;
(void)o_end;
(void)c;
// TODO TODO
#if 0
enum snmp_search_res r;
switch (o_curr->ids[1])
{
case SNMP_BGP4_MIB:
r = snmp_bgp_search(p, &o_curr, o_end, 0);
if (r == SNMP_SEARCH_OK)
{
*result = r;
break;
return o_curr;
}
// TODO add early break for o_end less then thinkable maximum in each tree
/* fall through */
default:
if (o_curr) mb_free(o_curr);
o_curr = snmp_oid_duplicate(p->pool, o_start);
*result = SNMP_SEARCH_END_OF_VIEW;
break;
}
if (o_end == blank)
/* cast drops const qualifier */
mb_free((struct oid *)blank);
return o_curr;
#endif
return SNMP_SEARCH_NO_OBJECT;
}
/*
* search_mib - search for successor of given OID
* @p: SNMP protocol instance
* @o_start: search starting OID
* @o_end: search ending OID
* @o_curr: current OID inside @o_start, @o_end interval
* @c: transmit PDU context to use
* @result: search result state
*
* Perform a search in MIB tree in SearchRange from @o_start to @o_end.
* If the @o_start has set include the search is inclusive, the @o_end has
* always the include flag cleared. For agentx-GetNext-PDU, the o_curr is always
* NULL, for agentx-GetBulk-PDU it could have non-NULL value. In such case the
* @o_curr effectively replaces the role of @o_start. It is mandatory to pass
* @o_start and @o_end only allocated from @p protocol's memory pool.
*
* Return found OID or NULL.
*/
/* tree is tree with "internet" prefix .1.3.6.1
working only with o_start, o_end allocated in heap (not from buffer)*/
#if 0
static struct oid *
search_mib2(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_end,
struct oid *o_curr, struct snmp_pdu UNUSED *c,
enum snmp_search_res *result)
{
// TODO flip retval and result (maybe on more place to stay consistent)
// TODO remove unnecessary o_start/o_curr duplication
ASSUME(o_start != NULL);
if (o_curr && (o_curr->n_subid < 2 || o_curr->ids[0] != 1))
return NULL;
if (!o_curr && (o_start->n_subid < 2 || o_start->ids[0] != 1))
return NULL;
if (!o_curr)
{
o_curr = snmp_oid_duplicate(p->pool, o_start);
// XXX is it right time to free o_start right now (here) ?
// not for use in snmp_get_next2() the o_start comes and ends in _gets_()
}
const struct oid *blank = NULL;
if (!snmp_is_oid_empty(o_end) &&
snmp_get_mib_class(o_curr) < snmp_get_mib_class(o_end))
{
o_end = blank = snmp_oid_blank(p);
}
enum snmp_search_res r;
switch (o_curr->ids[1])
{
case SNMP_BGP4_MIB:
r = snmp_bgp_search(p, &o_curr, o_end, 0);
if (r == SNMP_SEARCH_OK)
{
*result = r;
break;
return o_curr;
}
// TODO add early break for o_end less then thinkable maximum in each tree
/* fall through */
default:
if (o_curr) mb_free(o_curr);
o_curr = snmp_oid_duplicate(p->pool, o_start);
*result = SNMP_SEARCH_END_OF_VIEW;
break;
}
if (o_end == blank)
/* cast drops const qualifier */
mb_free((struct oid *)blank);
return o_curr;
}
#endif
#if 0
/**
* snmp_prefixize - return prefixed OID copy if possible
* @proto: allocation pool holder
* @oid: from packet loaded object identifier
*
* Return prefixed (meaning with nonzero prefix field) oid copy of @oid if
* possible, NULL otherwise. Returned pointer is always allocated from @proto's
* pool not a pointer to RX-buffer (from which is most likely @oid).
*/
struct oid *
snmp_prefixize(struct snmp_proto *proto, const struct oid *oid)
{
ASSUME(oid != NULL);
if (snmp_is_oid_empty(oid))
{
/* allocate new zeroed oid */
return snmp_oid_blank(proto);
}
/* already in prefixed form */
else if (oid->prefix != 0) {
struct oid *new = snmp_oid_duplicate(proto->pool, oid);
return new;
}
if (oid->n_subid < 5)
return NULL;
for (int i = 0; i < 4; i++)
if (LOAD_U32(oid->ids[i]) != snmp_internet[i])
return NULL;
/* validity check here */
if (oid->ids[4] >= 256)
return NULL;
struct oid *new = mb_alloc(proto->pool,
sizeof(struct oid) + MAX((oid->n_subid - 5) * sizeof(u32), 0));
memcpy(new, oid, sizeof(struct oid));
new->n_subid = oid->n_subid - 5;
/* validity check before allocation => ids[4] < 256
and can be copied to one byte new->prefix */
new->prefix = oid->ids[4];
memcpy(&new->ids, &oid->ids[5], new->n_subid * sizeof(u32));
return new;
}
#endif
/*
* snmp_mib_fill - append a AgentX VarBind to PDU
* @p: SNMP protocol instance
* @vb: indirect pointer to destination varbind
* @c: transmit PDU context to use
*
* Append new AgentX VarBind at the end of created PDU. The content (v.data)
* is handled in function specialized for given MIB subtree. The binding is
* created only if the v.name matches some variable name precisely.
*/
static void
snmp_mib_fill(struct snmp_proto *p, struct agentx_varbind **vb, struct snmp_pdu *c)
{
(void) p;
ASSUME(vb != NULL && *vb != NULL);
struct oid *oid = &((*vb)->name);
if (oid->n_subid < 2 || (oid->prefix != SNMP_MGMT && oid->ids[0] != SNMP_MIB_2))
{
snmp_set_varbind_type(*vb, AGENTX_NO_SUCH_OBJECT);
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(*vb));
return;
}
u8 mib_class = snmp_get_mib_class(oid);
switch (mib_class)
{
case SNMP_CLASS_BGP:
//snmp_bgp_fill(p, vb, c);
break;
case SNMP_CLASS_INVALID:
case SNMP_CLASS_END:
default:
break;
(*vb)->type = AGENTX_NO_SUCH_OBJECT;
ADVANCE(c->buffer, c->size, snmp_varbind_header_size(*vb));
}
}
/* /*
* snmp_manage_tbuf - TODO * snmp_manage_tbuf - TODO
*/ */

View File

@ -338,16 +338,6 @@ struct snmp_packet_info {
void *data; void *data;
}; };
#if 0
struct agentx_alloc_context {
u8 is_instance; /* flag INSTANCE_REGISTRATION */
u8 new_index; /* flag NEW_INDEX */
u8 any_index; /* flag ANY_INDEX */
char *context; /* context to allocate in */
uint clen; /* length of context string */
};
#endif
int snmp_rx(sock *sk, uint size); int snmp_rx(sock *sk, uint size);
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_down(struct snmp_proto *p);